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