diff --git a/baksmali/src/main/java/org/jf/baksmali/Deodex/DeodexUtil.java b/baksmali/src/main/java/org/jf/baksmali/Deodex/DeodexUtil.java index 70c22d48..515511ea 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Deodex/DeodexUtil.java +++ b/baksmali/src/main/java/org/jf/baksmali/Deodex/DeodexUtil.java @@ -39,103 +39,6 @@ import java.util.*; public class DeodexUtil { private final Deodexerant deodexerant; - //a table that reflects which instructions can throw an exception - public static final BitSet instructionThrowTable = new BitSet(256); - - { - //mark the instructions that can throw an exception - instructionThrowTable.set(Opcode.CONST_STRING.value & 0xFF); - instructionThrowTable.set(Opcode.CONST_STRING_JUMBO.value & 0xFF); - instructionThrowTable.set(Opcode.CONST_CLASS.value & 0xFF); - instructionThrowTable.set(Opcode.MONITOR_ENTER.value & 0xFF); - instructionThrowTable.set(Opcode.MONITOR_EXIT.value & 0xFF); - instructionThrowTable.set(Opcode.CHECK_CAST.value & 0xFF); - instructionThrowTable.set(Opcode.INSTANCE_OF.value & 0xFF); - instructionThrowTable.set(Opcode.ARRAY_LENGTH.value & 0xFF); - instructionThrowTable.set(Opcode.NEW_INSTANCE.value & 0xFF); - instructionThrowTable.set(Opcode.NEW_ARRAY.value & 0xFF); - instructionThrowTable.set(Opcode.FILLED_NEW_ARRAY.value & 0xFF); - instructionThrowTable.set(Opcode.FILLED_NEW_ARRAY_RANGE.value & 0xFF); - instructionThrowTable.set(Opcode.AGET.value & 0xFF); - instructionThrowTable.set(Opcode.AGET_BOOLEAN.value & 0xFF); - instructionThrowTable.set(Opcode.AGET_BYTE.value & 0xFF); - instructionThrowTable.set(Opcode.AGET_CHAR.value & 0xFF); - instructionThrowTable.set(Opcode.AGET_SHORT.value & 0xFF); - instructionThrowTable.set(Opcode.AGET_WIDE.value & 0xFF); - instructionThrowTable.set(Opcode.AGET_OBJECT.value & 0xFF); - instructionThrowTable.set(Opcode.APUT.value & 0xFF); - instructionThrowTable.set(Opcode.APUT_BOOLEAN.value & 0xFF); - instructionThrowTable.set(Opcode.APUT_BYTE.value & 0xFF); - instructionThrowTable.set(Opcode.APUT_CHAR.value & 0xFF); - instructionThrowTable.set(Opcode.APUT_SHORT.value & 0xFF); - instructionThrowTable.set(Opcode.APUT_WIDE.value & 0xFF); - instructionThrowTable.set(Opcode.APUT_OBJECT.value & 0xFF); - instructionThrowTable.set(Opcode.IGET.value & 0xFF); - instructionThrowTable.set(Opcode.IGET_BOOLEAN.value & 0xFF); - instructionThrowTable.set(Opcode.IGET_BYTE.value & 0xFF); - instructionThrowTable.set(Opcode.IGET_CHAR.value & 0xFF); - instructionThrowTable.set(Opcode.IGET_SHORT.value & 0xFF); - instructionThrowTable.set(Opcode.IGET_WIDE.value & 0xFF); - instructionThrowTable.set(Opcode.IGET_OBJECT.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT_BOOLEAN.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT_BYTE.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT_CHAR.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT_SHORT.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT_WIDE.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT_OBJECT.value & 0xFF); - instructionThrowTable.set(Opcode.SGET.value & 0xFF); - instructionThrowTable.set(Opcode.SGET_BOOLEAN.value & 0xFF); - instructionThrowTable.set(Opcode.SGET_BYTE.value & 0xFF); - instructionThrowTable.set(Opcode.SGET_CHAR.value & 0xFF); - instructionThrowTable.set(Opcode.SGET_SHORT.value & 0xFF); - instructionThrowTable.set(Opcode.SGET_WIDE.value & 0xFF); - instructionThrowTable.set(Opcode.SGET_OBJECT.value & 0xFF); - instructionThrowTable.set(Opcode.SPUT.value & 0xFF); - instructionThrowTable.set(Opcode.SPUT_BOOLEAN.value & 0xFF); - instructionThrowTable.set(Opcode.SPUT_BYTE.value & 0xFF); - instructionThrowTable.set(Opcode.SPUT_CHAR.value & 0xFF); - instructionThrowTable.set(Opcode.SPUT_SHORT.value & 0xFF); - instructionThrowTable.set(Opcode.SPUT_WIDE.value & 0xFF); - instructionThrowTable.set(Opcode.SPUT_OBJECT.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_VIRTUAL.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_VIRTUAL_RANGE.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_SUPER.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_SUPER_RANGE.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_DIRECT.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_DIRECT_RANGE.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_STATIC.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_STATIC_RANGE.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_INTERFACE.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_INTERFACE_RANGE.value & 0xFF); - instructionThrowTable.set(Opcode.DIV_INT.value & 0xFF); - instructionThrowTable.set(Opcode.REM_INT.value & 0xFF); - instructionThrowTable.set(Opcode.DIV_LONG.value & 0xFF); - instructionThrowTable.set(Opcode.REM_LONG.value & 0xFF); - instructionThrowTable.set(Opcode.DIV_INT_2ADDR.value & 0xFF); - instructionThrowTable.set(Opcode.REM_INT_2ADDR.value & 0xFF); - instructionThrowTable.set(Opcode.DIV_LONG_2ADDR.value & 0xFF); - instructionThrowTable.set(Opcode.REM_LONG_2ADDR.value & 0xFF); - instructionThrowTable.set(Opcode.DIV_INT_LIT16.value & 0xFF); - instructionThrowTable.set(Opcode.REM_INT_LIT16.value & 0xFF); - instructionThrowTable.set(Opcode.DIV_INT_LIT8.value & 0xFF); - instructionThrowTable.set(Opcode.REM_INT_LIT8.value & 0xFF); - instructionThrowTable.set(Opcode.THROW.value & 0xFF); - instructionThrowTable.set(Opcode.EXECUTE_INLINE.value & 0xFF); - instructionThrowTable.set(Opcode.EXECUTE_INLINE_RANGE.value & 0xFF); - instructionThrowTable.set(Opcode.IGET_QUICK.value & 0xFF); - instructionThrowTable.set(Opcode.IGET_WIDE_QUICK.value & 0xFF); - instructionThrowTable.set(Opcode.IGET_OBJECT_QUICK.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT_QUICK.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT_WIDE_QUICK.value & 0xFF); - instructionThrowTable.set(Opcode.IPUT_OBJECT_QUICK.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_VIRTUAL_QUICK.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_VIRTUAL_QUICK_RANGE.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_SUPER_QUICK.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_SUPER_QUICK_RANGE.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_DIRECT_EMPTY.value & 0xFF); - } - public DeodexUtil(Deodexerant deodexerant) { this.deodexerant = deodexerant; deodexerant.dexFile.disableInterning(); @@ -203,7 +106,7 @@ public class DeodexUtil { didSomething = false; somethingLeftToDo = false; for (insn i: insns) { - if (i.instruction.opcode.odexOnly && i.fixedInstruction == null) { + if (i.instruction.opcode.odexOnly() && i.fixedInstruction == null) { if (deodexInstruction(i)) { didSomething = true; } else { @@ -227,7 +130,7 @@ public class DeodexUtil { } else { instructions.add(new DeadInstruction(i.instruction)); } - } else if (i.instruction.opcode.odexOnly) { + } else if (i.instruction.opcode.odexOnly()) { assert i.fixedInstruction != null; instructions.add(i.fixedInstruction); } else { @@ -840,10 +743,6 @@ public class DeodexUtil { * The code address of the instruction, in 2-byte instruction blocks */ public final int address; - /** - * True if this instruction can throw an exception - */ - public final boolean canThrow; /** * maps a code address to an insn @@ -935,10 +834,9 @@ public class DeodexUtil { this.codeItem = codeItem; this.instruction = instruction; this.address = address; - this.canThrow = DeodexUtil.instructionThrowTable.get(instruction.opcode.value & 0xFF); this.insnsMap = insnsMap; - if (instruction.opcode.odexOnly) { + if (instruction.opcode.odexOnly()) { //we don't need INVOKE_EXECUTE_INLINE or EXECUTE_INLINE_RANGE here, because we don't need to know //the type of the object register in order to resolve which method is being called switch (instruction.opcode) { @@ -1304,7 +1202,7 @@ public class DeodexUtil { //if the next instruction can throw an exception, and is covered by exception handlers, //then the execution can in effect go directly from this instruction into the handler - if (i.canThrow && i.exceptionHandlers != null) { + if (i.instruction.opcode.canThrow() && i.exceptionHandlers != null) { for (insn handler: i.exceptionHandlers) { addSuccessor(handler); } @@ -1375,7 +1273,7 @@ public class DeodexUtil { } } - if (exceptionHandlers != null && canThrow) { + if (exceptionHandlers != null && instruction.opcode.canThrow()) { for (insn handlerinsn: exceptionHandlers) { handlerinsn.initializeRegistersFromParams(); } @@ -1425,7 +1323,7 @@ public class DeodexUtil { //if this is the first instruction, we're in a try block, then if the first instruction throws an //exception, execution could go directly into one of the handlers. We need to handle this recursively, //i.e. if the first instruction in the exception handler is also covered by a try block.. - if (this.firstInstruction && canThrow && exceptionHandlers != null) { + if (this.firstInstruction && instruction.opcode.canThrow() && exceptionHandlers != null) { for (insn handler: exceptionHandlers) { handler.propagateRegisters(); } diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java b/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java index 8d456057..7f0d3f80 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java @@ -60,20 +60,20 @@ public enum Opcode CONST_WIDE_32((byte)0x17, "const-wide/32", ReferenceType.none, Format.Format31i), CONST_WIDE((byte)0x18, "const-wide", ReferenceType.none, Format.Format51l), CONST_WIDE_HIGH16((byte)0x19, "const-wide/high16", ReferenceType.none, Format.Format21h), - CONST_STRING((byte)0x1a, "const-string", ReferenceType.string, Format.Format21c), - CONST_STRING_JUMBO((byte)0x1b, "const-string/jumbo", ReferenceType.string, Format.Format31c), - CONST_CLASS((byte)0x1c, "const-class", ReferenceType.type, Format.Format21c), - MONITOR_ENTER((byte)0x1d, "monitor-enter", ReferenceType.none, Format.Format11x), - MONITOR_EXIT((byte)0x1e, "monitor-exit", ReferenceType.none, Format.Format11x), - CHECK_CAST((byte)0x1f, "check-cast", ReferenceType.type, Format.Format21c), - INSTANCE_OF((byte)0x20, "instance-of", ReferenceType.type, Format.Format22c), - ARRAY_LENGTH((byte)0x21, "array-length", ReferenceType.none, Format.Format12x), - NEW_INSTANCE((byte)0x22, "new-instance", ReferenceType.type, Format.Format21c), - NEW_ARRAY((byte)0x23, "new-array", ReferenceType.type, Format.Format22c), - FILLED_NEW_ARRAY((byte)0x24, "filled-new-array", ReferenceType.type, Format.Format35c), - FILLED_NEW_ARRAY_RANGE((byte)0x25, "filled-new-array/range", ReferenceType.type, Format.Format3rc), + CONST_STRING((byte)0x1a, "const-string", ReferenceType.string, Format.Format21c, Opcode.CAN_THROW), + CONST_STRING_JUMBO((byte)0x1b, "const-string/jumbo", ReferenceType.string, Format.Format31c, Opcode.CAN_THROW), + CONST_CLASS((byte)0x1c, "const-class", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW), + MONITOR_ENTER((byte)0x1d, "monitor-enter", ReferenceType.none, Format.Format11x, Opcode.CAN_THROW), + MONITOR_EXIT((byte)0x1e, "monitor-exit", ReferenceType.none, Format.Format11x, Opcode.CAN_THROW), + CHECK_CAST((byte)0x1f, "check-cast", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW), + INSTANCE_OF((byte)0x20, "instance-of", ReferenceType.type, Format.Format22c, Opcode.CAN_THROW), + ARRAY_LENGTH((byte)0x21, "array-length", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW), + NEW_INSTANCE((byte)0x22, "new-instance", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW), + NEW_ARRAY((byte)0x23, "new-array", ReferenceType.type, Format.Format22c, Opcode.CAN_THROW), + FILLED_NEW_ARRAY((byte)0x24, "filled-new-array", ReferenceType.type, Format.Format35c, Opcode.CAN_THROW), + FILLED_NEW_ARRAY_RANGE((byte)0x25, "filled-new-array/range", ReferenceType.type, Format.Format3rc, Opcode.CAN_THROW), FILL_ARRAY_DATA((byte)0x26, "fill-array-data", ReferenceType.none, Format.Format31t), - THROW((byte)0x27, "throw", ReferenceType.none, Format.Format11x), + THROW((byte)0x27, "throw", ReferenceType.none, Format.Format11x, Opcode.CAN_THROW), GOTO((byte)0x28, "goto", ReferenceType.none, Format.Format10t), GOTO_16((byte)0x29, "goto/16", ReferenceType.none, Format.Format20t), GOTO_32((byte)0x2a, "goto/32", ReferenceType.none, Format.Format30t), @@ -96,58 +96,58 @@ public enum Opcode IF_GEZ((byte)0x3b, "if-gez", ReferenceType.none, Format.Format21t), IF_GTZ((byte)0x3c, "if-gtz", ReferenceType.none, Format.Format21t), IF_LEZ((byte)0x3d, "if-lez", ReferenceType.none, Format.Format21t), - AGET((byte)0x44, "aget", ReferenceType.none, Format.Format23x), - AGET_WIDE((byte)0x45, "aget-wide", ReferenceType.none, Format.Format23x), - AGET_OBJECT((byte)0x46, "aget-object", ReferenceType.none, Format.Format23x), - AGET_BOOLEAN((byte)0x47, "aget-boolean", ReferenceType.none, Format.Format23x), - AGET_BYTE((byte)0x48, "aget-byte", ReferenceType.none, Format.Format23x), - AGET_CHAR((byte)0x49, "aget-char", ReferenceType.none, Format.Format23x), - AGET_SHORT((byte)0x4a, "aget-short", ReferenceType.none, Format.Format23x), - APUT((byte)0x4b, "aput", ReferenceType.none, Format.Format23x), - APUT_WIDE((byte)0x4c, "aput-wide", ReferenceType.none, Format.Format23x), - APUT_OBJECT((byte)0x4d, "aput-object", ReferenceType.none, Format.Format23x), - APUT_BOOLEAN((byte)0x4e, "aput-boolean", ReferenceType.none, Format.Format23x), - APUT_BYTE((byte)0x4f, "aput-byte", ReferenceType.none, Format.Format23x), - APUT_CHAR((byte)0x50, "aput-char", ReferenceType.none, Format.Format23x), - APUT_SHORT((byte)0x51, "aput-short", ReferenceType.none, Format.Format23x), - IGET((byte)0x52, "iget", ReferenceType.field, Format.Format22c), - IGET_WIDE((byte)0x53, "iget-wide", ReferenceType.field, Format.Format22c), - IGET_OBJECT((byte)0x54, "iget-object", ReferenceType.field, Format.Format22c), - IGET_BOOLEAN((byte)0x55, "iget-boolean", ReferenceType.field, Format.Format22c), - IGET_BYTE((byte)0x56, "iget-byte", ReferenceType.field, Format.Format22c), - IGET_CHAR((byte)0x57, "iget-char", ReferenceType.field, Format.Format22c), - IGET_SHORT((byte)0x58, "iget-short", ReferenceType.field, Format.Format22c), - IPUT((byte)0x59, "iput", ReferenceType.field, Format.Format22c), - IPUT_WIDE((byte)0x5a, "iput-wide", ReferenceType.field, Format.Format22c), - IPUT_OBJECT((byte)0x5b, "iput-object", ReferenceType.field, Format.Format22c), - IPUT_BOOLEAN((byte)0x5c, "iput-boolean", ReferenceType.field, Format.Format22c), - IPUT_BYTE((byte)0x5d, "iput-byte", ReferenceType.field, Format.Format22c), - IPUT_CHAR((byte)0x5e, "iput-char", ReferenceType.field, Format.Format22c), - IPUT_SHORT((byte)0x5f, "iput-short", ReferenceType.field, Format.Format22c), - SGET((byte)0x60, "sget", ReferenceType.field, Format.Format21c), - SGET_WIDE((byte)0x61, "sget-wide", ReferenceType.field, Format.Format21c), - SGET_OBJECT((byte)0x62, "sget-object", ReferenceType.field, Format.Format21c), - SGET_BOOLEAN((byte)0x63, "sget-boolean", ReferenceType.field, Format.Format21c), - SGET_BYTE((byte)0x64, "sget-byte", ReferenceType.field, Format.Format21c), - SGET_CHAR((byte)0x65, "sget-char", ReferenceType.field, Format.Format21c), - SGET_SHORT((byte)0x66, "sget-short", ReferenceType.field, Format.Format21c), - SPUT((byte)0x67, "sput", ReferenceType.field, Format.Format21c), - SPUT_WIDE((byte)0x68, "sput-wide", ReferenceType.field, Format.Format21c), - SPUT_OBJECT((byte)0x69, "sput-object", ReferenceType.field, Format.Format21c), - SPUT_BOOLEAN((byte)0x6a, "sput-boolean", ReferenceType.field, Format.Format21c), - SPUT_BYTE((byte)0x6b, "sput-byte", ReferenceType.field, Format.Format21c), - SPUT_CHAR((byte)0x6c, "sput-char", ReferenceType.field, Format.Format21c), - SPUT_SHORT((byte)0x6d, "sput-short", ReferenceType.field, Format.Format21c), - INVOKE_VIRTUAL((byte)0x6e, "invoke-virtual", ReferenceType.method, Format.Format35c), - INVOKE_SUPER((byte)0x6f, "invoke-super", ReferenceType.method, Format.Format35c), - INVOKE_DIRECT((byte)0x70, "invoke-direct", ReferenceType.method, Format.Format35c), - INVOKE_STATIC((byte)0x71, "invoke-static", ReferenceType.method, Format.Format35c), - INVOKE_INTERFACE((byte)0x72, "invoke-interface", ReferenceType.method, Format.Format35c), - INVOKE_VIRTUAL_RANGE((byte)0x74, "invoke-virtual/range", ReferenceType.method, Format.Format3rc), - INVOKE_SUPER_RANGE((byte)0x75, "invoke-super/range", ReferenceType.method, Format.Format3rc), - INVOKE_DIRECT_RANGE((byte)0x76, "invoke-direct/range", ReferenceType.method, Format.Format3rc), - INVOKE_STATIC_RANGE((byte)0x77, "invoke-static/range", ReferenceType.method, Format.Format3rc), - INVOKE_INTERFACE_RANGE((byte)0x78, "invoke-interface/range", ReferenceType.method, Format.Format3rc), + AGET((byte)0x44, "aget", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + AGET_WIDE((byte)0x45, "aget-wide", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + AGET_OBJECT((byte)0x46, "aget-object", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + AGET_BOOLEAN((byte)0x47, "aget-boolean", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + AGET_BYTE((byte)0x48, "aget-byte", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + AGET_CHAR((byte)0x49, "aget-char", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + AGET_SHORT((byte)0x4a, "aget-short", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + APUT((byte)0x4b, "aput", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + APUT_WIDE((byte)0x4c, "aput-wide", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + APUT_OBJECT((byte)0x4d, "aput-object", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + APUT_BOOLEAN((byte)0x4e, "aput-boolean", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + APUT_BYTE((byte)0x4f, "aput-byte", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + APUT_CHAR((byte)0x50, "aput-char", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + APUT_SHORT((byte)0x51, "aput-short", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + IGET((byte)0x52, "iget", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IGET_WIDE((byte)0x53, "iget-wide", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IGET_OBJECT((byte)0x54, "iget-object", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IGET_BOOLEAN((byte)0x55, "iget-boolean", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IGET_BYTE((byte)0x56, "iget-byte", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IGET_CHAR((byte)0x57, "iget-char", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IGET_SHORT((byte)0x58, "iget-short", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IPUT((byte)0x59, "iput", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IPUT_WIDE((byte)0x5a, "iput-wide", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IPUT_OBJECT((byte)0x5b, "iput-object", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IPUT_BOOLEAN((byte)0x5c, "iput-boolean", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IPUT_BYTE((byte)0x5d, "iput-byte", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IPUT_CHAR((byte)0x5e, "iput-char", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + IPUT_SHORT((byte)0x5f, "iput-short", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW), + SGET((byte)0x60, "sget", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SGET_WIDE((byte)0x61, "sget-wide", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SGET_OBJECT((byte)0x62, "sget-object", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SGET_BOOLEAN((byte)0x63, "sget-boolean", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SGET_BYTE((byte)0x64, "sget-byte", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SGET_CHAR((byte)0x65, "sget-char", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SGET_SHORT((byte)0x66, "sget-short", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SPUT((byte)0x67, "sput", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SPUT_WIDE((byte)0x68, "sput-wide", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SPUT_OBJECT((byte)0x69, "sput-object", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SPUT_BOOLEAN((byte)0x6a, "sput-boolean", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SPUT_BYTE((byte)0x6b, "sput-byte", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SPUT_CHAR((byte)0x6c, "sput-char", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + SPUT_SHORT((byte)0x6d, "sput-short", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW), + INVOKE_VIRTUAL((byte)0x6e, "invoke-virtual", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW), + INVOKE_SUPER((byte)0x6f, "invoke-super", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW), + INVOKE_DIRECT((byte)0x70, "invoke-direct", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW), + INVOKE_STATIC((byte)0x71, "invoke-static", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW), + INVOKE_INTERFACE((byte)0x72, "invoke-interface", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW), + INVOKE_VIRTUAL_RANGE((byte)0x74, "invoke-virtual/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW), + INVOKE_SUPER_RANGE((byte)0x75, "invoke-super/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW), + INVOKE_DIRECT_RANGE((byte)0x76, "invoke-direct/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW), + INVOKE_STATIC_RANGE((byte)0x77, "invoke-static/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW), + INVOKE_INTERFACE_RANGE((byte)0x78, "invoke-interface/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW), NEG_INT((byte)0x7b, "neg-int", ReferenceType.none, Format.Format12x), NOT_INT((byte)0x7c, "not-int", ReferenceType.none, Format.Format12x), NEG_LONG((byte)0x7d, "neg-long", ReferenceType.none, Format.Format12x), @@ -172,8 +172,8 @@ public enum Opcode ADD_INT((byte)0x90, "add-int", ReferenceType.none, Format.Format23x), SUB_INT((byte)0x91, "sub-int", ReferenceType.none, Format.Format23x), MUL_INT((byte)0x92, "mul-int", ReferenceType.none, Format.Format23x), - DIV_INT((byte)0x93, "div-int", ReferenceType.none, Format.Format23x), - REM_INT((byte)0x94, "rem-int", ReferenceType.none, Format.Format23x), + DIV_INT((byte)0x93, "div-int", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + REM_INT((byte)0x94, "rem-int", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), AND_INT((byte)0x95, "and-int", ReferenceType.none, Format.Format23x), OR_INT((byte)0x96, "or-int", ReferenceType.none, Format.Format23x), XOR_INT((byte)0x97, "xor-int", ReferenceType.none, Format.Format23x), @@ -183,8 +183,8 @@ public enum Opcode ADD_LONG((byte)0x9b, "add-long", ReferenceType.none, Format.Format23x), SUB_LONG((byte)0x9c, "sub-long", ReferenceType.none, Format.Format23x), MUL_LONG((byte)0x9d, "mul-long", ReferenceType.none, Format.Format23x), - DIV_LONG((byte)0x9e, "div-long", ReferenceType.none, Format.Format23x), - REM_LONG((byte)0x9f, "rem-long", ReferenceType.none, Format.Format23x), + DIV_LONG((byte)0x9e, "div-long", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), + REM_LONG((byte)0x9f, "rem-long", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW), AND_LONG((byte)0xa0, "and-long", ReferenceType.none, Format.Format23x), OR_LONG((byte)0xa1, "or-long", ReferenceType.none, Format.Format23x), XOR_LONG((byte)0xa2, "xor-long", ReferenceType.none, Format.Format23x), @@ -204,8 +204,8 @@ public enum Opcode ADD_INT_2ADDR((byte)0xb0, "add-int/2addr", ReferenceType.none, Format.Format12x), SUB_INT_2ADDR((byte)0xb1, "sub-int/2addr", ReferenceType.none, Format.Format12x), MUL_INT_2ADDR((byte)0xb2, "mul-int/2addr", ReferenceType.none, Format.Format12x), - DIV_INT_2ADDR((byte)0xb3, "div-int/2addr", ReferenceType.none, Format.Format12x), - REM_INT_2ADDR((byte)0xb4, "rem-int/2addr", ReferenceType.none, Format.Format12x), + DIV_INT_2ADDR((byte)0xb3, "div-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW), + REM_INT_2ADDR((byte)0xb4, "rem-int/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW), AND_INT_2ADDR((byte)0xb5, "and-int/2addr", ReferenceType.none, Format.Format12x), OR_INT_2ADDR((byte)0xb6, "or-int/2addr", ReferenceType.none, Format.Format12x), XOR_INT_2ADDR((byte)0xb7, "xor-int/2addr", ReferenceType.none, Format.Format12x), @@ -215,8 +215,8 @@ public enum Opcode ADD_LONG_2ADDR((byte)0xbb, "add-long/2addr", ReferenceType.none, Format.Format12x), SUB_LONG_2ADDR((byte)0xbc, "sub-long/2addr", ReferenceType.none, Format.Format12x), MUL_LONG_2ADDR((byte)0xbd, "mul-long/2addr", ReferenceType.none, Format.Format12x), - DIV_LONG_2ADDR((byte)0xbe, "div-long/2addr", ReferenceType.none, Format.Format12x), - REM_LONG_2ADDR((byte)0xbf, "rem-long/2addr", ReferenceType.none, Format.Format12x), + DIV_LONG_2ADDR((byte)0xbe, "div-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW), + REM_LONG_2ADDR((byte)0xbf, "rem-long/2addr", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW), AND_LONG_2ADDR((byte)0xc0, "and-long/2addr", ReferenceType.none, Format.Format12x), OR_LONG_2ADDR((byte)0xc1, "or-long/2addr", ReferenceType.none, Format.Format12x), XOR_LONG_2ADDR((byte)0xc2, "xor-long/2addr", ReferenceType.none, Format.Format12x), @@ -236,16 +236,16 @@ public enum Opcode ADD_INT_LIT16((byte)0xd0, "add-int/lit16", ReferenceType.none, Format.Format22s), RSUB_INT((byte)0xd1, "rsub-int", ReferenceType.none, Format.Format22s), MUL_INT_LIT16((byte)0xd2, "mul-int/lit16", ReferenceType.none, Format.Format22s), - DIV_INT_LIT16((byte)0xd3, "div-int/lit16", ReferenceType.none, Format.Format22s), - REM_INT_LIT16((byte)0xd4, "rem-int/lit16", ReferenceType.none, Format.Format22s), + DIV_INT_LIT16((byte)0xd3, "div-int/lit16", ReferenceType.none, Format.Format22s, Opcode.CAN_THROW), + REM_INT_LIT16((byte)0xd4, "rem-int/lit16", ReferenceType.none, Format.Format22s, Opcode.CAN_THROW), AND_INT_LIT16((byte)0xd5, "and-int/lit16", ReferenceType.none, Format.Format22s), OR_INT_LIT16((byte)0xd6, "or-int/lit16", ReferenceType.none, Format.Format22s), XOR_INT_LIT16((byte)0xd7, "xor-int/lit16", ReferenceType.none, Format.Format22s), ADD_INT_LIT8((byte)0xd8, "add-int/lit8", ReferenceType.none, Format.Format22b), RSUB_INT_LIT8((byte)0xd9, "rsub-int/lit8", ReferenceType.none, Format.Format22b), MUL_INT_LIT8((byte)0xda, "mul-int/lit8", ReferenceType.none, Format.Format22b), - DIV_INT_LIT8((byte)0xdb, "div-int/lit8", ReferenceType.none, Format.Format22b), - REM_INT_LIT8((byte)0xdc, "rem-int/lit8", ReferenceType.none, Format.Format22b), + DIV_INT_LIT8((byte)0xdb, "div-int/lit8", ReferenceType.none, Format.Format22b, Opcode.CAN_THROW), + REM_INT_LIT8((byte)0xdc, "rem-int/lit8", ReferenceType.none, Format.Format22b, Opcode.CAN_THROW), AND_INT_LIT8((byte)0xdd, "and-int/lit8", ReferenceType.none, Format.Format22b), OR_INT_LIT8((byte)0xde, "or-int/lit8", ReferenceType.none, Format.Format22b), XOR_INT_LIT8((byte)0xdf, "xor-int/lit8", ReferenceType.none, Format.Format22b), @@ -254,24 +254,27 @@ public enum Opcode USHR_INT_LIT8((byte)0xe2, "ushr-int/lit8", ReferenceType.none, Format.Format22b), - EXECUTE_INLINE((byte)0xee, "execute-inline", ReferenceType.none, Format.Format35ms, true), - EXECUTE_INLINE_RANGE((byte)0xef, "execute-inline/range", ReferenceType.none, Format.Format3rms, true), - INVOKE_DIRECT_EMPTY((byte)0xf0, "invoke-direct-empty", ReferenceType.method, Format.Format35s, true), - IGET_QUICK((byte)0xf2, "iget-quick", ReferenceType.none, Format.Format22cs, true), - IGET_WIDE_QUICK((byte)0xf3, "iget-wide-quick", ReferenceType.none, Format.Format22cs, true), - IGET_OBJECT_QUICK((byte)0xf4, "iget-object-quick", ReferenceType.none, Format.Format22cs, true), - IPUT_QUICK((byte)0xf5, "iput-quick", ReferenceType.none, Format.Format22cs, true), - IPUT_WIDE_QUICK((byte)0xf6, "iput-wide-quick", ReferenceType.none, Format.Format22cs, true), - IPUT_OBJECT_QUICK((byte)0xf7, "iput-object-quick", ReferenceType.none, Format.Format22cs, true), - INVOKE_VIRTUAL_QUICK((byte)0xf8, "invoke-virtual-quick", ReferenceType.none, Format.Format35ms, true), - INVOKE_VIRTUAL_QUICK_RANGE((byte)0xf9, "invoke-virtual-quick/range", ReferenceType.none, Format.Format3rms, true), - INVOKE_SUPER_QUICK((byte)0xfa, "invoke-super-quick", ReferenceType.none, Format.Format35ms, true), - INVOKE_SUPER_QUICK_RANGE((byte)0xfb, "invoke-super-quick/range", ReferenceType.none, Format.Format3rms, true); + EXECUTE_INLINE((byte)0xee, "execute-inline", ReferenceType.none, Format.Format35ms, Opcode.ODEX_ONLY), + EXECUTE_INLINE_RANGE((byte)0xef, "execute-inline/range", ReferenceType.none, Format.Format3rms, Opcode.ODEX_ONLY), + INVOKE_DIRECT_EMPTY((byte)0xf0, "invoke-direct-empty", ReferenceType.method, Format.Format35s, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + IGET_QUICK((byte)0xf2, "iget-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + IGET_WIDE_QUICK((byte)0xf3, "iget-wide-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + IGET_OBJECT_QUICK((byte)0xf4, "iget-object-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + IPUT_QUICK((byte)0xf5, "iput-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + IPUT_WIDE_QUICK((byte)0xf6, "iput-wide-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + IPUT_OBJECT_QUICK((byte)0xf7, "iput-object-quick", ReferenceType.none, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + INVOKE_VIRTUAL_QUICK((byte)0xf8, "invoke-virtual-quick", ReferenceType.none, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + INVOKE_VIRTUAL_QUICK_RANGE((byte)0xf9, "invoke-virtual-quick/range", ReferenceType.none, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + INVOKE_SUPER_QUICK((byte)0xfa, "invoke-super-quick", ReferenceType.none, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + INVOKE_SUPER_QUICK_RANGE((byte)0xfb, "invoke-super-quick/range", ReferenceType.none, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW); private static Opcode[] opcodesByValue; private static HashMap opcodesByName; + public static final int CAN_THROW = 0x1; + public static final int ODEX_ONLY = 0x2; + static { opcodesByValue = new Opcode[256]; opcodesByName = new HashMap(); @@ -294,17 +297,25 @@ public enum Opcode public final String name; public final ReferenceType referenceType; public final Format format; - public final boolean odexOnly; + public final int flags; Opcode(byte opcodeValue, String opcodeName, ReferenceType referenceType, Format format) { - this(opcodeValue, opcodeName, referenceType, format, false); + this(opcodeValue, opcodeName, referenceType, format, 0); } - Opcode(byte opcodeValue, String opcodeName, ReferenceType referenceType, Format format, boolean odexOnly) { + Opcode(byte opcodeValue, String opcodeName, ReferenceType referenceType, Format format, int flags) { this.value = opcodeValue; this.name = opcodeName; this.referenceType = referenceType; this.format = format; - this.odexOnly = odexOnly; + this.flags = flags; + } + + public final boolean canThrow() { + return (flags & CAN_THROW) != 0; + } + + public final boolean odexOnly() { + return (flags & ODEX_ONLY) != 0; } }