1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * Dalvik instruction utility functions. 19 */ 20 #ifndef _LIBDEX_INSTRUTILS 21 #define _LIBDEX_INSTRUTILS 22 23 #include "DexFile.h" 24 #include "OpCode.h" 25 26 /* 27 * Dalvik-defined instruction formats. 28 * 29 * (This defines InstructionFormat as an unsigned char to reduce the size 30 * of the table. This isn't necessary with some compilers, which use an 31 * integer width appropriate for the number of enum values.) 32 * 33 * If you add or delete a format, you have to change some or all of: 34 * - this enum 35 * - the switch inside dexDecodeInstruction() in InstrUtils.c 36 * - the switch inside dumpInstruction() in DexDump.c 37 */ 38 typedef unsigned char InstructionFormat; 39 enum InstructionFormat { 40 kFmtUnknown = 0, 41 kFmt10x, // op 42 kFmt12x, // op vA, vB 43 kFmt11n, // op vA, #+B 44 kFmt11x, // op vAA 45 kFmt10t, // op +AA 46 kFmt20bc, // op AA, thing@BBBB 47 kFmt20t, // op +AAAA 48 kFmt22x, // op vAA, vBBBB 49 kFmt21t, // op vAA, +BBBB 50 kFmt21s, // op vAA, #+BBBB 51 kFmt21h, // op vAA, #+BBBB00000[00000000] 52 kFmt21c, // op vAA, thing@BBBB 53 kFmt23x, // op vAA, vBB, vCC 54 kFmt22b, // op vAA, vBB, #+CC 55 kFmt22t, // op vA, vB, +CCCC 56 kFmt22s, // op vA, vB, #+CCCC 57 kFmt22c, // op vA, vB, thing@CCCC 58 kFmt22cs, // [opt] op vA, vB, field offset CCCC 59 kFmt32x, // op vAAAA, vBBBB 60 kFmt30t, // op +AAAAAAAA 61 kFmt31t, // op vAA, +BBBBBBBB 62 kFmt31i, // op vAA, #+BBBBBBBB 63 kFmt31c, // op vAA, thing@BBBBBBBB 64 kFmt35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG) 65 kFmt35ms, // [opt] invoke-virtual+super 66 kFmt35fs, // [opt] invoke-interface 67 kFmt3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB 68 kFmt3rms, // [opt] invoke-virtual+super/range 69 kFmt3rfs, // [opt] invoke-interface/range 70 kFmt3inline, // [opt] inline invoke 71 kFmt51l, // op vAA, #+BBBBBBBBBBBBBBBB 72 }; 73 74 /* 75 * Holds the contents of a decoded instruction. 76 */ 77 typedef struct DecodedInstruction { 78 u4 vA; 79 u4 vB; 80 u8 vB_wide; /* for kFmt51l */ 81 u4 vC; 82 u4 arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */ 83 OpCode opCode; 84 } DecodedInstruction; 85 86 /* 87 * Instruction width, a value in the range -3 to 5. 88 */ 89 typedef signed char InstructionWidth; 90 91 /* 92 * Instruction flags, used by the verifier to determine where control 93 * can flow to next. 94 */ 95 typedef unsigned char InstructionFlags; 96 enum InstructionFlags { 97 kInstrCanBranch = 1, // conditional or unconditional branch 98 kInstrCanContinue = 1 << 1, // flow can continue to next statement 99 kInstrCanSwitch = 1 << 2, // switch statement 100 kInstrCanThrow = 1 << 3, // could cause an exception to be thrown 101 kInstrCanReturn = 1 << 4, // returns, no additional statements 102 kInstrInvoke = 1 << 5, // a flavor of invoke 103 kInstrUnconditional = 1 << 6, // unconditional branch 104 }; 105 106 107 /* 108 * Allocate and populate a 256-element array with instruction widths. A 109 * width of zero means the entry does not exist. 110 */ 111 InstructionWidth* dexCreateInstrWidthTable(void); 112 113 /* 114 * Returns the width of the specified instruction, or 0 if not defined. 115 * Optimized instructions use negative values. 116 */ dexGetInstrWidth(const InstructionWidth * widths,OpCode opCode)117 DEX_INLINE int dexGetInstrWidth(const InstructionWidth* widths, OpCode opCode) 118 { 119 // assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions); 120 return widths[opCode]; 121 } 122 123 /* 124 * Return the width of the specified instruction, or 0 if not defined. 125 */ dexGetInstrWidthAbs(const InstructionWidth * widths,OpCode opCode)126 DEX_INLINE int dexGetInstrWidthAbs(const InstructionWidth* widths,OpCode opCode) 127 { 128 //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions); 129 130 int val = dexGetInstrWidth(widths, opCode); 131 if (val < 0) 132 val = -val; 133 /* XXX - the no-compare trick may be a cycle slower on ARM */ 134 return val; 135 } 136 137 /* 138 * Return the width of the specified instruction, or 0 if not defined. Also 139 * works for special OP_NOP entries, including switch statement data tables 140 * and array data. 141 */ 142 int dexGetInstrOrTableWidthAbs(const InstructionWidth* widths, const u2* insns); 143 144 145 /* 146 * Allocate and populate a 256-element array with instruction flags. 147 */ 148 InstructionFlags* dexCreateInstrFlagsTable(void); 149 150 /* 151 * Returns the flags for the specified opcode. 152 */ dexGetInstrFlags(const InstructionFlags * flags,OpCode opCode)153 DEX_INLINE int dexGetInstrFlags(const InstructionFlags* flags, OpCode opCode) 154 { 155 //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions); 156 return flags[opCode]; 157 } 158 159 160 /* 161 * Allocate and populate a 256-element array with instruction formats. 162 */ 163 InstructionFormat* dexCreateInstrFormatTable(void); 164 165 /* 166 * Return the instruction format for the specified opcode. 167 */ dexGetInstrFormat(const InstructionFormat * fmts,OpCode opCode)168 DEX_INLINE InstructionFormat dexGetInstrFormat(const InstructionFormat* fmts, 169 OpCode opCode) 170 { 171 //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions); 172 return fmts[opCode]; 173 } 174 175 /* 176 * Decode the instruction pointed to by "insns". 177 */ 178 void dexDecodeInstruction(const InstructionFormat* fmts, const u2* insns, 179 DecodedInstruction* pDec); 180 181 #endif /*_LIBDEX_INSTRUTILS*/ 182