Merge "Use the generated opcode info tables." into dalvik-dev
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.c
index 5949303..556dbc2 100644
--- a/dexdump/DexDump.c
+++ b/dexdump/DexDump.c
@@ -1097,7 +1097,7 @@
}
}
- dexDecodeInstruction(&gInstrInfo, insns, &decInsn);
+ dexDecodeInstruction(insns, &decInsn);
dumpInstruction(pDexFile, pCode, insnIdx, insnWidth, &decInsn);
insns += insnWidth;
@@ -1891,10 +1891,7 @@
}
/* initialize some VM tables */
- if (dexCreateInstructionInfoTables(&gInstrInfo)) {
- fprintf(stderr, "Failed to construct instruction tables\n");
- return 1;
- }
+ dexGetInstructionInfoTables(&gInstrInfo);
if (wantUsage) {
usage();
@@ -1906,7 +1903,5 @@
result |= process(argv[optind++]);
}
- dexFreeInstructionInfoTables(&gInstrInfo);
-
return (result != 0);
}
diff --git a/libdex/InstrUtils.c b/libdex/InstrUtils.c
index ab15c81..936bd01 100644
--- a/libdex/InstrUtils.c
+++ b/libdex/InstrUtils.c
@@ -25,9 +25,6 @@
#include "InstrUtils.h"
#include <stdlib.h>
-#if 0
-/* coming soon! */
-
/*
* Table that maps each opcode to the full width of instructions that
* use that opcode, in (16-bit) code units. Unimplemented opcodes as
@@ -459,1379 +456,23 @@
kIndexUnknown,
// END(libdex-index-types)
};
-#endif
/*
- * Generate a table that holds the width of all instructions.
- *
- * Unimplemented instructions have a width of zero.
- *
- * I'm doing it with a giant switch statement because it's easier to
- * maintain and update than a static table with 256 unadorned integers,
- * and if we're missing a case gcc emits a "warning: enumeration value not
- * handled" message.
- *
- * (To save space in the binary we could generate a static table with a
- * command-line utility.)
+ * Global InstructionInfoTables struct.
*/
-InstructionWidth* dexCreateInstrWidthTable(void)
-{
-#ifdef __ARM_ARCH_7A__
- /* hack to work around mysterious problem on emulator */
- LOGD("creating instr width table\n");
-#endif
- InstructionWidth* instrWidth;
- int i;
-
- instrWidth = malloc(sizeof(InstructionWidth) * kNumDalvikInstructions);
- if (instrWidth == NULL)
- return NULL;
-
- for (i = 0; i < kNumDalvikInstructions; i++) {
- OpCode opc = (OpCode) i;
- int width = 0;
-
- switch (opc) {
- case OP_NOP: /* note data for e.g. switch-* encoded "inside" a NOP */
- case OP_MOVE:
- case OP_MOVE_WIDE:
- case OP_MOVE_OBJECT:
- case OP_MOVE_RESULT:
- case OP_MOVE_RESULT_WIDE:
- case OP_MOVE_RESULT_OBJECT:
- case OP_MOVE_EXCEPTION:
- case OP_RETURN_VOID:
- case OP_RETURN:
- case OP_RETURN_WIDE:
- case OP_RETURN_OBJECT:
- case OP_CONST_4:
- case OP_MONITOR_ENTER:
- case OP_MONITOR_EXIT:
- case OP_ARRAY_LENGTH:
- case OP_THROW:
- case OP_GOTO:
- case OP_NEG_INT:
- case OP_NOT_INT:
- case OP_NEG_LONG:
- case OP_NOT_LONG:
- case OP_NEG_FLOAT:
- case OP_NEG_DOUBLE:
- case OP_INT_TO_LONG:
- case OP_INT_TO_FLOAT:
- case OP_INT_TO_DOUBLE:
- case OP_LONG_TO_INT:
- case OP_LONG_TO_FLOAT:
- case OP_LONG_TO_DOUBLE:
- case OP_FLOAT_TO_INT:
- case OP_FLOAT_TO_LONG:
- case OP_FLOAT_TO_DOUBLE:
- case OP_DOUBLE_TO_INT:
- case OP_DOUBLE_TO_LONG:
- case OP_DOUBLE_TO_FLOAT:
- case OP_INT_TO_BYTE:
- case OP_INT_TO_CHAR:
- case OP_INT_TO_SHORT:
- case OP_ADD_INT_2ADDR:
- case OP_SUB_INT_2ADDR:
- case OP_MUL_INT_2ADDR:
- case OP_DIV_INT_2ADDR:
- case OP_REM_INT_2ADDR:
- case OP_AND_INT_2ADDR:
- case OP_OR_INT_2ADDR:
- case OP_XOR_INT_2ADDR:
- case OP_SHL_INT_2ADDR:
- case OP_SHR_INT_2ADDR:
- case OP_USHR_INT_2ADDR:
- case OP_ADD_LONG_2ADDR:
- case OP_SUB_LONG_2ADDR:
- case OP_MUL_LONG_2ADDR:
- case OP_DIV_LONG_2ADDR:
- case OP_REM_LONG_2ADDR:
- case OP_AND_LONG_2ADDR:
- case OP_OR_LONG_2ADDR:
- case OP_XOR_LONG_2ADDR:
- case OP_SHL_LONG_2ADDR:
- case OP_SHR_LONG_2ADDR:
- case OP_USHR_LONG_2ADDR:
- case OP_ADD_FLOAT_2ADDR:
- case OP_SUB_FLOAT_2ADDR:
- case OP_MUL_FLOAT_2ADDR:
- case OP_DIV_FLOAT_2ADDR:
- case OP_REM_FLOAT_2ADDR:
- case OP_ADD_DOUBLE_2ADDR:
- case OP_SUB_DOUBLE_2ADDR:
- case OP_MUL_DOUBLE_2ADDR:
- case OP_DIV_DOUBLE_2ADDR:
- case OP_REM_DOUBLE_2ADDR:
- width = 1;
- break;
-
- case OP_MOVE_FROM16:
- case OP_MOVE_WIDE_FROM16:
- case OP_MOVE_OBJECT_FROM16:
- case OP_CONST_16:
- case OP_CONST_HIGH16:
- case OP_CONST_WIDE_16:
- case OP_CONST_WIDE_HIGH16:
- case OP_CONST_STRING:
- case OP_CONST_CLASS:
- case OP_CHECK_CAST:
- case OP_INSTANCE_OF:
- case OP_NEW_INSTANCE:
- case OP_NEW_ARRAY:
- case OP_CMPL_FLOAT:
- case OP_CMPG_FLOAT:
- case OP_CMPL_DOUBLE:
- case OP_CMPG_DOUBLE:
- case OP_CMP_LONG:
- case OP_GOTO_16:
- case OP_IF_EQ:
- case OP_IF_NE:
- case OP_IF_LT:
- case OP_IF_GE:
- case OP_IF_GT:
- case OP_IF_LE:
- case OP_IF_EQZ:
- case OP_IF_NEZ:
- case OP_IF_LTZ:
- case OP_IF_GEZ:
- case OP_IF_GTZ:
- case OP_IF_LEZ:
- case OP_AGET:
- case OP_AGET_WIDE:
- case OP_AGET_OBJECT:
- case OP_AGET_BOOLEAN:
- case OP_AGET_BYTE:
- case OP_AGET_CHAR:
- case OP_AGET_SHORT:
- case OP_APUT:
- case OP_APUT_WIDE:
- case OP_APUT_OBJECT:
- case OP_APUT_BOOLEAN:
- case OP_APUT_BYTE:
- case OP_APUT_CHAR:
- case OP_APUT_SHORT:
- case OP_IGET:
- case OP_IGET_WIDE:
- case OP_IGET_OBJECT:
- case OP_IGET_BOOLEAN:
- case OP_IGET_BYTE:
- case OP_IGET_CHAR:
- case OP_IGET_SHORT:
- case OP_IPUT:
- case OP_IPUT_WIDE:
- case OP_IPUT_OBJECT:
- case OP_IPUT_BOOLEAN:
- case OP_IPUT_BYTE:
- case OP_IPUT_CHAR:
- case OP_IPUT_SHORT:
- case OP_SGET:
- case OP_SGET_WIDE:
- case OP_SGET_OBJECT:
- case OP_SGET_BOOLEAN:
- case OP_SGET_BYTE:
- case OP_SGET_CHAR:
- case OP_SGET_SHORT:
- case OP_SPUT:
- case OP_SPUT_WIDE:
- case OP_SPUT_OBJECT:
- case OP_SPUT_BOOLEAN:
- case OP_SPUT_BYTE:
- case OP_SPUT_CHAR:
- case OP_SPUT_SHORT:
- case OP_ADD_INT:
- case OP_SUB_INT:
- case OP_MUL_INT:
- case OP_DIV_INT:
- case OP_REM_INT:
- case OP_AND_INT:
- case OP_OR_INT:
- case OP_XOR_INT:
- case OP_SHL_INT:
- case OP_SHR_INT:
- case OP_USHR_INT:
- case OP_ADD_LONG:
- case OP_SUB_LONG:
- case OP_MUL_LONG:
- case OP_DIV_LONG:
- case OP_REM_LONG:
- case OP_AND_LONG:
- case OP_OR_LONG:
- case OP_XOR_LONG:
- case OP_SHL_LONG:
- case OP_SHR_LONG:
- case OP_USHR_LONG:
- case OP_ADD_FLOAT:
- case OP_SUB_FLOAT:
- case OP_MUL_FLOAT:
- case OP_DIV_FLOAT:
- case OP_REM_FLOAT:
- case OP_ADD_DOUBLE:
- case OP_SUB_DOUBLE:
- case OP_MUL_DOUBLE:
- case OP_DIV_DOUBLE:
- case OP_REM_DOUBLE:
- case OP_ADD_INT_LIT16:
- case OP_RSUB_INT:
- case OP_MUL_INT_LIT16:
- case OP_DIV_INT_LIT16:
- case OP_REM_INT_LIT16:
- case OP_AND_INT_LIT16:
- case OP_OR_INT_LIT16:
- case OP_XOR_INT_LIT16:
- case OP_ADD_INT_LIT8:
- case OP_RSUB_INT_LIT8:
- case OP_MUL_INT_LIT8:
- case OP_DIV_INT_LIT8:
- case OP_REM_INT_LIT8:
- case OP_AND_INT_LIT8:
- case OP_OR_INT_LIT8:
- case OP_XOR_INT_LIT8:
- case OP_SHL_INT_LIT8:
- case OP_SHR_INT_LIT8:
- case OP_USHR_INT_LIT8:
- width = 2;
- break;
-
- case OP_MOVE_16:
- case OP_MOVE_WIDE_16:
- case OP_MOVE_OBJECT_16:
- case OP_CONST:
- case OP_CONST_WIDE_32:
- case OP_CONST_STRING_JUMBO:
- case OP_GOTO_32:
- case OP_FILLED_NEW_ARRAY:
- case OP_FILLED_NEW_ARRAY_RANGE:
- case OP_FILL_ARRAY_DATA:
- case OP_PACKED_SWITCH:
- case OP_SPARSE_SWITCH:
- case OP_INVOKE_VIRTUAL:
- case OP_INVOKE_SUPER:
- case OP_INVOKE_DIRECT:
- case OP_INVOKE_STATIC:
- case OP_INVOKE_INTERFACE:
- case OP_INVOKE_VIRTUAL_RANGE:
- case OP_INVOKE_SUPER_RANGE:
- case OP_INVOKE_DIRECT_RANGE:
- case OP_INVOKE_STATIC_RANGE:
- case OP_INVOKE_INTERFACE_RANGE:
- width = 3;
- break;
-
- case OP_CONST_WIDE:
- width = 5;
- break;
-
- /*
- * Optimized instructions.
- */
- case OP_RETURN_VOID_BARRIER:
- width = 1;
- break;
- case OP_IGET_QUICK:
- case OP_IGET_WIDE_QUICK:
- case OP_IGET_OBJECT_QUICK:
- case OP_IPUT_QUICK:
- case OP_IPUT_WIDE_QUICK:
- case OP_IPUT_OBJECT_QUICK:
- case OP_IGET_VOLATILE:
- case OP_IPUT_VOLATILE:
- case OP_SGET_VOLATILE:
- case OP_SPUT_VOLATILE:
- case OP_IGET_OBJECT_VOLATILE:
- case OP_IPUT_OBJECT_VOLATILE:
- case OP_SGET_OBJECT_VOLATILE:
- case OP_SPUT_OBJECT_VOLATILE:
- case OP_IGET_WIDE_VOLATILE:
- case OP_IPUT_WIDE_VOLATILE:
- case OP_SGET_WIDE_VOLATILE:
- case OP_SPUT_WIDE_VOLATILE:
- case OP_THROW_VERIFICATION_ERROR:
- width = 2;
- break;
- case OP_INVOKE_VIRTUAL_QUICK:
- case OP_INVOKE_VIRTUAL_QUICK_RANGE:
- case OP_INVOKE_SUPER_QUICK:
- case OP_INVOKE_SUPER_QUICK_RANGE:
- case OP_EXECUTE_INLINE:
- case OP_EXECUTE_INLINE_RANGE:
- case OP_INVOKE_DIRECT_EMPTY:
- width = 3;
- break;
-
- /* these should never appear when scanning bytecode */
- case OP_UNUSED_3E:
- case OP_UNUSED_3F:
- case OP_UNUSED_40:
- case OP_UNUSED_41:
- case OP_UNUSED_42:
- case OP_UNUSED_43:
- case OP_UNUSED_73:
- case OP_UNUSED_79:
- case OP_UNUSED_7A:
- case OP_BREAKPOINT:
- case OP_UNUSED_FF:
- assert(width == 0);
- break;
-
- /*
- * DO NOT add a "default" clause here. Without it the compiler will
- * complain if an instruction is missing (which is desirable).
- */
- }
-
- instrWidth[opc] = width;
- }
-
- return instrWidth;
-}
+InstructionInfoTables gDexOpcodeInfo = {
+ gOpcodeFormatTable,
+ gOpcodeIndexTypeTable,
+ gOpcodeFlagsTable,
+ gOpcodeWidthTable
+};
/*
- * Generate a table that holds instruction flags.
+ * Copy pointers to all of the instruction info tables into
+ * the given struct.
*/
-InstructionFlags* dexCreateInstrFlagsTable(void)
-{
- InstructionFlags* instrFlags;
- int i;
-
- instrFlags = malloc(sizeof(InstructionFlags) * kNumDalvikInstructions);
- if (instrFlags == NULL)
- return NULL;
-
- for (i = 0; i < kNumDalvikInstructions; i++) {
- OpCode opc = (OpCode) i;
- InstructionFlags flags = 0;
-
- switch (opc) {
- /* these don't affect the PC and can't cause an exception */
- case OP_NOP:
- case OP_MOVE:
- case OP_MOVE_FROM16:
- case OP_MOVE_16:
- case OP_MOVE_WIDE:
- case OP_MOVE_WIDE_FROM16:
- case OP_MOVE_WIDE_16:
- case OP_MOVE_OBJECT:
- case OP_MOVE_OBJECT_FROM16:
- case OP_MOVE_OBJECT_16:
- case OP_MOVE_RESULT:
- case OP_MOVE_RESULT_WIDE:
- case OP_MOVE_RESULT_OBJECT:
- case OP_MOVE_EXCEPTION:
- case OP_CONST_4:
- case OP_CONST_16:
- case OP_CONST:
- case OP_CONST_HIGH16:
- case OP_CONST_WIDE_16:
- case OP_CONST_WIDE_32:
- case OP_CONST_WIDE:
- case OP_CONST_WIDE_HIGH16:
- case OP_FILL_ARRAY_DATA:
- case OP_CMPL_FLOAT:
- case OP_CMPG_FLOAT:
- case OP_CMPL_DOUBLE:
- case OP_CMPG_DOUBLE:
- case OP_CMP_LONG:
- case OP_NEG_INT:
- case OP_NOT_INT:
- case OP_NEG_LONG:
- case OP_NOT_LONG:
- case OP_NEG_FLOAT:
- case OP_NEG_DOUBLE:
- case OP_INT_TO_LONG:
- case OP_INT_TO_FLOAT:
- case OP_INT_TO_DOUBLE:
- case OP_LONG_TO_INT:
- case OP_LONG_TO_FLOAT:
- case OP_LONG_TO_DOUBLE:
- case OP_FLOAT_TO_INT:
- case OP_FLOAT_TO_LONG:
- case OP_FLOAT_TO_DOUBLE:
- case OP_DOUBLE_TO_INT:
- case OP_DOUBLE_TO_LONG:
- case OP_DOUBLE_TO_FLOAT:
- case OP_INT_TO_BYTE:
- case OP_INT_TO_CHAR:
- case OP_INT_TO_SHORT:
- case OP_ADD_INT:
- case OP_SUB_INT:
- case OP_MUL_INT:
- case OP_AND_INT:
- case OP_OR_INT:
- case OP_XOR_INT:
- case OP_SHL_INT:
- case OP_SHR_INT:
- case OP_USHR_INT:
- case OP_ADD_LONG:
- case OP_SUB_LONG:
- case OP_MUL_LONG:
- case OP_AND_LONG:
- case OP_OR_LONG:
- case OP_XOR_LONG:
- case OP_SHL_LONG:
- case OP_SHR_LONG:
- case OP_USHR_LONG:
- case OP_ADD_FLOAT:
- case OP_SUB_FLOAT:
- case OP_MUL_FLOAT:
- case OP_DIV_FLOAT:
- case OP_REM_FLOAT:
- case OP_ADD_DOUBLE:
- case OP_SUB_DOUBLE:
- case OP_MUL_DOUBLE:
- case OP_DIV_DOUBLE: // div by zero just returns NaN
- case OP_REM_DOUBLE:
- case OP_ADD_INT_2ADDR:
- case OP_SUB_INT_2ADDR:
- case OP_MUL_INT_2ADDR:
- case OP_AND_INT_2ADDR:
- case OP_OR_INT_2ADDR:
- case OP_XOR_INT_2ADDR:
- case OP_SHL_INT_2ADDR:
- case OP_SHR_INT_2ADDR:
- case OP_USHR_INT_2ADDR:
- case OP_ADD_LONG_2ADDR:
- case OP_SUB_LONG_2ADDR:
- case OP_MUL_LONG_2ADDR:
- case OP_AND_LONG_2ADDR:
- case OP_OR_LONG_2ADDR:
- case OP_XOR_LONG_2ADDR:
- case OP_SHL_LONG_2ADDR:
- case OP_SHR_LONG_2ADDR:
- case OP_USHR_LONG_2ADDR:
- case OP_ADD_FLOAT_2ADDR:
- case OP_SUB_FLOAT_2ADDR:
- case OP_MUL_FLOAT_2ADDR:
- case OP_DIV_FLOAT_2ADDR:
- case OP_REM_FLOAT_2ADDR:
- case OP_ADD_DOUBLE_2ADDR:
- case OP_SUB_DOUBLE_2ADDR:
- case OP_MUL_DOUBLE_2ADDR:
- case OP_DIV_DOUBLE_2ADDR:
- case OP_REM_DOUBLE_2ADDR:
- case OP_ADD_INT_LIT16:
- case OP_RSUB_INT:
- case OP_MUL_INT_LIT16:
- case OP_AND_INT_LIT16:
- case OP_OR_INT_LIT16:
- case OP_XOR_INT_LIT16:
- case OP_ADD_INT_LIT8:
- case OP_RSUB_INT_LIT8:
- case OP_MUL_INT_LIT8:
- case OP_AND_INT_LIT8:
- case OP_OR_INT_LIT8:
- case OP_XOR_INT_LIT8:
- case OP_SHL_INT_LIT8:
- case OP_SHR_INT_LIT8:
- case OP_USHR_INT_LIT8:
- flags = kInstrCanContinue;
- break;
-
- /* these don't affect the PC, but can cause exceptions */
- case OP_CONST_STRING:
- case OP_CONST_STRING_JUMBO:
- case OP_CONST_CLASS:
- case OP_MONITOR_ENTER:
- case OP_MONITOR_EXIT:
- case OP_CHECK_CAST:
- case OP_INSTANCE_OF:
- case OP_ARRAY_LENGTH:
- case OP_NEW_INSTANCE:
- case OP_NEW_ARRAY:
- case OP_FILLED_NEW_ARRAY:
- case OP_FILLED_NEW_ARRAY_RANGE:
- case OP_AGET:
- case OP_AGET_BOOLEAN:
- case OP_AGET_BYTE:
- case OP_AGET_CHAR:
- case OP_AGET_SHORT:
- case OP_AGET_WIDE:
- case OP_AGET_OBJECT:
- case OP_APUT:
- case OP_APUT_BOOLEAN:
- case OP_APUT_BYTE:
- case OP_APUT_CHAR:
- case OP_APUT_SHORT:
- case OP_APUT_WIDE:
- case OP_APUT_OBJECT:
- case OP_IGET:
- case OP_IGET_BOOLEAN:
- case OP_IGET_BYTE:
- case OP_IGET_CHAR:
- case OP_IGET_SHORT:
- case OP_IGET_WIDE:
- case OP_IGET_OBJECT:
- case OP_IPUT:
- case OP_IPUT_BOOLEAN:
- case OP_IPUT_BYTE:
- case OP_IPUT_CHAR:
- case OP_IPUT_SHORT:
- case OP_IPUT_WIDE:
- case OP_IPUT_OBJECT:
- case OP_SGET:
- case OP_SGET_BOOLEAN:
- case OP_SGET_BYTE:
- case OP_SGET_CHAR:
- case OP_SGET_SHORT:
- case OP_SGET_WIDE:
- case OP_SGET_OBJECT:
- case OP_SPUT:
- case OP_SPUT_BOOLEAN:
- case OP_SPUT_BYTE:
- case OP_SPUT_CHAR:
- case OP_SPUT_SHORT:
- case OP_SPUT_WIDE:
- case OP_SPUT_OBJECT:
- case OP_DIV_INT:
- case OP_REM_INT:
- case OP_DIV_LONG:
- case OP_REM_LONG:
- case OP_DIV_INT_2ADDR:
- case OP_REM_INT_2ADDR:
- case OP_DIV_LONG_2ADDR:
- case OP_REM_LONG_2ADDR:
- case OP_DIV_INT_LIT16:
- case OP_REM_INT_LIT16:
- case OP_DIV_INT_LIT8:
- case OP_REM_INT_LIT8:
- flags = kInstrCanContinue | kInstrCanThrow;
- break;
-
- case OP_INVOKE_VIRTUAL:
- case OP_INVOKE_VIRTUAL_RANGE:
- case OP_INVOKE_SUPER:
- case OP_INVOKE_SUPER_RANGE:
- case OP_INVOKE_DIRECT:
- case OP_INVOKE_DIRECT_RANGE:
- case OP_INVOKE_STATIC:
- case OP_INVOKE_STATIC_RANGE:
- case OP_INVOKE_INTERFACE:
- case OP_INVOKE_INTERFACE_RANGE:
- flags = kInstrCanContinue | kInstrCanThrow | kInstrInvoke;
- break;
-
- case OP_RETURN_VOID:
- case OP_RETURN:
- case OP_RETURN_WIDE:
- case OP_RETURN_OBJECT:
- flags = kInstrCanReturn;
- break;
-
- case OP_THROW:
- flags = kInstrCanThrow;
- break;
-
- /* unconditional branches */
- case OP_GOTO:
- case OP_GOTO_16:
- case OP_GOTO_32:
- flags = kInstrCanBranch;
- break;
-
- /* conditional branches */
- case OP_IF_EQ:
- case OP_IF_NE:
- case OP_IF_LT:
- case OP_IF_GE:
- case OP_IF_GT:
- case OP_IF_LE:
- case OP_IF_EQZ:
- case OP_IF_NEZ:
- case OP_IF_LTZ:
- case OP_IF_GEZ:
- case OP_IF_GTZ:
- case OP_IF_LEZ:
- flags = kInstrCanBranch | kInstrCanContinue;
- break;
-
- /* switch statements; if value not in switch, it continues */
- case OP_PACKED_SWITCH:
- case OP_SPARSE_SWITCH:
- flags = kInstrCanSwitch | kInstrCanContinue;
- break;
-
- /* verifier/optimizer-generated instructions */
- case OP_THROW_VERIFICATION_ERROR:
- flags = kInstrCanThrow;
- break;
- case OP_EXECUTE_INLINE:
- case OP_EXECUTE_INLINE_RANGE:
- flags = kInstrCanContinue | kInstrCanThrow;
- break;
- case OP_IGET_QUICK:
- case OP_IGET_WIDE_QUICK:
- case OP_IGET_OBJECT_QUICK:
- case OP_IPUT_QUICK:
- case OP_IPUT_WIDE_QUICK:
- case OP_IPUT_OBJECT_QUICK:
- case OP_IGET_VOLATILE:
- case OP_IPUT_VOLATILE:
- case OP_SGET_VOLATILE:
- case OP_SPUT_VOLATILE:
- case OP_IGET_OBJECT_VOLATILE:
- case OP_IPUT_OBJECT_VOLATILE:
- case OP_SGET_OBJECT_VOLATILE:
- case OP_SPUT_OBJECT_VOLATILE:
- case OP_IGET_WIDE_VOLATILE:
- case OP_IPUT_WIDE_VOLATILE:
- case OP_SGET_WIDE_VOLATILE:
- case OP_SPUT_WIDE_VOLATILE:
- flags = kInstrCanContinue | kInstrCanThrow;
- break;
- case OP_INVOKE_VIRTUAL_QUICK:
- case OP_INVOKE_VIRTUAL_QUICK_RANGE:
- case OP_INVOKE_SUPER_QUICK:
- case OP_INVOKE_SUPER_QUICK_RANGE:
- case OP_INVOKE_DIRECT_EMPTY:
- flags = kInstrCanContinue | kInstrCanThrow | kInstrInvoke;
- break;
- case OP_RETURN_VOID_BARRIER:
- flags = kInstrCanReturn;
- break;
-
- /* these should never appear when scanning code */
- case OP_UNUSED_3E:
- case OP_UNUSED_3F:
- case OP_UNUSED_40:
- case OP_UNUSED_41:
- case OP_UNUSED_42:
- case OP_UNUSED_43:
- case OP_UNUSED_73:
- case OP_UNUSED_79:
- case OP_UNUSED_7A:
- case OP_BREAKPOINT:
- case OP_UNUSED_FF:
- break;
-
- /*
- * DO NOT add a "default" clause here. Without it the compiler will
- * complain if an instruction is missing (which is desirable).
- */
- }
-
- instrFlags[opc] = flags;
- }
-
- return instrFlags;
-}
-
-/*
- * Allocate and populate a 256-element array with instruction formats.
- * Used in conjunction with dexDecodeInstruction.
- */
-InstructionFormat* dexCreateInstrFormatTable(void)
-{
- InstructionFormat* instFmt;
- int i;
-
- instFmt = malloc(sizeof(InstructionFormat) * kNumDalvikInstructions);
- if (instFmt == NULL)
- return NULL;
-
- for (i = 0; i < kNumDalvikInstructions; i++) {
- OpCode opc = (OpCode) i;
- InstructionFormat fmt = kFmt00x;
-
- switch (opc) {
- case OP_GOTO:
- fmt = kFmt10t;
- break;
- case OP_NOP:
- case OP_RETURN_VOID:
- fmt = kFmt10x;
- break;
- case OP_CONST_4:
- fmt = kFmt11n;
- break;
- case OP_CONST_HIGH16:
- case OP_CONST_WIDE_HIGH16:
- fmt = kFmt21h;
- break;
- case OP_MOVE_RESULT:
- case OP_MOVE_RESULT_WIDE:
- case OP_MOVE_RESULT_OBJECT:
- case OP_MOVE_EXCEPTION:
- case OP_RETURN:
- case OP_RETURN_WIDE:
- case OP_RETURN_OBJECT:
- case OP_MONITOR_ENTER:
- case OP_MONITOR_EXIT:
- case OP_THROW:
- fmt = kFmt11x;
- break;
- case OP_MOVE:
- case OP_MOVE_WIDE:
- case OP_MOVE_OBJECT:
- case OP_ARRAY_LENGTH:
- case OP_NEG_INT:
- case OP_NOT_INT:
- case OP_NEG_LONG:
- case OP_NOT_LONG:
- case OP_NEG_FLOAT:
- case OP_NEG_DOUBLE:
- case OP_INT_TO_LONG:
- case OP_INT_TO_FLOAT:
- case OP_INT_TO_DOUBLE:
- case OP_LONG_TO_INT:
- case OP_LONG_TO_FLOAT:
- case OP_LONG_TO_DOUBLE:
- case OP_FLOAT_TO_INT:
- case OP_FLOAT_TO_LONG:
- case OP_FLOAT_TO_DOUBLE:
- case OP_DOUBLE_TO_INT:
- case OP_DOUBLE_TO_LONG:
- case OP_DOUBLE_TO_FLOAT:
- case OP_INT_TO_BYTE:
- case OP_INT_TO_CHAR:
- case OP_INT_TO_SHORT:
- case OP_ADD_INT_2ADDR:
- case OP_SUB_INT_2ADDR:
- case OP_MUL_INT_2ADDR:
- case OP_DIV_INT_2ADDR:
- case OP_REM_INT_2ADDR:
- case OP_AND_INT_2ADDR:
- case OP_OR_INT_2ADDR:
- case OP_XOR_INT_2ADDR:
- case OP_SHL_INT_2ADDR:
- case OP_SHR_INT_2ADDR:
- case OP_USHR_INT_2ADDR:
- case OP_ADD_LONG_2ADDR:
- case OP_SUB_LONG_2ADDR:
- case OP_MUL_LONG_2ADDR:
- case OP_DIV_LONG_2ADDR:
- case OP_REM_LONG_2ADDR:
- case OP_AND_LONG_2ADDR:
- case OP_OR_LONG_2ADDR:
- case OP_XOR_LONG_2ADDR:
- case OP_SHL_LONG_2ADDR:
- case OP_SHR_LONG_2ADDR:
- case OP_USHR_LONG_2ADDR:
- case OP_ADD_FLOAT_2ADDR:
- case OP_SUB_FLOAT_2ADDR:
- case OP_MUL_FLOAT_2ADDR:
- case OP_DIV_FLOAT_2ADDR:
- case OP_REM_FLOAT_2ADDR:
- case OP_ADD_DOUBLE_2ADDR:
- case OP_SUB_DOUBLE_2ADDR:
- case OP_MUL_DOUBLE_2ADDR:
- case OP_DIV_DOUBLE_2ADDR:
- case OP_REM_DOUBLE_2ADDR:
- fmt = kFmt12x;
- break;
- case OP_GOTO_16:
- fmt = kFmt20t;
- break;
- case OP_GOTO_32:
- fmt = kFmt30t;
- break;
- case OP_CONST_STRING:
- case OP_CONST_CLASS:
- case OP_CHECK_CAST:
- case OP_NEW_INSTANCE:
- case OP_SGET:
- case OP_SGET_WIDE:
- case OP_SGET_OBJECT:
- case OP_SGET_BOOLEAN:
- case OP_SGET_BYTE:
- case OP_SGET_CHAR:
- case OP_SGET_SHORT:
- case OP_SPUT:
- case OP_SPUT_WIDE:
- case OP_SPUT_OBJECT:
- case OP_SPUT_BOOLEAN:
- case OP_SPUT_BYTE:
- case OP_SPUT_CHAR:
- case OP_SPUT_SHORT:
- fmt = kFmt21c;
- break;
- case OP_CONST_16:
- case OP_CONST_WIDE_16:
- fmt = kFmt21s;
- break;
- case OP_IF_EQZ:
- case OP_IF_NEZ:
- case OP_IF_LTZ:
- case OP_IF_GEZ:
- case OP_IF_GTZ:
- case OP_IF_LEZ:
- fmt = kFmt21t;
- break;
- case OP_FILL_ARRAY_DATA:
- case OP_PACKED_SWITCH:
- case OP_SPARSE_SWITCH:
- fmt = kFmt31t;
- break;
- case OP_ADD_INT_LIT8:
- case OP_RSUB_INT_LIT8:
- case OP_MUL_INT_LIT8:
- case OP_DIV_INT_LIT8:
- case OP_REM_INT_LIT8:
- case OP_AND_INT_LIT8:
- case OP_OR_INT_LIT8:
- case OP_XOR_INT_LIT8:
- case OP_SHL_INT_LIT8:
- case OP_SHR_INT_LIT8:
- case OP_USHR_INT_LIT8:
- fmt = kFmt22b;
- break;
- case OP_INSTANCE_OF:
- case OP_NEW_ARRAY:
- case OP_IGET:
- case OP_IGET_WIDE:
- case OP_IGET_OBJECT:
- case OP_IGET_BOOLEAN:
- case OP_IGET_BYTE:
- case OP_IGET_CHAR:
- case OP_IGET_SHORT:
- case OP_IPUT:
- case OP_IPUT_WIDE:
- case OP_IPUT_OBJECT:
- case OP_IPUT_BOOLEAN:
- case OP_IPUT_BYTE:
- case OP_IPUT_CHAR:
- case OP_IPUT_SHORT:
- fmt = kFmt22c;
- break;
- case OP_ADD_INT_LIT16:
- case OP_RSUB_INT:
- case OP_MUL_INT_LIT16:
- case OP_DIV_INT_LIT16:
- case OP_REM_INT_LIT16:
- case OP_AND_INT_LIT16:
- case OP_OR_INT_LIT16:
- case OP_XOR_INT_LIT16:
- fmt = kFmt22s;
- break;
- case OP_IF_EQ:
- case OP_IF_NE:
- case OP_IF_LT:
- case OP_IF_GE:
- case OP_IF_GT:
- case OP_IF_LE:
- fmt = kFmt22t;
- break;
- case OP_MOVE_FROM16:
- case OP_MOVE_WIDE_FROM16:
- case OP_MOVE_OBJECT_FROM16:
- fmt = kFmt22x;
- break;
- case OP_CMPL_FLOAT:
- case OP_CMPG_FLOAT:
- case OP_CMPL_DOUBLE:
- case OP_CMPG_DOUBLE:
- case OP_CMP_LONG:
- case OP_AGET:
- case OP_AGET_WIDE:
- case OP_AGET_OBJECT:
- case OP_AGET_BOOLEAN:
- case OP_AGET_BYTE:
- case OP_AGET_CHAR:
- case OP_AGET_SHORT:
- case OP_APUT:
- case OP_APUT_WIDE:
- case OP_APUT_OBJECT:
- case OP_APUT_BOOLEAN:
- case OP_APUT_BYTE:
- case OP_APUT_CHAR:
- case OP_APUT_SHORT:
- case OP_ADD_INT:
- case OP_SUB_INT:
- case OP_MUL_INT:
- case OP_DIV_INT:
- case OP_REM_INT:
- case OP_AND_INT:
- case OP_OR_INT:
- case OP_XOR_INT:
- case OP_SHL_INT:
- case OP_SHR_INT:
- case OP_USHR_INT:
- case OP_ADD_LONG:
- case OP_SUB_LONG:
- case OP_MUL_LONG:
- case OP_DIV_LONG:
- case OP_REM_LONG:
- case OP_AND_LONG:
- case OP_OR_LONG:
- case OP_XOR_LONG:
- case OP_SHL_LONG:
- case OP_SHR_LONG:
- case OP_USHR_LONG:
- case OP_ADD_FLOAT:
- case OP_SUB_FLOAT:
- case OP_MUL_FLOAT:
- case OP_DIV_FLOAT:
- case OP_REM_FLOAT:
- case OP_ADD_DOUBLE:
- case OP_SUB_DOUBLE:
- case OP_MUL_DOUBLE:
- case OP_DIV_DOUBLE:
- case OP_REM_DOUBLE:
- fmt = kFmt23x;
- break;
- case OP_CONST:
- case OP_CONST_WIDE_32:
- fmt = kFmt31i;
- break;
- case OP_CONST_STRING_JUMBO:
- fmt = kFmt31c;
- break;
- case OP_MOVE_16:
- case OP_MOVE_WIDE_16:
- case OP_MOVE_OBJECT_16:
- fmt = kFmt32x;
- break;
- case OP_FILLED_NEW_ARRAY:
- case OP_INVOKE_VIRTUAL:
- case OP_INVOKE_SUPER:
- case OP_INVOKE_DIRECT:
- case OP_INVOKE_STATIC:
- case OP_INVOKE_INTERFACE:
- fmt = kFmt35c;
- break;
- case OP_FILLED_NEW_ARRAY_RANGE:
- case OP_INVOKE_VIRTUAL_RANGE:
- case OP_INVOKE_SUPER_RANGE:
- case OP_INVOKE_DIRECT_RANGE:
- case OP_INVOKE_STATIC_RANGE:
- case OP_INVOKE_INTERFACE_RANGE:
- fmt = kFmt3rc;
- break;
- case OP_CONST_WIDE:
- fmt = kFmt51l;
- break;
-
- /*
- * Optimized instructions.
- */
- case OP_THROW_VERIFICATION_ERROR:
- fmt = kFmt20bc;
- break;
- case OP_IGET_WIDE_VOLATILE:
- case OP_IPUT_WIDE_VOLATILE:
- case OP_IGET_VOLATILE:
- case OP_IPUT_VOLATILE:
- case OP_IGET_OBJECT_VOLATILE:
- case OP_IPUT_OBJECT_VOLATILE:
- fmt = kFmt22c;
- break;
- case OP_SGET_OBJECT_VOLATILE:
- case OP_SPUT_OBJECT_VOLATILE:
- case OP_SGET_VOLATILE:
- case OP_SPUT_VOLATILE:
- case OP_SGET_WIDE_VOLATILE:
- case OP_SPUT_WIDE_VOLATILE:
- fmt = kFmt21c;
- break;
- case OP_IGET_QUICK:
- case OP_IGET_WIDE_QUICK:
- case OP_IGET_OBJECT_QUICK:
- case OP_IPUT_QUICK:
- case OP_IPUT_WIDE_QUICK:
- case OP_IPUT_OBJECT_QUICK:
- fmt = kFmt22cs;
- break;
- case OP_INVOKE_VIRTUAL_QUICK:
- case OP_INVOKE_SUPER_QUICK:
- fmt = kFmt35ms;
- break;
- case OP_INVOKE_VIRTUAL_QUICK_RANGE:
- case OP_INVOKE_SUPER_QUICK_RANGE:
- fmt = kFmt3rms;
- break;
- case OP_EXECUTE_INLINE:
- fmt = kFmt35mi;
- break;
- case OP_EXECUTE_INLINE_RANGE:
- fmt = kFmt3rmi;
- break;
- case OP_INVOKE_DIRECT_EMPTY:
- fmt = kFmt35c;
- break;
- case OP_RETURN_VOID_BARRIER:
- fmt = kFmt10x;
- break;
-
- /* these should never appear when scanning code */
- case OP_UNUSED_3E:
- case OP_UNUSED_3F:
- case OP_UNUSED_40:
- case OP_UNUSED_41:
- case OP_UNUSED_42:
- case OP_UNUSED_43:
- case OP_UNUSED_73:
- case OP_UNUSED_79:
- case OP_UNUSED_7A:
- case OP_BREAKPOINT:
- case OP_UNUSED_FF:
- fmt = kFmt00x;
- break;
-
- /*
- * DO NOT add a "default" clause here. Without it the compiler will
- * complain if an instruction is missing (which is desirable).
- */
- }
-
- instFmt[opc] = fmt;
- }
-
- return instFmt;
-}
-
-/*
- * Allocate and populate an array with index types for all instructions.
- * Used in conjunction with dexDecodeInstruction.
- */
-InstructionIndexType* dexCreateInstrIndexTypeTable(void)
-{
- InstructionIndexType* indexTypes;
- int i;
-
- indexTypes = malloc(sizeof(InstructionIndexType) * kNumDalvikInstructions);
- if (indexTypes == NULL)
- return NULL;
-
- for (i = 0; i < kNumDalvikInstructions; i++) {
- OpCode opc = (OpCode) i;
- InstructionIndexType indexType = kIndexUnknown;
-
- switch (opc) {
- case OP_GOTO:
- case OP_NOP:
- case OP_RETURN_VOID:
- case OP_CONST_4:
- case OP_CONST_HIGH16:
- case OP_CONST_WIDE_HIGH16:
- case OP_MOVE_RESULT:
- case OP_MOVE_RESULT_WIDE:
- case OP_MOVE_RESULT_OBJECT:
- case OP_MOVE_EXCEPTION:
- case OP_RETURN:
- case OP_RETURN_WIDE:
- case OP_RETURN_OBJECT:
- case OP_MONITOR_ENTER:
- case OP_MONITOR_EXIT:
- case OP_THROW:
- case OP_MOVE:
- case OP_MOVE_WIDE:
- case OP_MOVE_OBJECT:
- case OP_ARRAY_LENGTH:
- case OP_NEG_INT:
- case OP_NOT_INT:
- case OP_NEG_LONG:
- case OP_NOT_LONG:
- case OP_NEG_FLOAT:
- case OP_NEG_DOUBLE:
- case OP_INT_TO_LONG:
- case OP_INT_TO_FLOAT:
- case OP_INT_TO_DOUBLE:
- case OP_LONG_TO_INT:
- case OP_LONG_TO_FLOAT:
- case OP_LONG_TO_DOUBLE:
- case OP_FLOAT_TO_INT:
- case OP_FLOAT_TO_LONG:
- case OP_FLOAT_TO_DOUBLE:
- case OP_DOUBLE_TO_INT:
- case OP_DOUBLE_TO_LONG:
- case OP_DOUBLE_TO_FLOAT:
- case OP_INT_TO_BYTE:
- case OP_INT_TO_CHAR:
- case OP_INT_TO_SHORT:
- case OP_ADD_INT_2ADDR:
- case OP_SUB_INT_2ADDR:
- case OP_MUL_INT_2ADDR:
- case OP_DIV_INT_2ADDR:
- case OP_REM_INT_2ADDR:
- case OP_AND_INT_2ADDR:
- case OP_OR_INT_2ADDR:
- case OP_XOR_INT_2ADDR:
- case OP_SHL_INT_2ADDR:
- case OP_SHR_INT_2ADDR:
- case OP_USHR_INT_2ADDR:
- case OP_ADD_LONG_2ADDR:
- case OP_SUB_LONG_2ADDR:
- case OP_MUL_LONG_2ADDR:
- case OP_DIV_LONG_2ADDR:
- case OP_REM_LONG_2ADDR:
- case OP_AND_LONG_2ADDR:
- case OP_OR_LONG_2ADDR:
- case OP_XOR_LONG_2ADDR:
- case OP_SHL_LONG_2ADDR:
- case OP_SHR_LONG_2ADDR:
- case OP_USHR_LONG_2ADDR:
- case OP_ADD_FLOAT_2ADDR:
- case OP_SUB_FLOAT_2ADDR:
- case OP_MUL_FLOAT_2ADDR:
- case OP_DIV_FLOAT_2ADDR:
- case OP_REM_FLOAT_2ADDR:
- case OP_ADD_DOUBLE_2ADDR:
- case OP_SUB_DOUBLE_2ADDR:
- case OP_MUL_DOUBLE_2ADDR:
- case OP_DIV_DOUBLE_2ADDR:
- case OP_REM_DOUBLE_2ADDR:
- case OP_GOTO_16:
- case OP_GOTO_32:
- case OP_CONST_16:
- case OP_CONST_WIDE_16:
- case OP_IF_EQZ:
- case OP_IF_NEZ:
- case OP_IF_LTZ:
- case OP_IF_GEZ:
- case OP_IF_GTZ:
- case OP_IF_LEZ:
- case OP_FILL_ARRAY_DATA:
- case OP_PACKED_SWITCH:
- case OP_SPARSE_SWITCH:
- case OP_ADD_INT_LIT8:
- case OP_RSUB_INT_LIT8:
- case OP_MUL_INT_LIT8:
- case OP_DIV_INT_LIT8:
- case OP_REM_INT_LIT8:
- case OP_AND_INT_LIT8:
- case OP_OR_INT_LIT8:
- case OP_XOR_INT_LIT8:
- case OP_SHL_INT_LIT8:
- case OP_SHR_INT_LIT8:
- case OP_USHR_INT_LIT8:
- case OP_ADD_INT_LIT16:
- case OP_RSUB_INT:
- case OP_MUL_INT_LIT16:
- case OP_DIV_INT_LIT16:
- case OP_REM_INT_LIT16:
- case OP_AND_INT_LIT16:
- case OP_OR_INT_LIT16:
- case OP_XOR_INT_LIT16:
- case OP_IF_EQ:
- case OP_IF_NE:
- case OP_IF_LT:
- case OP_IF_GE:
- case OP_IF_GT:
- case OP_IF_LE:
- case OP_MOVE_FROM16:
- case OP_MOVE_WIDE_FROM16:
- case OP_MOVE_OBJECT_FROM16:
- case OP_CMPL_FLOAT:
- case OP_CMPG_FLOAT:
- case OP_CMPL_DOUBLE:
- case OP_CMPG_DOUBLE:
- case OP_CMP_LONG:
- case OP_AGET:
- case OP_AGET_WIDE:
- case OP_AGET_OBJECT:
- case OP_AGET_BOOLEAN:
- case OP_AGET_BYTE:
- case OP_AGET_CHAR:
- case OP_AGET_SHORT:
- case OP_APUT:
- case OP_APUT_WIDE:
- case OP_APUT_OBJECT:
- case OP_APUT_BOOLEAN:
- case OP_APUT_BYTE:
- case OP_APUT_CHAR:
- case OP_APUT_SHORT:
- case OP_ADD_INT:
- case OP_SUB_INT:
- case OP_MUL_INT:
- case OP_DIV_INT:
- case OP_REM_INT:
- case OP_AND_INT:
- case OP_OR_INT:
- case OP_XOR_INT:
- case OP_SHL_INT:
- case OP_SHR_INT:
- case OP_USHR_INT:
- case OP_ADD_LONG:
- case OP_SUB_LONG:
- case OP_MUL_LONG:
- case OP_DIV_LONG:
- case OP_REM_LONG:
- case OP_AND_LONG:
- case OP_OR_LONG:
- case OP_XOR_LONG:
- case OP_SHL_LONG:
- case OP_SHR_LONG:
- case OP_USHR_LONG:
- case OP_ADD_FLOAT:
- case OP_SUB_FLOAT:
- case OP_MUL_FLOAT:
- case OP_DIV_FLOAT:
- case OP_REM_FLOAT:
- case OP_ADD_DOUBLE:
- case OP_SUB_DOUBLE:
- case OP_MUL_DOUBLE:
- case OP_DIV_DOUBLE:
- case OP_REM_DOUBLE:
- case OP_CONST:
- case OP_CONST_WIDE_32:
- case OP_MOVE_16:
- case OP_MOVE_WIDE_16:
- case OP_MOVE_OBJECT_16:
- case OP_CONST_WIDE:
- indexType = kIndexNone;
- break;
- case OP_CONST_STRING:
- case OP_CONST_STRING_JUMBO:
- indexType = kIndexStringRef;
- break;
- case OP_CONST_CLASS:
- case OP_CHECK_CAST:
- case OP_NEW_INSTANCE:
- case OP_INSTANCE_OF:
- case OP_NEW_ARRAY:
- case OP_FILLED_NEW_ARRAY:
- case OP_FILLED_NEW_ARRAY_RANGE:
- indexType = kIndexTypeRef;
- break;
- case OP_SGET:
- case OP_SGET_WIDE:
- case OP_SGET_OBJECT:
- case OP_SGET_BOOLEAN:
- case OP_SGET_BYTE:
- case OP_SGET_CHAR:
- case OP_SGET_SHORT:
- case OP_SPUT:
- case OP_SPUT_WIDE:
- case OP_SPUT_OBJECT:
- case OP_SPUT_BOOLEAN:
- case OP_SPUT_BYTE:
- case OP_SPUT_CHAR:
- case OP_SPUT_SHORT:
- case OP_IGET:
- case OP_IGET_WIDE:
- case OP_IGET_OBJECT:
- case OP_IGET_BOOLEAN:
- case OP_IGET_BYTE:
- case OP_IGET_CHAR:
- case OP_IGET_SHORT:
- case OP_IPUT:
- case OP_IPUT_WIDE:
- case OP_IPUT_OBJECT:
- case OP_IPUT_BOOLEAN:
- case OP_IPUT_BYTE:
- case OP_IPUT_CHAR:
- case OP_IPUT_SHORT:
- indexType = kIndexFieldRef;
- break;
- case OP_INVOKE_VIRTUAL:
- case OP_INVOKE_SUPER:
- case OP_INVOKE_DIRECT:
- case OP_INVOKE_STATIC:
- case OP_INVOKE_INTERFACE:
- case OP_INVOKE_VIRTUAL_RANGE:
- case OP_INVOKE_SUPER_RANGE:
- case OP_INVOKE_DIRECT_RANGE:
- case OP_INVOKE_STATIC_RANGE:
- case OP_INVOKE_INTERFACE_RANGE:
- indexType = kIndexMethodRef;
- break;
-
- /*
- * Optimized instructions.
- */
- case OP_THROW_VERIFICATION_ERROR:
- indexType = kIndexVaries;
- break;
- case OP_IGET_WIDE_VOLATILE:
- case OP_IPUT_WIDE_VOLATILE:
- case OP_IGET_VOLATILE:
- case OP_IPUT_VOLATILE:
- case OP_IGET_OBJECT_VOLATILE:
- case OP_IPUT_OBJECT_VOLATILE:
- case OP_SGET_OBJECT_VOLATILE:
- case OP_SPUT_OBJECT_VOLATILE:
- case OP_SGET_VOLATILE:
- case OP_SPUT_VOLATILE:
- case OP_SGET_WIDE_VOLATILE:
- case OP_SPUT_WIDE_VOLATILE:
- indexType = kIndexFieldRef;
- break;
- case OP_IGET_QUICK:
- case OP_IGET_WIDE_QUICK:
- case OP_IGET_OBJECT_QUICK:
- case OP_IPUT_QUICK:
- case OP_IPUT_WIDE_QUICK:
- case OP_IPUT_OBJECT_QUICK:
- indexType = kIndexFieldOffset;
- break;
- case OP_INVOKE_VIRTUAL_QUICK:
- case OP_INVOKE_SUPER_QUICK:
- case OP_INVOKE_VIRTUAL_QUICK_RANGE:
- case OP_INVOKE_SUPER_QUICK_RANGE:
- indexType = kIndexVtableOffset;
- break;
- case OP_EXECUTE_INLINE:
- case OP_EXECUTE_INLINE_RANGE:
- indexType = kIndexInlineMethod;
- break;
- case OP_INVOKE_DIRECT_EMPTY:
- indexType = kIndexMethodRef;
- break;
- case OP_RETURN_VOID_BARRIER:
- indexType = kIndexNone;
- break;
-
- /* these should never appear when scanning code */
- case OP_UNUSED_3E:
- case OP_UNUSED_3F:
- case OP_UNUSED_40:
- case OP_UNUSED_41:
- case OP_UNUSED_42:
- case OP_UNUSED_43:
- case OP_UNUSED_73:
- case OP_UNUSED_79:
- case OP_UNUSED_7A:
- case OP_BREAKPOINT:
- case OP_UNUSED_FF:
- indexType = kIndexUnknown;
- break;
-
- /*
- * DO NOT add a "default" clause here. Without it the compiler will
- * complain if an instruction is missing (which is desirable).
- */
- }
-
- indexTypes[opc] = indexType;
- }
-
- return indexTypes;
-}
-
-/*
- * Construct all of the instruction info tables, storing references to
- * them into the given struct. This returns 0 on success or non-zero on
- * failure. If this fails, then no net allocation will have occurred.
- */
-int dexCreateInstructionInfoTables(InstructionInfoTables* info) {
- info->formats = NULL;
- info->indexTypes = NULL;
- info->flags = NULL;
- info->widths = NULL;
-
- info->formats = dexCreateInstrFormatTable();
- info->indexTypes = dexCreateInstrIndexTypeTable();
- info->flags = dexCreateInstrFlagsTable();
- info->widths = dexCreateInstrWidthTable();
-
- if ((info->formats == NULL)
- || (info->indexTypes == NULL)
- || (info->flags == NULL)
- || (info->widths == NULL)) {
- dexFreeInstructionInfoTables(info);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Free up the tables referred to by the given instruction info struct.
- */
-void dexFreeInstructionInfoTables(InstructionInfoTables* info) {
- free(info->formats);
- free(info->indexTypes);
- free(info->flags);
- free(info->widths);
+void dexGetInstructionInfoTables(InstructionInfoTables* info) {
+ *info = gDexOpcodeInfo;
}
/*
@@ -1855,15 +496,14 @@
* Fills out the pieces of "pDec" that are affected by the current
* instruction. Does not touch anything else.
*/
-void dexDecodeInstruction(const InstructionInfoTables* info, const u2* insns,
- DecodedInstruction* pDec)
+void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec)
{
u2 inst = *insns;
OpCode opCode = (OpCode) INST_INST(inst);
- InstructionFormat format = dexGetInstrFormat(info->formats, opCode);
+ InstructionFormat format = dexGetInstrFormat(gOpcodeFormatTable, opCode);
pDec->opCode = opCode;
- pDec->indexType = dexGetInstrIndexType(info->indexTypes, opCode);
+ pDec->indexType = dexGetInstrIndexType(gOpcodeIndexTypeTable, opCode);
switch (format) {
case kFmt10x: // op
@@ -2062,8 +702,7 @@
* works for special OP_NOP entries, including switch statement data tables
* and array data.
*/
-size_t dexGetInstrOrTableWidth(const InstructionWidth* widths,
- const u2* insns)
+size_t dexGetInstrOrTableWidth(const u2* insns)
{
size_t width;
@@ -2076,7 +715,7 @@
u4 len = insns[2] | (((u4)insns[3]) << 16);
width = 4 + (elemWidth * len + 1) / 2;
} else {
- width = dexGetInstrWidth(widths, INST_INST(insns[0]));
+ width = dexGetInstrWidth(gOpcodeWidthTable, INST_INST(insns[0]));
}
return width;
}
diff --git a/libdex/InstrUtils.h b/libdex/InstrUtils.h
index 44e5af2..b4678ff 100644
--- a/libdex/InstrUtils.h
+++ b/libdex/InstrUtils.h
@@ -138,10 +138,9 @@
} InstructionInfoTables;
/*
- * Allocate and populate a 256-element array with instruction widths. A
- * width of zero means the entry does not exist.
+ * Global InstructionInfoTables struct.
*/
-InstructionWidth* dexCreateInstrWidthTable(void);
+extern InstructionInfoTables gDexOpcodeInfo;
/*
* Return the width of the specified instruction, or 0 if not defined.
@@ -158,13 +157,7 @@
* works for special OP_NOP entries, including switch statement data tables
* and array data.
*/
-size_t dexGetInstrOrTableWidth(const InstructionWidth* widths,
- const u2* insns);
-
-/*
- * Allocate and populate a 256-element array with instruction flags.
- */
-InstructionFlags* dexCreateInstrFlagsTable(void);
+size_t dexGetInstrOrTableWidth(const u2* insns);
/*
* Returns the flags for the specified opcode.
@@ -184,11 +177,6 @@
}
/*
- * Allocate and populate a 256-element array with instruction formats.
- */
-InstructionFormat* dexCreateInstrFormatTable(void);
-
-/*
* Return the instruction format for the specified opcode.
*/
DEX_INLINE InstructionFormat dexGetInstrFormat(const InstructionFormat* fmts,
@@ -199,12 +187,6 @@
}
/*
- * Allocate and populate an array with index types for all instructions.
- * Used in conjunction with dexDecodeInstruction.
- */
-InstructionIndexType* dexCreateInstrIndexTypeTable(void);
-
-/*
* Return the instruction index type for the specified opcode.
*/
DEX_INLINE InstructionIndexType dexGetInstrIndexType(
@@ -215,21 +197,14 @@
}
/*
- * Construct all of the instruction info tables, storing references to
- * them into the given struct. This returns 0 on success or non-zero on
- * failure. If this fails, then no net allocation will have occurred.
+ * Copy pointers to all of the instruction info tables into
+ * the given struct.
*/
-int dexCreateInstructionInfoTables(InstructionInfoTables* info);
-
-/*
- * Free up the tables referred to by the given instruction info struct.
- */
-void dexFreeInstructionInfoTables(InstructionInfoTables* info);
+void dexGetInstructionInfoTables(InstructionInfoTables* info);
/*
* Decode the instruction pointed to by "insns".
*/
-void dexDecodeInstruction(const InstructionInfoTables* info, const u2* insns,
- DecodedInstruction* pDec);
+void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec);
#endif /*_LIBDEX_INSTRUTILS*/
diff --git a/libdex/OpCode.h b/libdex/OpCode.h
index 32d3b3e..4c5ae52 100644
--- a/libdex/OpCode.h
+++ b/libdex/OpCode.h
@@ -41,8 +41,8 @@
* immediately below in this file.
*
* Opcode definitions and attributes:
- * - update the instruction info table generators and (if you changed an
- * instruction format) instruction decoder in InstrUtils.c
+ * - update the instruction decoder in InstrUtils.c if you added a new
+ * instruction format.
* - update the instruction format list in InstrUtils.h, if necessary
* - update the parallel definitions in the class dalvik.bytecode.Opcodes
*
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 2069848..e9ae842 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -3557,7 +3557,7 @@
#ifndef NDEBUG
memset(&decInsn, 0x81, sizeof(decInsn));
#endif
- dexDecodeInstruction(&gDvm.instrInfo, insns, &decInsn);
+ dexDecodeInstruction(insns, &decInsn);
int nextFlags = dexGetInstrFlags(gDvm.instrInfo.flags, decInsn.opCode);
diff --git a/vm/analysis/DexVerify.c b/vm/analysis/DexVerify.c
index b35c4ae..654bd01 100644
--- a/vm/analysis/DexVerify.c
+++ b/vm/analysis/DexVerify.c
@@ -33,11 +33,7 @@
*/
bool dvmVerificationStartup(void)
{
- if (dexCreateInstructionInfoTables(&gDvm.instrInfo)) {
- LOGE("Unable to create instruction tables\n");
- return false;
- }
-
+ dexGetInstructionInfoTables(&gDvm.instrInfo);
return true;
}
@@ -46,7 +42,7 @@
*/
void dvmVerificationShutdown(void)
{
- dexFreeInstructionInfoTables(&gDvm.instrInfo);
+ /* No need to do anything here. */
}
/*
@@ -112,7 +108,7 @@
for (i = 0; i < (int) insnCount; /**/) {
- size_t width = dexGetInstrOrTableWidth(gDvm.instrInfo.widths, insns);
+ size_t width = dexGetInstrOrTableWidth(insns);
if (width == 0) {
LOG_VFY_METH(meth,
"VFY: invalid post-opt instruction (0x%04x)\n", *insns);
@@ -817,7 +813,6 @@
const Method* meth = vdata->method;
const DvmDex* pDvmDex = meth->clazz->pDvmDex;
InsnFlags* insnFlags = vdata->insnFlags;
- const InstructionInfoTables* infoTables = &gDvm.instrInfo;
const InstructionFlags* flagTable = gDvm.instrInfo.flags;
const u2* insns = meth->insns;
unsigned int codeOffset;
@@ -833,7 +828,7 @@
DecodedInstruction decInsn;
bool okay = true;
- dexDecodeInstruction(infoTables, meth->insns + codeOffset, &decInsn);
+ dexDecodeInstruction(meth->insns + codeOffset, &decInsn);
/*
* Check register, type, class, field, method, and string indices
diff --git a/vm/analysis/Optimize.c b/vm/analysis/Optimize.c
index 6bc221e..5204096 100644
--- a/vm/analysis/Optimize.c
+++ b/vm/analysis/Optimize.c
@@ -299,7 +299,7 @@
}
}
- width = dexGetInstrOrTableWidth(gDvm.instrInfo.widths, insns);
+ width = dexGetInstrOrTableWidth(insns);
assert(width > 0);
insns += width;
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 3c1e837..af704af 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -40,7 +40,7 @@
}
}
- dexDecodeInstruction(&gDvm.instrInfo, codePtr, decInsn);
+ dexDecodeInstruction(codePtr, decInsn);
if (printMe) {
char *decodedString = dvmCompilerGetDalvikDisassembly(decInsn, NULL);
LOGD("%p: %#06x %s\n", codePtr, opcode, decodedString);
diff --git a/vm/compiler/InlineTransformation.c b/vm/compiler/InlineTransformation.c
index 951da61..f93558c 100644
--- a/vm/compiler/InlineTransformation.c
+++ b/vm/compiler/InlineTransformation.c
@@ -46,7 +46,7 @@
MIR *newGetterMIR = dvmCompilerNew(sizeof(MIR), true);
DecodedInstruction getterInsn;
- dexDecodeInstruction(&gDvm.instrInfo, calleeMethod->insns, &getterInsn);
+ dexDecodeInstruction(calleeMethod->insns, &getterInsn);
if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &getterInsn))
return;
@@ -137,7 +137,7 @@
MIR *newSetterMIR = dvmCompilerNew(sizeof(MIR), true);
DecodedInstruction setterInsn;
- dexDecodeInstruction(&gDvm.instrInfo, calleeMethod->insns, &setterInsn);
+ dexDecodeInstruction(calleeMethod->insns, &setterInsn);
if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &setterInsn))
return;
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index be9d6df..2ae49ca 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -288,7 +288,7 @@
SelfVerificationState state = shadowSpace->selfVerificationState;
DecodedInstruction decInsn;
- dexDecodeInstruction(&gDvm.instrInfo, pc, &decInsn);
+ dexDecodeInstruction(pc, &decInsn);
//LOGD("### DbgIntp(%d): PC: 0x%x endPC: 0x%x state: %d len: %d %s",
// self->threadId, (int)pc, (int)shadowSpace->endPC, state,
@@ -669,7 +669,7 @@
DecodedInstruction nextDecInsn;
const u2 *moveResultPC = lastPC + len;
- dexDecodeInstruction(&gDvm.instrInfo, moveResultPC, &nextDecInsn);
+ dexDecodeInstruction(moveResultPC, &nextDecInsn);
if ((nextDecInsn.opCode != OP_MOVE_RESULT) &&
(nextDecInsn.opCode != OP_MOVE_RESULT_WIDE) &&
(nextDecInsn.opCode != OP_MOVE_RESULT_OBJECT))
@@ -685,8 +685,7 @@
interpState->trace[currTraceRun].frag.isCode = true;
interpState->totalTraceLen++;
- interpState->currRunLen = dexGetInstrOrTableWidth(gDvm.instrInfo.widths,
- moveResultPC);
+ interpState->currRunLen = dexGetInstrOrTableWidth(moveResultPC);
}
/*
@@ -733,7 +732,7 @@
/* First instruction - just remember the PC and exit */
if (lastPC == NULL) break;
/* Grow the trace around the last PC if jitState is kJitTSelect */
- dexDecodeInstruction(&gDvm.instrInfo, lastPC, &decInsn);
+ dexDecodeInstruction(lastPC, &decInsn);
/*
* Treat {PACKED,SPARSE}_SWITCH as trace-ending instructions due
@@ -752,7 +751,7 @@
LOGD("TraceGen: adding %s", dexGetOpcodeName(decInsn.opCode));
#endif
flags = dexGetInstrFlags(gDvm.instrInfo.flags, decInsn.opCode);
- len = dexGetInstrOrTableWidth(gDvm.instrInfo.widths, lastPC);
+ len = dexGetInstrOrTableWidth(lastPC);
offset = lastPC - interpState->method->insns;
assert((unsigned) offset <
dvmGetMethodInsnsSize(interpState->method));