1 /*
2 * Copyright (C) 2017 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 #include "slicer/dex_bytecode.h"
18 #include "slicer/common.h"
19
20 #include <assert.h>
21 #include <array>
22
23 namespace dex {
24
OpcodeFromBytecode(u2 bytecode)25 Opcode OpcodeFromBytecode(u2 bytecode) {
26 Opcode opcode = Opcode(bytecode & 0xff);
27 SLICER_CHECK(opcode != OP_UNUSED_FF);
28 return opcode;
29 }
30
31 // Table that maps each opcode to the index type implied by that opcode
32 static constexpr std::array<InstructionIndexType, kNumPackedOpcodes>
33 gInstructionIndexTypeTable = {
34 kIndexNone, kIndexNone, kIndexNone,
35 kIndexNone, kIndexNone, kIndexNone,
36 kIndexNone, kIndexNone, kIndexNone,
37 kIndexNone, kIndexNone, kIndexNone,
38 kIndexNone, kIndexNone, kIndexNone,
39 kIndexNone, kIndexNone, kIndexNone,
40 kIndexNone, kIndexNone, kIndexNone,
41 kIndexNone, kIndexNone, kIndexNone,
42 kIndexNone, kIndexNone, kIndexStringRef,
43 kIndexStringRef, kIndexTypeRef, kIndexNone,
44 kIndexNone, kIndexTypeRef, kIndexTypeRef,
45 kIndexNone, kIndexTypeRef, kIndexTypeRef,
46 kIndexTypeRef, kIndexTypeRef, kIndexNone,
47 kIndexNone, kIndexNone, kIndexNone,
48 kIndexNone, kIndexNone, kIndexNone,
49 kIndexNone, kIndexNone, kIndexNone,
50 kIndexNone, kIndexNone, kIndexNone,
51 kIndexNone, kIndexNone, kIndexNone,
52 kIndexNone, kIndexNone, kIndexNone,
53 kIndexNone, kIndexNone, kIndexNone,
54 kIndexNone, kIndexNone, kIndexUnknown,
55 kIndexUnknown, kIndexUnknown, kIndexUnknown,
56 kIndexUnknown, kIndexUnknown, kIndexNone,
57 kIndexNone, kIndexNone, kIndexNone,
58 kIndexNone, kIndexNone, kIndexNone,
59 kIndexNone, kIndexNone, kIndexNone,
60 kIndexNone, kIndexNone, kIndexNone,
61 kIndexNone, kIndexFieldRef, kIndexFieldRef,
62 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
63 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
64 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
65 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
66 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
67 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
68 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
69 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
70 kIndexFieldRef, kIndexFieldRef, kIndexMethodRef,
71 kIndexMethodRef, kIndexMethodRef, kIndexMethodRef,
72 kIndexMethodRef, kIndexUnknown, kIndexMethodRef,
73 kIndexMethodRef, kIndexMethodRef, kIndexMethodRef,
74 kIndexMethodRef, kIndexUnknown, kIndexUnknown,
75 kIndexNone, kIndexNone, kIndexNone,
76 kIndexNone, kIndexNone, kIndexNone,
77 kIndexNone, kIndexNone, kIndexNone,
78 kIndexNone, kIndexNone, kIndexNone,
79 kIndexNone, kIndexNone, kIndexNone,
80 kIndexNone, kIndexNone, kIndexNone,
81 kIndexNone, kIndexNone, kIndexNone,
82 kIndexNone, kIndexNone, kIndexNone,
83 kIndexNone, kIndexNone, kIndexNone,
84 kIndexNone, kIndexNone, kIndexNone,
85 kIndexNone, kIndexNone, kIndexNone,
86 kIndexNone, kIndexNone, kIndexNone,
87 kIndexNone, kIndexNone, kIndexNone,
88 kIndexNone, kIndexNone, kIndexNone,
89 kIndexNone, kIndexNone, kIndexNone,
90 kIndexNone, kIndexNone, kIndexNone,
91 kIndexNone, kIndexNone, kIndexNone,
92 kIndexNone, kIndexNone, kIndexNone,
93 kIndexNone, kIndexNone, kIndexNone,
94 kIndexNone, kIndexNone, kIndexNone,
95 kIndexNone, kIndexNone, kIndexNone,
96 kIndexNone, kIndexNone, kIndexNone,
97 kIndexNone, kIndexNone, kIndexNone,
98 kIndexNone, kIndexNone, kIndexNone,
99 kIndexNone, kIndexNone, kIndexNone,
100 kIndexNone, kIndexNone, kIndexNone,
101 kIndexNone, kIndexNone, kIndexNone,
102 kIndexNone, kIndexNone, kIndexNone,
103 kIndexNone, kIndexNone, kIndexNone,
104 kIndexNone, kIndexNone, kIndexNone,
105 kIndexNone, kIndexNone, kIndexNone,
106 kIndexNone, kIndexNone, kIndexNone,
107 kIndexNone, kIndexNone, kIndexNone,
108 kIndexNone, kIndexNone, kIndexNone,
109 kIndexNone, kIndexNone, kIndexFieldRef,
110 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
111 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
112 kIndexFieldRef, kIndexFieldRef, kIndexUnknown,
113 kIndexVaries, kIndexInlineMethod, kIndexInlineMethod,
114 kIndexMethodRef, kIndexNone, kIndexFieldOffset,
115 kIndexFieldOffset, kIndexFieldOffset, kIndexFieldOffset,
116 kIndexFieldOffset, kIndexFieldOffset, kIndexVtableOffset,
117 kIndexVtableOffset, kIndexVtableOffset, kIndexVtableOffset,
118 kIndexFieldRef, kIndexFieldRef, kIndexFieldRef,
119 kIndexUnknown,
120 };
121
GetIndexTypeFromOpcode(Opcode opcode)122 InstructionIndexType GetIndexTypeFromOpcode(Opcode opcode) {
123 return gInstructionIndexTypeTable[opcode];
124 }
125
126 // Table that maps each opcode to the full width of instructions that
127 // use that opcode, in (16-bit) code units. Unimplemented opcodes as
128 // well as the "breakpoint" opcode have a width of zero.
129 static constexpr std::array<u1, kNumPackedOpcodes> gInstructionWidthTable = {
130 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 2, 3,
131 5, 2, 2, 3, 2, 1, 1, 2, 2, 1, 2, 2, 3, 3, 3, 1, 1, 2, 3, 3, 3, 2, 2, 2,
132 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
133 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
134 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,
135 3, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
136 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
137 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
138 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
139 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 3, 3,
140 3, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0,
141 };
142
GetWidthFromOpcode(Opcode opcode)143 size_t GetWidthFromOpcode(Opcode opcode) {
144 return gInstructionWidthTable[opcode];
145 }
146
GetWidthFromBytecode(const u2 * bytecode)147 size_t GetWidthFromBytecode(const u2* bytecode) {
148 size_t width = 0;
149 if (*bytecode == kPackedSwitchSignature) {
150 width = 4 + bytecode[1] * 2;
151 } else if (*bytecode == kSparseSwitchSignature) {
152 width = 2 + bytecode[1] * 4;
153 } else if (*bytecode == kArrayDataSignature) {
154 u2 elemWidth = bytecode[1];
155 u4 len = bytecode[2] | (((u4)bytecode[3]) << 16);
156 // The plus 1 is to round up for odd size and width.
157 width = 4 + (elemWidth * len + 1) / 2;
158 } else {
159 width = GetWidthFromOpcode(OpcodeFromBytecode(bytecode[0]));
160 }
161 return width;
162 }
163
164 // Table that maps each opcode to the instruction flags
165 static constexpr std::array<OpcodeFlags, kNumPackedOpcodes> gOpcodeFlagsTable = {
166 /* NOP */ kInstrCanContinue,
167 /* MOVE */ kInstrCanContinue,
168 /* MOVE_FROM16 */ kInstrCanContinue,
169 /* MOVE_16 */ kInstrCanContinue,
170 /* MOVE_WIDE */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
171 /* MOVE_WIDE_FROM16 */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
172 /* MOVE_WIDE_16 */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
173 /* MOVE_OBJECT */ kInstrCanContinue,
174 /* MOVE_OBJECT_FROM16 */ kInstrCanContinue,
175 /* MOVE_OBJECT_16 */ kInstrCanContinue,
176 /* MOVE_RESULT */ kInstrCanContinue,
177 /* MOVE_RESULT_WIDE */ kInstrCanContinue|kInstrWideRegA,
178 /* MOVE_RESULT_OBJECT */ kInstrCanContinue,
179 /* MOVE_EXCEPTION */ kInstrCanContinue,
180 /* RETURN_VOID */ kInstrCanReturn,
181 /* RETURN */ kInstrCanReturn,
182 /* RETURN_WIDE */ kInstrCanReturn|kInstrWideRegA,
183 /* RETURN_OBJECT */ kInstrCanReturn,
184 /* CONST_4 */ kInstrCanContinue,
185 /* CONST_16 */ kInstrCanContinue,
186 /* CONST */ kInstrCanContinue,
187 /* CONST_HIGH16 */ kInstrCanContinue,
188 /* CONST_WIDE_16 */ kInstrCanContinue|kInstrWideRegA,
189 /* CONST_WIDE_32 */ kInstrCanContinue|kInstrWideRegA,
190 /* CONST_WIDE */ kInstrCanContinue|kInstrWideRegA,
191 /* CONST_WIDE_HIGH16 */ kInstrCanContinue|kInstrWideRegA,
192 /* CONST_STRING */ kInstrCanContinue|kInstrCanThrow,
193 /* CONST_STRING_JUMBO */ kInstrCanContinue|kInstrCanThrow,
194 /* CONST_CLASS */ kInstrCanContinue|kInstrCanThrow,
195 /* MONITOR_ENTER */ kInstrCanContinue|kInstrCanThrow,
196 /* MONITOR_EXIT */ kInstrCanContinue|kInstrCanThrow,
197 /* SLICER_CHECK_CAST */ kInstrCanContinue|kInstrCanThrow,
198 /* INSTANCE_OF */ kInstrCanContinue|kInstrCanThrow,
199 /* ARRAY_LENGTH */ kInstrCanContinue|kInstrCanThrow,
200 /* NEW_INSTANCE */ kInstrCanContinue|kInstrCanThrow,
201 /* NEW_ARRAY */ kInstrCanContinue|kInstrCanThrow,
202 /* FILLED_NEW_ARRAY */ kInstrCanContinue|kInstrCanThrow,
203 /* FILLED_NEW_ARRAY_RANGE */ kInstrCanContinue|kInstrCanThrow,
204 /* FILL_ARRAY_DATA */ kInstrCanContinue,
205 /* THROW */ kInstrCanThrow,
206 /* GOTO */ kInstrCanBranch,
207 /* GOTO_16 */ kInstrCanBranch,
208 /* GOTO_32 */ kInstrCanBranch,
209 /* PACKED_SWITCH */ kInstrCanContinue|kInstrCanSwitch,
210 /* SPARSE_SWITCH */ kInstrCanContinue|kInstrCanSwitch,
211 /* CMPL_FLOAT */ kInstrCanContinue,
212 /* CMPG_FLOAT */ kInstrCanContinue,
213 /* CMPL_DOUBLE */ kInstrCanContinue|kInstrWideRegB|kInstrWideRegC,
214 /* CMPG_DOUBLE */ kInstrCanContinue|kInstrWideRegB|kInstrWideRegC,
215 /* CMP_LONG */ kInstrCanContinue|kInstrWideRegB|kInstrWideRegC,
216 /* IF_EQ */ kInstrCanContinue|kInstrCanBranch,
217 /* IF_NE */ kInstrCanContinue|kInstrCanBranch,
218 /* IF_LT */ kInstrCanContinue|kInstrCanBranch,
219 /* IF_GE */ kInstrCanContinue|kInstrCanBranch,
220 /* IF_GT */ kInstrCanContinue|kInstrCanBranch,
221 /* IF_LE */ kInstrCanContinue|kInstrCanBranch,
222 /* IF_EQZ */ kInstrCanContinue|kInstrCanBranch,
223 /* IF_NEZ */ kInstrCanContinue|kInstrCanBranch,
224 /* IF_LTZ */ kInstrCanContinue|kInstrCanBranch,
225 /* IF_GEZ */ kInstrCanContinue|kInstrCanBranch,
226 /* IF_GTZ */ kInstrCanContinue|kInstrCanBranch,
227 /* IF_LEZ */ kInstrCanContinue|kInstrCanBranch,
228 /* UNUSED_3E */ 0,
229 /* UNUSED_3F */ 0,
230 /* UNUSED_40 */ 0,
231 /* UNUSED_41 */ 0,
232 /* UNUSED_42 */ 0,
233 /* UNUSED_43 */ 0,
234 /* AGET */ kInstrCanContinue|kInstrCanThrow,
235 /* AGET_WIDE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
236 /* AGET_OBJECT */ kInstrCanContinue|kInstrCanThrow,
237 /* AGET_BOOLEAN */ kInstrCanContinue|kInstrCanThrow,
238 /* AGET_BYTE */ kInstrCanContinue|kInstrCanThrow,
239 /* AGET_CHAR */ kInstrCanContinue|kInstrCanThrow,
240 /* AGET_SHORT */ kInstrCanContinue|kInstrCanThrow,
241 /* APUT */ kInstrCanContinue|kInstrCanThrow,
242 /* APUT_WIDE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
243 /* APUT_OBJECT */ kInstrCanContinue|kInstrCanThrow,
244 /* APUT_BOOLEAN */ kInstrCanContinue|kInstrCanThrow,
245 /* APUT_BYTE */ kInstrCanContinue|kInstrCanThrow,
246 /* APUT_CHAR */ kInstrCanContinue|kInstrCanThrow,
247 /* APUT_SHORT */ kInstrCanContinue|kInstrCanThrow,
248 /* IGET */ kInstrCanContinue|kInstrCanThrow,
249 /* IGET_WIDE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
250 /* IGET_OBJECT */ kInstrCanContinue|kInstrCanThrow,
251 /* IGET_BOOLEAN */ kInstrCanContinue|kInstrCanThrow,
252 /* IGET_BYTE */ kInstrCanContinue|kInstrCanThrow,
253 /* IGET_CHAR */ kInstrCanContinue|kInstrCanThrow,
254 /* IGET_SHORT */ kInstrCanContinue|kInstrCanThrow,
255 /* IPUT */ kInstrCanContinue|kInstrCanThrow,
256 /* IPUT_WIDE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
257 /* IPUT_OBJECT */ kInstrCanContinue|kInstrCanThrow,
258 /* IPUT_BOOLEAN */ kInstrCanContinue|kInstrCanThrow,
259 /* IPUT_BYTE */ kInstrCanContinue|kInstrCanThrow,
260 /* IPUT_CHAR */ kInstrCanContinue|kInstrCanThrow,
261 /* IPUT_SHORT */ kInstrCanContinue|kInstrCanThrow,
262 /* SGET */ kInstrCanContinue|kInstrCanThrow,
263 /* SGET_WIDE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
264 /* SGET_OBJECT */ kInstrCanContinue|kInstrCanThrow,
265 /* SGET_BOOLEAN */ kInstrCanContinue|kInstrCanThrow,
266 /* SGET_BYTE */ kInstrCanContinue|kInstrCanThrow,
267 /* SGET_CHAR */ kInstrCanContinue|kInstrCanThrow,
268 /* SGET_SHORT */ kInstrCanContinue|kInstrCanThrow,
269 /* SPUT */ kInstrCanContinue|kInstrCanThrow,
270 /* SPUT_WIDE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
271 /* SPUT_OBJECT */ kInstrCanContinue|kInstrCanThrow,
272 /* SPUT_BOOLEAN */ kInstrCanContinue|kInstrCanThrow,
273 /* SPUT_BYTE */ kInstrCanContinue|kInstrCanThrow,
274 /* SPUT_CHAR */ kInstrCanContinue|kInstrCanThrow,
275 /* SPUT_SHORT */ kInstrCanContinue|kInstrCanThrow,
276 /* INVOKE_VIRTUAL */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
277 /* INVOKE_SUPER */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
278 /* INVOKE_DIRECT */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
279 /* INVOKE_STATIC */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
280 /* INVOKE_INTERFACE */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
281 /* UNUSED_73 */ 0,
282 /* INVOKE_VIRTUAL_RANGE */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
283 /* INVOKE_SUPER_RANGE */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
284 /* INVOKE_DIRECT_RANGE */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
285 /* INVOKE_STATIC_RANGE */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
286 /* INVOKE_INTERFACE_RANGE */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
287 /* UNUSED_79 */ 0,
288 /* UNUSED_7A */ 0,
289 /* NEG_INT */ kInstrCanContinue,
290 /* NOT_INT */ kInstrCanContinue,
291 /* NEG_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
292 /* NOT_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
293 /* NEG_FLOAT */ kInstrCanContinue,
294 /* NEG_DOUBLE */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
295 /* INT_TO_LONG */ kInstrCanContinue|kInstrWideRegA,
296 /* INT_TO_FLOAT */ kInstrCanContinue,
297 /* INT_TO_DOUBLE */ kInstrCanContinue|kInstrWideRegA,
298 /* LONG_TO_INT */ kInstrCanContinue|kInstrWideRegB,
299 /* LONG_TO_FLOAT */ kInstrCanContinue|kInstrWideRegB,
300 /* LONG_TO_DOUBLE */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
301 /* FLOAT_TO_INT */ kInstrCanContinue,
302 /* FLOAT_TO_LONG */ kInstrCanContinue|kInstrWideRegA,
303 /* FLOAT_TO_DOUBLE */ kInstrCanContinue|kInstrWideRegA,
304 /* DOUBLE_TO_INT */ kInstrCanContinue|kInstrWideRegB,
305 /* DOUBLE_TO_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
306 /* DOUBLE_TO_FLOAT */ kInstrCanContinue|kInstrWideRegB,
307 /* INT_TO_BYTE */ kInstrCanContinue,
308 /* INT_TO_CHAR */ kInstrCanContinue,
309 /* INT_TO_SHORT */ kInstrCanContinue,
310 /* ADD_INT */ kInstrCanContinue,
311 /* SUB_INT */ kInstrCanContinue,
312 /* MUL_INT */ kInstrCanContinue,
313 /* DIV_INT */ kInstrCanContinue|kInstrCanThrow,
314 /* REM_INT */ kInstrCanContinue|kInstrCanThrow,
315 /* AND_INT */ kInstrCanContinue,
316 /* OR_INT */ kInstrCanContinue,
317 /* XOR_INT */ kInstrCanContinue,
318 /* SHL_INT */ kInstrCanContinue,
319 /* SHR_INT */ kInstrCanContinue,
320 /* USHR_INT */ kInstrCanContinue,
321 /* ADD_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
322 /* SUB_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
323 /* MUL_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
324 /* DIV_LONG */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
325 /* REM_LONG */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
326 /* AND_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
327 /* OR_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
328 /* XOR_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
329 /* SHL_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
330 /* SHR_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
331 /* USHR_LONG */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
332 /* ADD_FLOAT */ kInstrCanContinue,
333 /* SUB_FLOAT */ kInstrCanContinue,
334 /* MUL_FLOAT */ kInstrCanContinue,
335 /* DIV_FLOAT */ kInstrCanContinue,
336 /* REM_FLOAT */ kInstrCanContinue,
337 /* ADD_DOUBLE */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
338 /* SUB_DOUBLE */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
339 /* MUL_DOUBLE */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
340 /* DIV_DOUBLE */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
341 /* REM_DOUBLE */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB|kInstrWideRegC,
342 /* ADD_INT_2ADDR */ kInstrCanContinue,
343 /* SUB_INT_2ADDR */ kInstrCanContinue,
344 /* MUL_INT_2ADDR */ kInstrCanContinue,
345 /* DIV_INT_2ADDR */ kInstrCanContinue|kInstrCanThrow,
346 /* REM_INT_2ADDR */ kInstrCanContinue|kInstrCanThrow,
347 /* AND_INT_2ADDR */ kInstrCanContinue,
348 /* OR_INT_2ADDR */ kInstrCanContinue,
349 /* XOR_INT_2ADDR */ kInstrCanContinue,
350 /* SHL_INT_2ADDR */ kInstrCanContinue,
351 /* SHR_INT_2ADDR */ kInstrCanContinue,
352 /* USHR_INT_2ADDR */ kInstrCanContinue,
353 /* ADD_LONG_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
354 /* SUB_LONG_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
355 /* MUL_LONG_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
356 /* DIV_LONG_2ADDR */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA|kInstrWideRegB,
357 /* REM_LONG_2ADDR */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA|kInstrWideRegB,
358 /* AND_LONG_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
359 /* OR_LONG_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
360 /* XOR_LONG_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
361 /* SHL_LONG_2ADDR */ kInstrCanContinue|kInstrWideRegA,
362 /* SHR_LONG_2ADDR */ kInstrCanContinue|kInstrWideRegA,
363 /* USHR_LONG_2ADDR */ kInstrCanContinue|kInstrWideRegA,
364 /* ADD_FLOAT_2ADDR */ kInstrCanContinue,
365 /* SUB_FLOAT_2ADDR */ kInstrCanContinue,
366 /* MUL_FLOAT_2ADDR */ kInstrCanContinue,
367 /* DIV_FLOAT_2ADDR */ kInstrCanContinue,
368 /* REM_FLOAT_2ADDR */ kInstrCanContinue,
369 /* ADD_DOUBLE_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
370 /* SUB_DOUBLE_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
371 /* MUL_DOUBLE_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
372 /* DIV_DOUBLE_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
373 /* REM_DOUBLE_2ADDR */ kInstrCanContinue|kInstrWideRegA|kInstrWideRegB,
374 /* ADD_INT_LIT16 */ kInstrCanContinue,
375 /* RSUB_INT */ kInstrCanContinue,
376 /* MUL_INT_LIT16 */ kInstrCanContinue,
377 /* DIV_INT_LIT16 */ kInstrCanContinue|kInstrCanThrow,
378 /* REM_INT_LIT16 */ kInstrCanContinue|kInstrCanThrow,
379 /* AND_INT_LIT16 */ kInstrCanContinue,
380 /* OR_INT_LIT16 */ kInstrCanContinue,
381 /* XOR_INT_LIT16 */ kInstrCanContinue,
382 /* ADD_INT_LIT8 */ kInstrCanContinue,
383 /* RSUB_INT_LIT8 */ kInstrCanContinue,
384 /* MUL_INT_LIT8 */ kInstrCanContinue,
385 /* DIV_INT_LIT8 */ kInstrCanContinue|kInstrCanThrow,
386 /* REM_INT_LIT8 */ kInstrCanContinue|kInstrCanThrow,
387 /* AND_INT_LIT8 */ kInstrCanContinue,
388 /* OR_INT_LIT8 */ kInstrCanContinue,
389 /* XOR_INT_LIT8 */ kInstrCanContinue,
390 /* SHL_INT_LIT8 */ kInstrCanContinue,
391 /* SHR_INT_LIT8 */ kInstrCanContinue,
392 /* USHR_INT_LIT8 */ kInstrCanContinue,
393 /* IGET_VOLATILE */ kInstrCanContinue|kInstrCanThrow,
394 /* IPUT_VOLATILE */ kInstrCanContinue|kInstrCanThrow,
395 /* SGET_VOLATILE */ kInstrCanContinue|kInstrCanThrow,
396 /* SPUT_VOLATILE */ kInstrCanContinue|kInstrCanThrow,
397 /* IGET_OBJECT_VOLATILE */ kInstrCanContinue|kInstrCanThrow,
398 /* IGET_WIDE_VOLATILE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
399 /* IPUT_WIDE_VOLATILE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
400 /* SGET_WIDE_VOLATILE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
401 /* SPUT_WIDE_VOLATILE */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
402 /* BREAKPOINT */ 0,
403 /* THROW_VERIFICATION_ERROR */ kInstrCanThrow,
404 /* EXECUTE_INLINE */ kInstrCanContinue|kInstrCanThrow,
405 /* EXECUTE_INLINE_RANGE */ kInstrCanContinue|kInstrCanThrow,
406 /* INVOKE_OBJECT_INIT_RANGE */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
407 /* RETURN_VOID_BARRIER */ kInstrCanReturn,
408 /* IGET_QUICK */ kInstrCanContinue|kInstrCanThrow,
409 /* IGET_WIDE_QUICK */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
410 /* IGET_OBJECT_QUICK */ kInstrCanContinue|kInstrCanThrow,
411 /* IPUT_QUICK */ kInstrCanContinue|kInstrCanThrow,
412 /* IPUT_WIDE_QUICK */ kInstrCanContinue|kInstrCanThrow|kInstrWideRegA,
413 /* IPUT_OBJECT_QUICK */ kInstrCanContinue|kInstrCanThrow,
414 /* INVOKE_VIRTUAL_QUICK */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
415 /* INVOKE_VIRTUAL_QUICK_RANGE */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
416 /* INVOKE_SUPER_QUICK */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
417 /* INVOKE_SUPER_QUICK_RANGE */ kInstrCanContinue|kInstrCanThrow|kInstrInvoke,
418 /* IPUT_OBJECT_VOLATILE */ kInstrCanContinue|kInstrCanThrow,
419 /* SGET_OBJECT_VOLATILE */ kInstrCanContinue|kInstrCanThrow,
420 /* SPUT_OBJECT_VOLATILE */ kInstrCanContinue|kInstrCanThrow,
421 /* UNUSED_FF */ 0,
422 };
423
424 // Table that maps each opcode to the instruction format
425 static constexpr std::array<InstructionFormat, kNumPackedOpcodes> gInstructionFormatTable = {
426 kFmt10x, kFmt12x, kFmt22x, kFmt32x, kFmt12x, kFmt22x, kFmt32x,
427 kFmt12x, kFmt22x, kFmt32x, kFmt11x, kFmt11x, kFmt11x, kFmt11x,
428 kFmt10x, kFmt11x, kFmt11x, kFmt11x, kFmt11n, kFmt21s, kFmt31i,
429 kFmt21h, kFmt21s, kFmt31i, kFmt51l, kFmt21h, kFmt21c, kFmt31c,
430 kFmt21c, kFmt11x, kFmt11x, kFmt21c, kFmt22c, kFmt12x, kFmt21c,
431 kFmt22c, kFmt35c, kFmt3rc, kFmt31t, kFmt11x, kFmt10t, kFmt20t,
432 kFmt30t, kFmt31t, kFmt31t, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
433 kFmt23x, kFmt22t, kFmt22t, kFmt22t, kFmt22t, kFmt22t, kFmt22t,
434 kFmt21t, kFmt21t, kFmt21t, kFmt21t, kFmt21t, kFmt21t, kFmt00x,
435 kFmt00x, kFmt00x, kFmt00x, kFmt00x, kFmt00x, kFmt23x, kFmt23x,
436 kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
437 kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt22c, kFmt22c,
438 kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c,
439 kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt22c, kFmt21c, kFmt21c,
440 kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c,
441 kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt21c, kFmt35c, kFmt35c,
442 kFmt35c, kFmt35c, kFmt35c, kFmt00x, kFmt3rc, kFmt3rc, kFmt3rc,
443 kFmt3rc, kFmt3rc, kFmt00x, kFmt00x, kFmt12x, kFmt12x, kFmt12x,
444 kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
445 kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
446 kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt23x, kFmt23x, kFmt23x,
447 kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
448 kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
449 kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
450 kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x, kFmt23x,
451 kFmt23x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
452 kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
453 kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
454 kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x,
455 kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt12x, kFmt22s, kFmt22s,
456 kFmt22s, kFmt22s, kFmt22s, kFmt22s, kFmt22s, kFmt22s, kFmt22b,
457 kFmt22b, kFmt22b, kFmt22b, kFmt22b, kFmt22b, kFmt22b, kFmt22b,
458 kFmt22b, kFmt22b, kFmt22b, kFmt22c, kFmt22c, kFmt21c, kFmt21c,
459 kFmt22c, kFmt22c, kFmt22c, kFmt21c, kFmt21c, kFmt00x, kFmt20bc,
460 kFmt35mi, kFmt3rmi, kFmt35c, kFmt10x, kFmt22cs, kFmt22cs, kFmt22cs,
461 kFmt22cs, kFmt22cs, kFmt22cs, kFmt35ms, kFmt3rms, kFmt35ms, kFmt3rms,
462 kFmt22c, kFmt21c, kFmt21c, kFmt00x,
463 };
464
GetFormatFromOpcode(Opcode opcode)465 InstructionFormat GetFormatFromOpcode(Opcode opcode) {
466 return gInstructionFormatTable[opcode];
467 }
468
GetFlagsFromOpcode(Opcode opcode)469 OpcodeFlags GetFlagsFromOpcode(Opcode opcode) {
470 return gOpcodeFlagsTable[opcode];
471 }
472
473 // Dalvik opcode names.
474 static constexpr std::array<const char*, kNumPackedOpcodes> gOpcodeNames = {
475 "nop",
476 "move",
477 "move/from16",
478 "move/16",
479 "move-wide",
480 "move-wide/from16",
481 "move-wide/16",
482 "move-object",
483 "move-object/from16",
484 "move-object/16",
485 "move-result",
486 "move-result-wide",
487 "move-result-object",
488 "move-exception",
489 "return-void",
490 "return",
491 "return-wide",
492 "return-object",
493 "const/4",
494 "const/16",
495 "const",
496 "const/high16",
497 "const-wide/16",
498 "const-wide/32",
499 "const-wide",
500 "const-wide/high16",
501 "const-string",
502 "const-string/jumbo",
503 "const-class",
504 "monitor-enter",
505 "monitor-exit",
506 "check-cast",
507 "instance-of",
508 "array-length",
509 "new-instance",
510 "new-array",
511 "filled-new-array",
512 "filled-new-array/range",
513 "fill-array-data",
514 "throw",
515 "goto",
516 "goto/16",
517 "goto/32",
518 "packed-switch",
519 "sparse-switch",
520 "cmpl-float",
521 "cmpg-float",
522 "cmpl-double",
523 "cmpg-double",
524 "cmp-long",
525 "if-eq",
526 "if-ne",
527 "if-lt",
528 "if-ge",
529 "if-gt",
530 "if-le",
531 "if-eqz",
532 "if-nez",
533 "if-ltz",
534 "if-gez",
535 "if-gtz",
536 "if-lez",
537 "unused-3e",
538 "unused-3f",
539 "unused-40",
540 "unused-41",
541 "unused-42",
542 "unused-43",
543 "aget",
544 "aget-wide",
545 "aget-object",
546 "aget-boolean",
547 "aget-byte",
548 "aget-char",
549 "aget-short",
550 "aput",
551 "aput-wide",
552 "aput-object",
553 "aput-boolean",
554 "aput-byte",
555 "aput-char",
556 "aput-short",
557 "iget",
558 "iget-wide",
559 "iget-object",
560 "iget-boolean",
561 "iget-byte",
562 "iget-char",
563 "iget-short",
564 "iput",
565 "iput-wide",
566 "iput-object",
567 "iput-boolean",
568 "iput-byte",
569 "iput-char",
570 "iput-short",
571 "sget",
572 "sget-wide",
573 "sget-object",
574 "sget-boolean",
575 "sget-byte",
576 "sget-char",
577 "sget-short",
578 "sput",
579 "sput-wide",
580 "sput-object",
581 "sput-boolean",
582 "sput-byte",
583 "sput-char",
584 "sput-short",
585 "invoke-virtual",
586 "invoke-super",
587 "invoke-direct",
588 "invoke-static",
589 "invoke-interface",
590 "unused-73",
591 "invoke-virtual/range",
592 "invoke-super/range",
593 "invoke-direct/range",
594 "invoke-static/range",
595 "invoke-interface/range",
596 "unused-79",
597 "unused-7a",
598 "neg-int",
599 "not-int",
600 "neg-long",
601 "not-long",
602 "neg-float",
603 "neg-double",
604 "int-to-long",
605 "int-to-float",
606 "int-to-double",
607 "long-to-int",
608 "long-to-float",
609 "long-to-double",
610 "float-to-int",
611 "float-to-long",
612 "float-to-double",
613 "double-to-int",
614 "double-to-long",
615 "double-to-float",
616 "int-to-byte",
617 "int-to-char",
618 "int-to-short",
619 "add-int",
620 "sub-int",
621 "mul-int",
622 "div-int",
623 "rem-int",
624 "and-int",
625 "or-int",
626 "xor-int",
627 "shl-int",
628 "shr-int",
629 "ushr-int",
630 "add-long",
631 "sub-long",
632 "mul-long",
633 "div-long",
634 "rem-long",
635 "and-long",
636 "or-long",
637 "xor-long",
638 "shl-long",
639 "shr-long",
640 "ushr-long",
641 "add-float",
642 "sub-float",
643 "mul-float",
644 "div-float",
645 "rem-float",
646 "add-double",
647 "sub-double",
648 "mul-double",
649 "div-double",
650 "rem-double",
651 "add-int/2addr",
652 "sub-int/2addr",
653 "mul-int/2addr",
654 "div-int/2addr",
655 "rem-int/2addr",
656 "and-int/2addr",
657 "or-int/2addr",
658 "xor-int/2addr",
659 "shl-int/2addr",
660 "shr-int/2addr",
661 "ushr-int/2addr",
662 "add-long/2addr",
663 "sub-long/2addr",
664 "mul-long/2addr",
665 "div-long/2addr",
666 "rem-long/2addr",
667 "and-long/2addr",
668 "or-long/2addr",
669 "xor-long/2addr",
670 "shl-long/2addr",
671 "shr-long/2addr",
672 "ushr-long/2addr",
673 "add-float/2addr",
674 "sub-float/2addr",
675 "mul-float/2addr",
676 "div-float/2addr",
677 "rem-float/2addr",
678 "add-double/2addr",
679 "sub-double/2addr",
680 "mul-double/2addr",
681 "div-double/2addr",
682 "rem-double/2addr",
683 "add-int/lit16",
684 "rsub-int",
685 "mul-int/lit16",
686 "div-int/lit16",
687 "rem-int/lit16",
688 "and-int/lit16",
689 "or-int/lit16",
690 "xor-int/lit16",
691 "add-int/lit8",
692 "rsub-int/lit8",
693 "mul-int/lit8",
694 "div-int/lit8",
695 "rem-int/lit8",
696 "and-int/lit8",
697 "or-int/lit8",
698 "xor-int/lit8",
699 "shl-int/lit8",
700 "shr-int/lit8",
701 "ushr-int/lit8",
702 "+iget-volatile",
703 "+iput-volatile",
704 "+sget-volatile",
705 "+sput-volatile",
706 "+iget-object-volatile",
707 "+iget-wide-volatile",
708 "+iput-wide-volatile",
709 "+sget-wide-volatile",
710 "+sput-wide-volatile",
711 "^breakpoint",
712 "^throw-verification-error",
713 "+execute-inline",
714 "+execute-inline/range",
715 "+invoke-object-init/range",
716 "+return-void-barrier",
717 "+iget-quick",
718 "+iget-wide-quick",
719 "+iget-object-quick",
720 "+iput-quick",
721 "+iput-wide-quick",
722 "+iput-object-quick",
723 "+invoke-virtual-quick",
724 "+invoke-virtual-quick/range",
725 "+invoke-super-quick",
726 "+invoke-super-quick/range",
727 "+iput-object-volatile",
728 "+sget-object-volatile",
729 "+sput-object-volatile",
730 "unused-ff",
731 };
732
GetOpcodeName(Opcode opcode)733 const char* GetOpcodeName(Opcode opcode) { return gOpcodeNames[opcode]; }
734
735 // Helpers for DecodeInstruction()
InstA(u2 inst)736 static u4 InstA(u2 inst) { return (inst >> 8) & 0x0f; }
InstB(u2 inst)737 static u4 InstB(u2 inst) { return inst >> 12; }
InstAA(u2 inst)738 static u4 InstAA(u2 inst) { return inst >> 8; }
739
740 // Helper for DecodeInstruction()
FetchU4(const u2 * ptr)741 static u4 FetchU4(const u2* ptr) {
742 return ptr[0] | (u4(ptr[1]) << 16);
743 }
744
745 // Helper for DecodeInstruction()
FetchU8(const u2 * ptr)746 static u8 FetchU8(const u2* ptr) {
747 return FetchU4(ptr) | (u8(FetchU4(ptr + 2)) << 32);
748 }
749
750 // Decode a Dalvik bytecode and extract the individual fields
DecodeInstruction(const u2 * bytecode)751 Instruction DecodeInstruction(const u2* bytecode) {
752 u2 inst = bytecode[0];
753 Opcode opcode = OpcodeFromBytecode(inst);
754 InstructionFormat format = GetFormatFromOpcode(opcode);
755
756 Instruction dec = {};
757 dec.opcode = opcode;
758
759 switch (format) {
760 case kFmt10x: // op
761 break;
762 case kFmt12x: // op vA, vB
763 dec.vA = InstA(inst);
764 dec.vB = InstB(inst);
765 break;
766 case kFmt11n: // op vA, #+B
767 dec.vA = InstA(inst);
768 dec.vB = s4(InstB(inst) << 28) >> 28; // sign extend 4-bit value
769 break;
770 case kFmt11x: // op vAA
771 dec.vA = InstAA(inst);
772 break;
773 case kFmt10t: // op +AA
774 dec.vA = s1(InstAA(inst)); // sign-extend 8-bit value
775 break;
776 case kFmt20t: // op +AAAA
777 dec.vA = s2(bytecode[1]); // sign-extend 16-bit value
778 break;
779 case kFmt20bc: // [opt] op AA, thing@BBBB
780 case kFmt21c: // op vAA, thing@BBBB
781 case kFmt22x: // op vAA, vBBBB
782 dec.vA = InstAA(inst);
783 dec.vB = bytecode[1];
784 break;
785 case kFmt21s: // op vAA, #+BBBB
786 case kFmt21t: // op vAA, +BBBB
787 dec.vA = InstAA(inst);
788 dec.vB = s2(bytecode[1]); // sign-extend 16-bit value
789 break;
790 case kFmt21h: // op vAA, #+BBBB0000[00000000]
791 dec.vA = InstAA(inst);
792 // The value should be treated as right-zero-extended, but we don't
793 // actually do that here. Among other things, we don't know if it's
794 // the top bits of a 32- or 64-bit value.
795 dec.vB = bytecode[1];
796 break;
797 case kFmt23x: // op vAA, vBB, vCC
798 dec.vA = InstAA(inst);
799 dec.vB = bytecode[1] & 0xff;
800 dec.vC = bytecode[1] >> 8;
801 break;
802 case kFmt22b: // op vAA, vBB, #+CC
803 dec.vA = InstAA(inst);
804 dec.vB = bytecode[1] & 0xff;
805 dec.vC = s1(bytecode[1] >> 8); // sign-extend 8-bit value
806 break;
807 case kFmt22s: // op vA, vB, #+CCCC
808 case kFmt22t: // op vA, vB, +CCCC
809 dec.vA = InstA(inst);
810 dec.vB = InstB(inst);
811 dec.vC = s2(bytecode[1]); // sign-extend 16-bit value
812 break;
813 case kFmt22c: // op vA, vB, thing@CCCC
814 case kFmt22cs: // [opt] op vA, vB, field offset CCCC
815 dec.vA = InstA(inst);
816 dec.vB = InstB(inst);
817 dec.vC = bytecode[1];
818 break;
819 case kFmt30t: // op +AAAAAAAA
820 dec.vA = FetchU4(bytecode + 1);
821 break;
822 case kFmt31t: // op vAA, +BBBBBBBB
823 case kFmt31c: // op vAA, string@BBBBBBBB
824 dec.vA = InstAA(inst);
825 dec.vB = FetchU4(bytecode + 1);
826 break;
827 case kFmt32x: // op vAAAA, vBBBB
828 dec.vA = bytecode[1];
829 dec.vB = bytecode[2];
830 break;
831 case kFmt31i: // op vAA, #+BBBBBBBB
832 dec.vA = InstAA(inst);
833 dec.vB = FetchU4(bytecode + 1);
834 break;
835 case kFmt35c: // op {vC, vD, vE, vF, vG}, thing@BBBB
836 case kFmt35ms: // [opt] invoke-virtual+super
837 case kFmt35mi: // [opt] inline invoke
838 {
839 dec.vA = InstB(inst); // This is labeled A in the spec.
840 dec.vB = bytecode[1];
841
842 u2 regList = bytecode[2];
843
844 // Copy the argument registers into the arg[] array, and
845 // also copy the first argument (if any) into vC. (The
846 // Instruction structure doesn't have separate
847 // fields for {vD, vE, vF, vG}, so there's no need to make
848 // copies of those.) Note that cases 5..2 fall through.
849 switch (dec.vA) {
850 case 5:
851 // A fifth arg is verboten for inline invokes
852 SLICER_CHECK(format != kFmt35mi);
853
854 // Per note at the top of this format decoder, the
855 // fifth argument comes from the A field in the
856 // instruction, but it's labeled G in the spec.
857 dec.arg[4] = InstA(inst);
858 // fallthrough
859 case 4:
860 dec.arg[3] = (regList >> 12) & 0x0f;
861 // fallthrough
862 case 3:
863 dec.arg[2] = (regList >> 8) & 0x0f;
864 // fallthrough
865 case 2:
866 dec.arg[1] = (regList >> 4) & 0x0f;
867 // fallthrough
868 case 1:
869 dec.vC = dec.arg[0] = regList & 0x0f;
870 // fallthrough
871 case 0:
872 // Valid, but no need to do anything
873 break;
874 default:
875 SLICER_CHECK(!"Invalid arg count in 35c/35ms/35mi");
876 break;
877 }
878 } break;
879 case kFmt3rc: // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
880 case kFmt3rms: // [opt] invoke-virtual+super/range
881 case kFmt3rmi: // [opt] execute-inline/range
882 dec.vA = InstAA(inst);
883 dec.vB = bytecode[1];
884 dec.vC = bytecode[2];
885 break;
886 case kFmt51l: // op vAA, #+BBBBBBBBBBBBBBBB
887 dec.vA = InstAA(inst);
888 dec.vB_wide = FetchU8(bytecode + 1);
889 break;
890 default:
891 SLICER_FATAL("Can't decode unexpected format 0x%02x", format);
892 }
893
894 return dec;
895 }
896
897 } // namespace dex
898