diff options
Diffstat (limited to 'dex/src/main/java/com/android/dex/Dex.java')
-rw-r--r-- | dex/src/main/java/com/android/dex/Dex.java | 109 |
1 files changed, 76 insertions, 33 deletions
diff --git a/dex/src/main/java/com/android/dex/Dex.java b/dex/src/main/java/com/android/dex/Dex.java index e6bee6847..29cd30ea7 100644 --- a/dex/src/main/java/com/android/dex/Dex.java +++ b/dex/src/main/java/com/android/dex/Dex.java @@ -16,9 +16,12 @@ package com.android.dex; +import com.android.dex.Code.CatchHandler; +import com.android.dex.Code.Try; import com.android.dex.util.ByteInput; import com.android.dex.util.ByteOutput; import com.android.dex.util.FileUtils; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -546,41 +549,74 @@ public final class Dex { 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(); - } - } - return new Code(registersSize, insSize, outsSize, debugInfoOffset, instructions, - tries, catchHandlers); - } - - private Code.CatchHandler readCatchHandler() { - int size = readSleb128(); - int handlersCount = Math.abs(size); - int[] typeIndexes = new int[handlersCount]; - int[] addresses = new int[handlersCount]; - for (int i = 0; i < handlersCount; i++) { - typeIndexes[i] = readUleb128(); - addresses[i] = readUleb128(); + if (instructions.length % 2 == 1) { + readShort(); // padding + } + + /* + * 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(data.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 CatchHandler[] readCatchHandlers() { + int baseOffset = data.position(); + int catchHandlersSize = readUleb128(); + CatchHandler[] result = new CatchHandler[catchHandlersSize]; + for (int i = 0; i < catchHandlersSize; i++) { + int offset = data.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; } - int catchAllAddress = size <= 0 ? readUleb128() : -1; - return new Code.CatchHandler(typeIndexes, addresses, catchAllAddress); + } + throw new IllegalArgumentException(); + } + + private CatchHandler readCatchHandler(int offset) { + int size = readSleb128(); + int handlersCount = Math.abs(size); + int[] typeIndexes = new int[handlersCount]; + int[] addresses = new int[handlersCount]; + for (int i = 0; i < handlersCount; i++) { + typeIndexes[i] = readUleb128(); + addresses[i] = readUleb128(); + } + int catchAllAddress = size <= 0 ? readUleb128() : -1; + return new CatchHandler(typeIndexes, addresses, catchAllAddress, offset); } private ClassData readClassData() { @@ -643,6 +679,13 @@ public final class Dex { return new EncodedValue(getBytesFrom(start)); } + public void skip(int count) { + if (count < 0) { + throw new IllegalArgumentException(); + } + data.position(data.position() + count); + } + /** * Skips bytes until the position is aligned to a multiple of 4. */ |