summaryrefslogtreecommitdiffstats
path: root/dx/src/com/android/dx/io/DexBuffer.java
diff options
context:
space:
mode:
Diffstat (limited to 'dx/src/com/android/dx/io/DexBuffer.java')
-rw-r--r--dx/src/com/android/dx/io/DexBuffer.java75
1 files changed, 59 insertions, 16 deletions
diff --git a/dx/src/com/android/dx/io/DexBuffer.java b/dx/src/com/android/dx/io/DexBuffer.java
index 39e5858e6..9fbc78cac 100644
--- a/dx/src/com/android/dx/io/DexBuffer.java
+++ b/dx/src/com/android/dx/io/DexBuffer.java
@@ -19,6 +19,8 @@ package com.android.dx.io;
import com.android.dx.dex.DexFormat;
import com.android.dx.dex.SizeOf;
import com.android.dx.dex.TableOfContents;
+import com.android.dx.io.Code.CatchHandler;
+import com.android.dx.io.Code.Try;
import com.android.dx.merge.TypeList;
import com.android.dx.util.ByteInput;
import com.android.dx.util.ByteOutput;
@@ -443,31 +445,64 @@ public final class DexBuffer {
int debugInfoOffset = readInt();
int instructionsSize = readInt();
short[] instructions = readShortArray(instructionsSize);
- Code.Try[] tries = new Code.Try[triesSize];
- Code.CatchHandler[] catchHandlers = new Code.CatchHandler[0];
+ Try[] tries;
+ CatchHandler[] catchHandlers;
if (triesSize > 0) {
if (instructions.length % 2 == 1) {
readShort(); // padding
}
- for (int i = 0; i < triesSize; i++) {
- int startAddress = readInt();
- int instructionCount = readUnsignedShort();
- int handlerOffset = readUnsignedShort();
- tries[i] = new Code.Try(startAddress, instructionCount, handlerOffset);
- }
-
- int catchHandlersSize = readUleb128();
- catchHandlers = new Code.CatchHandler[catchHandlersSize];
- for (int i = 0; i < catchHandlersSize; i++) {
- catchHandlers[i] = readCatchHandler();
- }
+ /*
+ * We can't read the tries until we've read the catch handlers.
+ * Unfortunately they're in the opposite order in the dex file
+ * so we need to read them out-of-order.
+ */
+ Section triesSection = open(position);
+ skip(triesSize * SizeOf.TRY_ITEM);
+ catchHandlers = readCatchHandlers();
+ tries = triesSection.readTries(triesSize, catchHandlers);
+ } else {
+ tries = new Try[0];
+ catchHandlers = new CatchHandler[0];
}
return new Code(registersSize, insSize, outsSize, debugInfoOffset, instructions,
tries, catchHandlers);
}
- private Code.CatchHandler readCatchHandler() {
+ private CatchHandler[] readCatchHandlers() {
+ int baseOffset = position;
+ int catchHandlersSize = readUleb128();
+ CatchHandler[] result = new CatchHandler[catchHandlersSize];
+ for (int i = 0; i < catchHandlersSize; i++) {
+ int offset = position - baseOffset;
+ result[i] = readCatchHandler(offset);
+ }
+ return result;
+ }
+
+ private Try[] readTries(int triesSize, CatchHandler[] catchHandlers) {
+ Try[] result = new Try[triesSize];
+ for (int i = 0; i < triesSize; i++) {
+ int startAddress = readInt();
+ int instructionCount = readUnsignedShort();
+ int handlerOffset = readUnsignedShort();
+ int catchHandlerIndex = findCatchHandlerIndex(catchHandlers, handlerOffset);
+ result[i] = new Try(startAddress, instructionCount, catchHandlerIndex);
+ }
+ return result;
+ }
+
+ private int findCatchHandlerIndex(CatchHandler[] catchHandlers, int offset) {
+ for (int i = 0; i < catchHandlers.length; i++) {
+ CatchHandler catchHandler = catchHandlers[i];
+ if (catchHandler.getOffset() == offset) {
+ return i;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+
+ private CatchHandler readCatchHandler(int offset) {
int size = readSleb128();
int handlersCount = Math.abs(size);
int[] typeIndexes = new int[handlersCount];
@@ -477,7 +512,7 @@ public final class DexBuffer {
addresses[i] = readUleb128();
}
int catchAllAddress = size <= 0 ? readUleb128() : -1;
- return new Code.CatchHandler(typeIndexes, addresses, catchAllAddress);
+ return new CatchHandler(typeIndexes, addresses, catchAllAddress, offset);
}
private ClassData readClassData() {
@@ -548,6 +583,14 @@ public final class DexBuffer {
}
}
+ public void skip(int count) {
+ if (count < 0) {
+ throw new IllegalArgumentException();
+ }
+ ensureCapacity(count);
+ position += count;
+ }
+
/**
* Writes 0x00 until the position is aligned to a multiple of 4.
*/