1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 163a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dalvik instruction utility functions. 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 20375fb116bcb817b37509ab579dbd55cdbb765cbfCarl Shapiro#ifndef LIBDEX_INSTRUTILS_H_ 21375fb116bcb817b37509ab579dbd55cdbb765cbfCarl Shapiro#define LIBDEX_INSTRUTILS_H_ 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "DexFile.h" 24df4daaf8f41e3dcaa8221f54273338160dd43138Dan Bornstein#include "DexOpcodes.h" 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 274b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * Possible instruction formats associated with Dalvik opcodes. 28de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 29758a6733f7d1a525aa1530e008cab8a912e7a084Dan Bornstein * See the file opcode-gen/README.txt for information about updating 30758a6733f7d1a525aa1530e008cab8a912e7a084Dan Bornstein * opcodes and instruction formats. 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 32bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiroenum InstructionFormat { 338424432a87c784547e4510bca538eaedc312e40dDan Bornstein kFmt00x = 0, // unknown format (also used for "breakpoint" opcode) 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt10x, // op 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt12x, // op vA, vB 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt11n, // op vA, #+B 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt11x, // op vAA 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt10t, // op +AA 39d325011fc98e0f1179d467bbc284cccea72f560bAndy McFadden kFmt20bc, // [opt] op AA, thing@BBBB 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt20t, // op +AAAA 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt22x, // op vAA, vBBBB 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt21t, // op vAA, +BBBB 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt21s, // op vAA, #+BBBB 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt21h, // op vAA, #+BBBB00000[00000000] 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt21c, // op vAA, thing@BBBB 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt23x, // op vAA, vBB, vCC 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt22b, // op vAA, vBB, #+CC 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt22t, // op vA, vB, +CCCC 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt22s, // op vA, vB, #+CCCC 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt22c, // op vA, vB, thing@CCCC 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt22cs, // [opt] op vA, vB, field offset CCCC 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt30t, // op +AAAAAAAA 53d325011fc98e0f1179d467bbc284cccea72f560bAndy McFadden kFmt32x, // op vAAAA, vBBBB 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt31i, // op vAA, #+BBBBBBBB 55d325011fc98e0f1179d467bbc284cccea72f560bAndy McFadden kFmt31t, // op vAA, +BBBBBBBB 56d325011fc98e0f1179d467bbc284cccea72f560bAndy McFadden kFmt31c, // op vAA, string@BBBBBBBB 577b3e9b0886f2b716b004f0377866988ae39a136eDan Bornstein kFmt35c, // op {vC,vD,vE,vF,vG}, thing@BBBB 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt35ms, // [opt] invoke-virtual+super 594a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein kFmt3rc, // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFmt3rms, // [opt] invoke-virtual+super/range 61d325011fc98e0f1179d467bbc284cccea72f560bAndy McFadden kFmt51l, // op vAA, #+BBBBBBBBBBBBBBBB 627b3e9b0886f2b716b004f0377866988ae39a136eDan Bornstein kFmt35mi, // [opt] inline invoke 637b3e9b0886f2b716b004f0377866988ae39a136eDan Bornstein kFmt3rmi, // [opt] inline invoke/range 64bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro}; 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 674b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * Types of indexed reference that are associated with opcodes whose 684b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * formats include such an indexed reference (e.g., 21c and 35c). 6944a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein */ 70bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiroenum InstructionIndexType { 7144a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein kIndexUnknown = 0, 7244a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein kIndexNone, // has no index 7344a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein kIndexVaries, // "It depends." Used for throw-verification-error 741530c3e6952581aa20ac1e06562a49b9d70bc2b6Dan Bornstein kIndexTypeRef, // type reference index 7544a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein kIndexStringRef, // string reference index 7644a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein kIndexMethodRef, // method reference index 7744a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein kIndexFieldRef, // field reference index 7844a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein kIndexInlineMethod, // inline method index (for inline linked methods) 7944a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein kIndexVtableOffset, // vtable offset (for static linked methods) 8044a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein kIndexFieldOffset // field offset (for static linked fields) 81bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro}; 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 84e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein * Instruction width implied by an opcode's format; a value in the 85e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein * range 0 to 5. Note that there are special "pseudo-instructions" 86e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein * which are used to encode switch and data tables, and these don't 87e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein * have a fixed width. See dexGetWidthFromInstruction(), below. 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 894b6e9baa06c39376496a1860972a68924c8d4440Dan Bornsteintypedef u1 InstructionWidth; 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 924b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * Opcode control flow flags, used by the verifier and JIT. 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 94e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornsteintypedef u1 OpcodeFlags; 95e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornsteinenum OpcodeFlagsBits { 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInstrCanBranch = 1, // conditional or unconditional branch 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInstrCanContinue = 1 << 1, // flow can continue to next statement 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInstrCanSwitch = 1 << 2, // switch statement 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInstrCanThrow = 1 << 3, // could cause an exception to be thrown 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInstrCanReturn = 1 << 4, // returns, no additional statements 101ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng kInstrInvoke = 1 << 5, // a flavor of invoke 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 10444a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein/* 1054b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * Struct that includes a pointer to each of the opcode information 10644a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein * tables. 1074b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * 1084b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * Note: We use "u1*" here instead of the names of the enumerated 1094b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * types to guarantee that elements don't use much space. We hold out 1104b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * hope for a standard way to indicate the size of an enumerated type 1114b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * that works for both C and C++, but in the mean time, this will 1124b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * suffice. 11344a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein */ 114bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapirostruct InstructionInfoTables { 115e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein u1* formats; /* InstructionFormat elements */ 116e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein u1* indexTypes; /* InstructionIndexType elements */ 117e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein OpcodeFlags* flags; 1180f737c5778b9661bdb0b978f4bd29ccbcd73b5fbDan Bornstein InstructionWidth* widths; 119bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro}; 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 122543223954993a19fa96670692bc7aa55d851966bDan Bornstein * Global InstructionInfoTables struct. 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 124543223954993a19fa96670692bc7aa55d851966bDan Bornsteinextern InstructionInfoTables gDexOpcodeInfo; 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1274b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein * Holds the contents of a decoded instruction. 1284b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein */ 129bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapirostruct DecodedInstruction { 1304b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein u4 vA; 1314b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein u4 vB; 1324b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein u8 vB_wide; /* for kFmt51l */ 1334b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein u4 vC; 1344b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein u4 arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */ 1354b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein Opcode opcode; 1364b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein InstructionIndexType indexType; 137bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro}; 1384b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein 1394b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein/* 140e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein * Return the instruction width of the specified opcode, or 0 if not defined. 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 142e485276c6ba778cafa373b3b5c867f84e91b0bfdDan BornsteinDEX_INLINE size_t dexGetWidthFromOpcode(Opcode opcode) 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 14444209fab6f9a58368809ca278f04e5c9384e7515Dan Bornstein assert((u4) opcode < kNumPackedOpcodes); 1459a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein return gDexOpcodeInfo.widths[opcode]; 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the width of the specified instruction, or 0 if not defined. Also 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * works for special OP_NOP entries, including switch statement data tables 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and array data. 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 153e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornsteinsize_t dexGetWidthFromInstruction(const u2* insns); 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the flags for the specified opcode. 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 158e485276c6ba778cafa373b3b5c867f84e91b0bfdDan BornsteinDEX_INLINE OpcodeFlags dexGetFlagsFromOpcode(Opcode opcode) 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 16044209fab6f9a58368809ca278f04e5c9384e7515Dan Bornstein assert((u4) opcode < kNumPackedOpcodes); 1619a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein return gDexOpcodeInfo.flags[opcode]; 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 165c2b486fe6e49555c3a5df0702d04c20b6d6a33c4Dan Bornstein * Returns true if the given flags represent a goto (unconditional branch). 166c2b486fe6e49555c3a5df0702d04c20b6d6a33c4Dan Bornstein */ 167e485276c6ba778cafa373b3b5c867f84e91b0bfdDan BornsteinDEX_INLINE bool dexIsGoto(OpcodeFlags flags) 168c2b486fe6e49555c3a5df0702d04c20b6d6a33c4Dan Bornstein{ 169c2b486fe6e49555c3a5df0702d04c20b6d6a33c4Dan Bornstein return (flags & (kInstrCanBranch | kInstrCanContinue)) == kInstrCanBranch; 170c2b486fe6e49555c3a5df0702d04c20b6d6a33c4Dan Bornstein} 171c2b486fe6e49555c3a5df0702d04c20b6d6a33c4Dan Bornstein 172c2b486fe6e49555c3a5df0702d04c20b6d6a33c4Dan Bornstein/* 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the instruction format for the specified opcode. 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 175e485276c6ba778cafa373b3b5c867f84e91b0bfdDan BornsteinDEX_INLINE InstructionFormat dexGetFormatFromOpcode(Opcode opcode) 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 17744209fab6f9a58368809ca278f04e5c9384e7515Dan Bornstein assert((u4) opcode < kNumPackedOpcodes); 1784b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein return (InstructionFormat) gDexOpcodeInfo.formats[opcode]; 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18244a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein * Return the instruction index type for the specified opcode. 18344a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein */ 184e485276c6ba778cafa373b3b5c867f84e91b0bfdDan BornsteinDEX_INLINE InstructionIndexType dexGetIndexTypeFromOpcode(Opcode opcode) 18544a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein{ 18644209fab6f9a58368809ca278f04e5c9384e7515Dan Bornstein assert((u4) opcode < kNumPackedOpcodes); 1874b6e9baa06c39376496a1860972a68924c8d4440Dan Bornstein return (InstructionIndexType) gDexOpcodeInfo.indexTypes[opcode]; 18844a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein} 18944a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein 19044a38f4a6a1cde0490e78b7de3b27906c6c81078Dan Bornstein/* 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Decode the instruction pointed to by "insns". 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 193543223954993a19fa96670692bc7aa55d851966bDan Bornsteinvoid dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec); 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 195375fb116bcb817b37509ab579dbd55cdbb765cbfCarl Shapiro#endif // LIBDEX_INSTRUTILS_H_ 196