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