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