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_H_ 21 #define LIBDEX_INSTRUTILS_H_ 22 23 #include "DexFile.h" 24 #include "DexOpcodes.h" 25 26 /* 27 * Possible instruction formats associated with Dalvik opcodes. 28 * 29 * See the file opcode-gen/README.txt for information about updating 30 * opcodes and instruction formats. 31 */ 32 enum InstructionFormat { 33 kFmt00x = 0, // unknown format (also used for "breakpoint" opcode) 34 kFmt10x, // op 35 kFmt12x, // op vA, vB 36 kFmt11n, // op vA, #+B 37 kFmt11x, // op vAA 38 kFmt10t, // op +AA 39 kFmt20bc, // [opt] op AA, thing@BBBB 40 kFmt20t, // op +AAAA 41 kFmt22x, // op vAA, vBBBB 42 kFmt21t, // op vAA, +BBBB 43 kFmt21s, // op vAA, #+BBBB 44 kFmt21h, // op vAA, #+BBBB00000[00000000] 45 kFmt21c, // op vAA, thing@BBBB 46 kFmt23x, // op vAA, vBB, vCC 47 kFmt22b, // op vAA, vBB, #+CC 48 kFmt22t, // op vA, vB, +CCCC 49 kFmt22s, // op vA, vB, #+CCCC 50 kFmt22c, // op vA, vB, thing@CCCC 51 kFmt22cs, // [opt] op vA, vB, field offset CCCC 52 kFmt30t, // op +AAAAAAAA 53 kFmt32x, // op vAAAA, vBBBB 54 kFmt31i, // op vAA, #+BBBBBBBB 55 kFmt31t, // op vAA, +BBBBBBBB 56 kFmt31c, // op vAA, string@BBBBBBBB 57 kFmt35c, // op {vC,vD,vE,vF,vG}, thing@BBBB 58 kFmt35ms, // [opt] invoke-virtual+super 59 kFmt3rc, // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB 60 kFmt3rms, // [opt] invoke-virtual+super/range 61 kFmt51l, // op vAA, #+BBBBBBBBBBBBBBBB 62 kFmt35mi, // [opt] inline invoke 63 kFmt3rmi, // [opt] inline invoke/range 64 kFmt33x, // exop vAA, vBB, vCCCC 65 kFmt32s, // exop vAA, vBB, #+CCCC 66 kFmt40sc, // [opt] exop AAAA, thing@BBBBBBBB 67 kFmt41c, // exop vAAAA, thing@BBBBBBBB 68 kFmt52c, // exop vAAAA, vBBBB, thing@CCCCCCCC 69 kFmt5rc, // exop {vCCCC .. v(CCCC+AAAA-1)}, thing@BBBBBBBB 70 }; 71 72 /* 73 * Types of indexed reference that are associated with opcodes whose 74 * formats include such an indexed reference (e.g., 21c and 35c). 75 */ 76 enum InstructionIndexType { 77 kIndexUnknown = 0, 78 kIndexNone, // has no index 79 kIndexVaries, // "It depends." Used for throw-verification-error 80 kIndexTypeRef, // type reference index 81 kIndexStringRef, // string reference index 82 kIndexMethodRef, // method reference index 83 kIndexFieldRef, // field reference index 84 kIndexInlineMethod, // inline method index (for inline linked methods) 85 kIndexVtableOffset, // vtable offset (for static linked methods) 86 kIndexFieldOffset // field offset (for static linked fields) 87 }; 88 89 /* 90 * Instruction width implied by an opcode's format; a value in the 91 * range 0 to 5. Note that there are special "pseudo-instructions" 92 * which are used to encode switch and data tables, and these don't 93 * have a fixed width. See dexGetWidthFromInstruction(), below. 94 */ 95 typedef u1 InstructionWidth; 96 97 /* 98 * Opcode control flow flags, used by the verifier and JIT. 99 */ 100 typedef u1 OpcodeFlags; 101 enum OpcodeFlagsBits { 102 kInstrCanBranch = 1, // conditional or unconditional branch 103 kInstrCanContinue = 1 << 1, // flow can continue to next statement 104 kInstrCanSwitch = 1 << 2, // switch statement 105 kInstrCanThrow = 1 << 3, // could cause an exception to be thrown 106 kInstrCanReturn = 1 << 4, // returns, no additional statements 107 kInstrInvoke = 1 << 5, // a flavor of invoke 108 }; 109 110 /* 111 * Struct that includes a pointer to each of the opcode information 112 * tables. 113 * 114 * Note: We use "u1*" here instead of the names of the enumerated 115 * types to guarantee that elements don't use much space. We hold out 116 * hope for a standard way to indicate the size of an enumerated type 117 * that works for both C and C++, but in the mean time, this will 118 * suffice. 119 */ 120 struct InstructionInfoTables { 121 u1* formats; /* InstructionFormat elements */ 122 u1* indexTypes; /* InstructionIndexType elements */ 123 OpcodeFlags* flags; 124 InstructionWidth* widths; 125 }; 126 127 /* 128 * Global InstructionInfoTables struct. 129 */ 130 extern InstructionInfoTables gDexOpcodeInfo; 131 132 /* 133 * Holds the contents of a decoded instruction. 134 */ 135 struct DecodedInstruction { 136 u4 vA; 137 u4 vB; 138 u8 vB_wide; /* for kFmt51l */ 139 u4 vC; 140 u4 arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */ 141 Opcode opcode; 142 InstructionIndexType indexType; 143 }; 144 145 /* 146 * Return the instruction width of the specified opcode, or 0 if not defined. 147 */ 148 DEX_INLINE size_t dexGetWidthFromOpcode(Opcode opcode) 149 { 150 assert((u4) opcode < kNumPackedOpcodes); 151 return gDexOpcodeInfo.widths[opcode]; 152 } 153 154 /* 155 * Return the width of the specified instruction, or 0 if not defined. Also 156 * works for special OP_NOP entries, including switch statement data tables 157 * and array data. 158 */ 159 size_t dexGetWidthFromInstruction(const u2* insns); 160 161 /* 162 * Returns the flags for the specified opcode. 163 */ 164 DEX_INLINE OpcodeFlags dexGetFlagsFromOpcode(Opcode opcode) 165 { 166 assert((u4) opcode < kNumPackedOpcodes); 167 return gDexOpcodeInfo.flags[opcode]; 168 } 169 170 /* 171 * Returns true if the given flags represent a goto (unconditional branch). 172 */ 173 DEX_INLINE bool dexIsGoto(OpcodeFlags flags) 174 { 175 return (flags & (kInstrCanBranch | kInstrCanContinue)) == kInstrCanBranch; 176 } 177 178 /* 179 * Return the instruction format for the specified opcode. 180 */ 181 DEX_INLINE InstructionFormat dexGetFormatFromOpcode(Opcode opcode) 182 { 183 assert((u4) opcode < kNumPackedOpcodes); 184 return (InstructionFormat) gDexOpcodeInfo.formats[opcode]; 185 } 186 187 /* 188 * Return the instruction index type for the specified opcode. 189 */ 190 DEX_INLINE InstructionIndexType dexGetIndexTypeFromOpcode(Opcode opcode) 191 { 192 assert((u4) opcode < kNumPackedOpcodes); 193 return (InstructionIndexType) gDexOpcodeInfo.indexTypes[opcode]; 194 } 195 196 /* 197 * Decode the instruction pointed to by "insns". 198 */ 199 void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec); 200 201 #endif // LIBDEX_INSTRUTILS_H_ 202