diff options
Diffstat (limited to 'dx/src/com/android/dx/io/DexBuffer.java')
-rw-r--r-- | dx/src/com/android/dx/io/DexBuffer.java | 75 |
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. */ |