summaryrefslogtreecommitdiffstats
path: root/dex
diff options
context:
space:
mode:
Diffstat (limited to 'dex')
-rw-r--r--dex/src/main/java/com/android/dex/Code.java22
-rw-r--r--dex/src/main/java/com/android/dex/Dex.java109
-rw-r--r--dex/src/main/java/com/android/dex/SizeOf.java7
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;
}