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