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