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 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 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 143 size_t GetWidthFromOpcode(Opcode opcode) { 144 return gInstructionWidthTable[opcode]; 145 } 146 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 465 InstructionFormat GetFormatFromOpcode(Opcode opcode) { 466 return gInstructionFormatTable[opcode]; 467 } 468 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 733 const char* GetOpcodeName(Opcode opcode) { return gOpcodeNames[opcode]; } 734 735 // Helpers for DecodeInstruction() 736 static u4 InstA(u2 inst) { return (inst >> 8) & 0x0f; } 737 static u4 InstB(u2 inst) { return inst >> 12; } 738 static u4 InstAA(u2 inst) { return inst >> 8; } 739 740 // Helper for DecodeInstruction() 741 static u4 FetchU4(const u2* ptr) { 742 return ptr[0] | (u4(ptr[1]) << 16); 743 } 744 745 // Helper for DecodeInstruction() 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 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