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