diff options
Diffstat (limited to 'dex/src')
-rw-r--r-- | dex/src/main/java/com/android/dex/Code.java | 22 | ||||
-rw-r--r-- | dex/src/main/java/com/android/dex/Dex.java | 109 | ||||
-rw-r--r-- | dex/src/main/java/com/android/dex/SizeOf.java | 7 |
3 files changed, 99 insertions, 39 deletions
diff --git a/dex/src/main/java/com/android/dex/Code.java b/dex/src/main/java/com/android/dex/Code.java index 8a9b885..9258af7 100644 --- a/dex/src/main/java/com/android/dex/Code.java +++ b/dex/src/main/java/com/android/dex/Code.java @@ -67,12 +67,12 @@ public final class Code { public static class Try { final int startAddress; final int instructionCount; - final int handlerOffset; + final int catchHandlerIndex; - Try(int startAddress, int instructionCount, int handlerOffset) { + Try(int startAddress, int instructionCount, int catchHandlerIndex) { this.startAddress = startAddress; this.instructionCount = instructionCount; - this.handlerOffset = handlerOffset; + this.catchHandlerIndex = catchHandlerIndex; } public int getStartAddress() { @@ -83,8 +83,12 @@ public final class Code { return instructionCount; } - public int getHandlerOffset() { - return handlerOffset; + /** + * Returns this try's catch handler <strong>index</strong>. Note that + * this is distinct from the its catch handler <strong>offset</strong>. + */ + public int getCatchHandlerIndex() { + return catchHandlerIndex; } } @@ -92,11 +96,13 @@ public final class Code { final int[] typeIndexes; final int[] addresses; final int catchAllAddress; + final int offset; - public CatchHandler(int[] typeIndexes, int[] addresses, int catchAllAddress) { + public CatchHandler(int[] typeIndexes, int[] addresses, int catchAllAddress, int offset) { this.typeIndexes = typeIndexes; this.addresses = addresses; this.catchAllAddress = catchAllAddress; + this.offset = offset; } public int[] getTypeIndexes() { @@ -110,5 +116,9 @@ public final class Code { public int getCatchAllAddress() { return catchAllAddress; } + + public int getOffset() { + return offset; + } } } diff --git a/dex/src/main/java/com/android/dex/Dex.java b/dex/src/main/java/com/android/dex/Dex.java index e6bee68..29cd30e 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. */ diff --git a/dex/src/main/java/com/android/dex/SizeOf.java b/dex/src/main/java/com/android/dex/SizeOf.java index 03b40bd..65fab56 100644 --- a/dex/src/main/java/com/android/dex/SizeOf.java +++ b/dex/src/main/java/com/android/dex/SizeOf.java @@ -100,4 +100,11 @@ public final class SizeOf { * offset uint */ public static final int MAP_ITEM = USHORT + USHORT + UINT + UINT; + + /** + * start_addr uint + * insn_count ushort + * handler_off ushort + */ + public static final int TRY_ITEM = UINT + USHORT + USHORT; } |