CodeReader.java revision a2c9b2631e0e0034fdd6518e45a20d27914c731f
1/* 2 * Copyright (C) 2011 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 17package com.android.dx.io; 18 19import com.android.dx.dex.DexException; 20import java.util.BitSet; 21 22/** 23 * Walks through a block of code and calls visitor call backs. 24 */ 25public final class CodeReader { 26 27 private final Instruction[] instructions = new Instruction[] { 28 // 0x00...0x0f 29 new Instruction(1, "nop"), 30 new Instruction(1, "move vA, vB"), 31 new Instruction(2, "move/from vAA, vBBBB"), 32 new Instruction(3, "move/16 vAAAA, vBBBB"), 33 new Instruction(1, "move-wide, vA, vB"), 34 new Instruction(2, "move-wide/from16 vAA, vBBBB"), 35 new Instruction(3, "move-wide/from16 vAAAA, vBBBB"), 36 new Instruction(1, "move-object vA, vB"), 37 new Instruction(2, "move-object/from16 vAA, vBBBB"), 38 new Instruction(3, "move-object/16 vAAAA, vBBBB"), 39 new Instruction(1, "move-result vAA"), 40 new Instruction(1, "move-result-wide vAA"), 41 new Instruction(1, "move-result-object vAA"), 42 new Instruction(1, "move-exception vAA"), 43 new Instruction(1, "return void"), 44 new Instruction(1, "return vAA"), 45 46 // 0x10...0x1f 47 new Instruction(1, "return-wide vAA"), 48 new Instruction(1, "return-object vAA"), 49 new Instruction(1, "const/4 vA, #+B"), 50 new Instruction(2, "const/16 vAA, #+BBBB"), 51 new Instruction(3, "const vAA, #+BBBBBBBB"), 52 new Instruction(2, "const/high16 vAA, #+BBBB0000"), 53 new Instruction(2, "const-wide/16 vAA, #+BBBB"), 54 new Instruction(3, "const-wide/32 vAA, #+BBBBBBBB"), 55 new Instruction(5, "const-wide vAA, #+BBBBBBBBBBBBBBBB"), 56 new Instruction(2, "const-wide/high16 vAA, #+BBBB000000000000"), 57 new Instruction(2, "const-string vAA, string@BBBB"), 58 new Instruction(3, "const-string/jumbo vAA, string@BBBBBBBB"), 59 new Instruction(2, "const-class vAA, type@BBBB"), 60 new Instruction(1, "monitor-enter vAA"), 61 new Instruction(1, "monitor-exit vAA"), 62 new Instruction(2, "check-cast vAA type@BBBB"), 63 64 // 0x20...0x2f 65 new Instruction(2, "instance-of vA, vB, type@CCCC"), 66 new Instruction(1, "array-length vA, vB"), 67 new Instruction(2, "new-instance vAA, type@BBBB"), 68 new Instruction(2, "new-array vA, vB, type@CCCC"), 69 new Instruction(3, "filled-new-array {vD, vE, vF, vG, vA}, type@CCCC"), 70 new Instruction(3, "filled-new-array/range {vCCCC..vNNNN}, type@BBBB"), 71 new FillArrayInstruction(3, "fill-array-data vAA, +BBBBBBBB"), 72 new Instruction(1, "throw vAA"), 73 new Instruction(1, "goto +AA"), 74 new Instruction(2, "goto/16 +AAAA"), 75 new Instruction(3, "goto/32 +AAAAAAAA"), 76 new PackedSwitchInstruction(3, "packed-switch vAA, +BBBBBBBB"), 77 new SparseSwitchInstruction(3, "sparse-switch vAA, +BBBBBBBB"), 78 new Instruction(2, "cmpl-float vAA, vBB, vCC"), 79 new Instruction(2, "cmpg-float vAA, vBB, vCC"), 80 new Instruction(2, "cmpl-double vAA, vBB, vCC"), 81 82 // 0x30...0x3f 83 new Instruction(2, "cmpg-double vAA, vBB, vCC"), 84 new Instruction(2, "cmp-long vAA, vBB, vCC"), 85 new Instruction(2, "if-eq vA, vB, +CCCC"), 86 new Instruction(2, "if-ne vA, vB, +CCCC"), 87 new Instruction(2, "if-lt vA, vB, +CCCC"), 88 new Instruction(2, "if-ge vA, vB, +CCCC"), 89 new Instruction(2, "if-gt vA, vB, +CCCC"), 90 new Instruction(2, "if-le vA, vB, +CCCC"), 91 new Instruction(2, "if-eqz vAA, +BBBB"), 92 new Instruction(2, "if-nez vAA, +BBBB"), 93 new Instruction(2, "if-ltz vAA, +BBBB"), 94 new Instruction(2, "if-gez vAA, +BBBB"), 95 new Instruction(2, "if-gtz vAA, +BBBB"), 96 new Instruction(2, "if-lez vAA, +BBBB"), 97 new UnusedInstruction(), 98 new UnusedInstruction(), 99 100 // 0x40...0x4f 101 new UnusedInstruction(), 102 new UnusedInstruction(), 103 new UnusedInstruction(), 104 new UnusedInstruction(), 105 new Instruction(2, "aget vAA, vBB, vCC"), 106 new Instruction(2, "aget-wide vAA, vBB, vCC"), 107 new Instruction(2, "aget-object vAA, vBB, vCC"), 108 new Instruction(2, "aget-boolean vAA, vBB, vCC"), 109 new Instruction(2, "aget-byte vAA, vBB, vCC"), 110 new Instruction(2, "aget-char vAA, vBB, vCC"), 111 new Instruction(2, "aget-short vAA, vBB, vCC"), 112 new Instruction(2, "aput vAA, vBB, vCC"), 113 new Instruction(2, "aput-wide vAA, vBB, vCC"), 114 new Instruction(2, "aput-object vAA, vBB, vCC"), 115 new Instruction(2, "aput-boolean vAA, vBB, vCC"), 116 new Instruction(2, "aput-byte vAA, vBB, vCC"), 117 118 // 0x50...0x5f 119 new Instruction(2, "aput-char vAA, vBB, vCC"), 120 new Instruction(2, "aput-short vAA, vBB, vCC"), 121 new Instruction(2, "iget vA, vB, field@CCCC"), 122 new Instruction(2, "iget-wide vA, vB, field@CCCC"), 123 new Instruction(2, "iget-object vA, vB, field@CCCC"), 124 new Instruction(2, "iget-boolean vA, vB, field@CCCC"), 125 new Instruction(2, "iget-byte vA, vB, field@CCCC"), 126 new Instruction(2, "iget-char vA, vB, field@CCCC"), 127 new Instruction(2, "iget-short vA, vB, field@CCCC"), 128 new Instruction(2, "iput vA, vB, field@CCCC"), 129 new Instruction(2, "iput-wide vA, vB, field@CCCC"), 130 new Instruction(2, "iput-object vA, vB, field@CCCC"), 131 new Instruction(2, "iput-boolean vA, vB, field@CCCC"), 132 new Instruction(2, "iput-byte vA, vB, field@CCCC"), 133 new Instruction(2, "iput-char vA, vB, field@CCCC"), 134 new Instruction(2, "iput-short vA, vB, field@CCCC"), 135 136 // 0x60...0x6f 137 new Instruction(2, "sget vAA, field@BBBB"), 138 new Instruction(2, "sget-wide vAA, field@BBBB"), 139 new Instruction(2, "sget-object vAA, field@BBBB"), 140 new Instruction(2, "sget-boolean vAA, field@BBBB"), 141 new Instruction(2, "sget-byte vAA, field@BBBB"), 142 new Instruction(2, "sget-char vAA, field@BBBB"), 143 new Instruction(2, "sget-short vAA, field@BBBB"), 144 new Instruction(2, "sput vAA, field@BBBB"), 145 new Instruction(2, "sput-wide vAA, field@BBBB"), 146 new Instruction(2, "sput-object vAA, field@BBBB"), 147 new Instruction(2, "sput-boolean vAA, field@BBBB"), 148 new Instruction(2, "sput-byte vAA, field@BBBB"), 149 new Instruction(2, "sput-char vAA, field@BBBB"), 150 new Instruction(2, "sput-short vAA, field@BBBB"), 151 new Instruction(3, "invoke-virtual {vD, vE, vF, vG, vA}, meth@CCCC"), 152 new Instruction(3, "invoke-super {vD, vE, vF, vG, vA}, meth@CCCC"), 153 154 // 0x70...0x7f 155 new Instruction(3, "invoke-direct {vD, vE, vF, vG, vA}, meth@CCCC"), 156 new Instruction(3, "invoke-static {vD, vE, vF, vG, vA}, meth@CCCC"), 157 new Instruction(3, "invoke-interface {vD, vE, vF, vG, vA}, meth@CCCC"), 158 new UnusedInstruction(), 159 new Instruction(3, "invoke-virtual/range {vCCCC..vNNNN}, meth@BBBB"), 160 new Instruction(3, "invoke-super/range {vCCCC..vNNNN}, meth@BBBB"), 161 new Instruction(3, "invoke-direct/range {vCCCC..vNNNN}, meth@BBBB"), 162 new Instruction(3, "invoke-static/range {vCCCC..vNNNN}, meth@BBBB"), 163 new Instruction(3, "invoke-interface/range {vCCCC..vNNNN}, meth@BBBB"), 164 new UnusedInstruction(), 165 new UnusedInstruction(), 166 new Instruction(1, "neg-int vA, vB"), 167 new Instruction(1, "not-int vA, vB"), 168 new Instruction(1, "neg-long vA, vB"), 169 new Instruction(1, "not-long vA, vB"), 170 new Instruction(1, "neg-float vA, vB"), 171 172 // 0x80...0x8f 173 new Instruction(1, "neg-double vA, vB"), 174 new Instruction(1, "int-to-long vA, vB"), 175 new Instruction(1, "int-to-float vA, vB"), 176 new Instruction(1, "int-to-double vA, vB"), 177 new Instruction(1, "long-to-int vA, vB"), 178 new Instruction(1, "long-to-float vA, vB"), 179 new Instruction(1, "long-to-double vA, vB"), 180 new Instruction(1, "float-to-int vA, vB"), 181 new Instruction(1, "float-to-long vA, vB"), 182 new Instruction(1, "float-to-double vA, vB"), 183 new Instruction(1, "double-to-int vA, vB"), 184 new Instruction(1, "double-to-long vA, vB"), 185 new Instruction(1, "double-to-float vA, vB"), 186 new Instruction(1, "int-to-byte vA, vB"), 187 new Instruction(1, "int-to-char vA, vB"), 188 new Instruction(1, "int-to-short vA, vB"), 189 190 // 0x90...0x9f 191 new Instruction(2, "add-int vAA, vBB, vCC"), 192 new Instruction(2, "sub-int vAA, vBB, vCC"), 193 new Instruction(2, "mul-int vAA, vBB, vCC"), 194 new Instruction(2, "div-int vAA, vBB, vCC"), 195 new Instruction(2, "rem-int vAA, vBB, vCC"), 196 new Instruction(2, "and-int vAA, vBB, vCC"), 197 new Instruction(2, "or-int vAA, vBB, vCC"), 198 new Instruction(2, "xor-int vAA, vBB, vCC"), 199 new Instruction(2, "shl-int vAA, vBB, vCC"), 200 new Instruction(2, "shr-int vAA, vBB, vCC"), 201 new Instruction(2, "ushr-int vAA, vBB, vCC"), 202 new Instruction(2, "add-long vAA, vBB, vCC"), 203 new Instruction(2, "sub-long vAA, vBB, vCC"), 204 new Instruction(2, "mul-long vAA, vBB, vCC"), 205 new Instruction(2, "div-long vAA, vBB, vCC"), 206 new Instruction(2, "rem-long vAA, vBB, vCC"), 207 208 // 0xa0...0xaf 209 new Instruction(2, "and-long vAA, vBB, vCC"), 210 new Instruction(2, "or-long vAA, vBB, vCC"), 211 new Instruction(2, "xor-long vAA, vBB, vCC"), 212 new Instruction(2, "shl-long vAA, vBB, vCC"), 213 new Instruction(2, "shr-long vAA, vBB, vCC"), 214 new Instruction(2, "ushr-long vAA, vBB, vCC"), 215 new Instruction(2, "add-float vAA, vBB, vCC"), 216 new Instruction(2, "sub-float vAA, vBB, vCC"), 217 new Instruction(2, "mul-float vAA, vBB, vCC"), 218 new Instruction(2, "div-float vAA, vBB, vCC"), 219 new Instruction(2, "rem-float vAA, vBB, vCC"), 220 new Instruction(2, "add-double vAA, vBB, vCC"), 221 new Instruction(2, "sub-double vAA, vBB, vCC"), 222 new Instruction(2, "mul-double vAA, vBB, vCC"), 223 new Instruction(2, "div-double vAA, vBB, vCC"), 224 new Instruction(2, "rem-double vAA, vBB, vCC"), 225 226 // 0xb0..0xbf 227 new Instruction(1, "add-int/2addr vA, vB"), 228 new Instruction(1, "sub-int/2addr vA, vB"), 229 new Instruction(1, "mul-int/2addr vA, vB"), 230 new Instruction(1, "div-int/2addr vA, vB"), 231 new Instruction(1, "rem-int/2addr vA, vB"), 232 new Instruction(1, "and-int/2addr vA, vB"), 233 new Instruction(1, "or-int/2addr vA, vB"), 234 new Instruction(1, "xor-int/2addr vA, vB"), 235 new Instruction(1, "shl-int/2addr vA, vB"), 236 new Instruction(1, "shr-int/2addr vA, vB"), 237 new Instruction(1, "ushr-int/2addr vA, vB"), 238 new Instruction(1, "add-long/2addr vA, vB"), 239 new Instruction(1, "sub-long/2addr vA, vB"), 240 new Instruction(1, "mul-long/2addr vA, vB"), 241 new Instruction(1, "div-long/2addr vA, vB"), 242 new Instruction(1, "rem-long/2addr vA, vB"), 243 244 // 0xc0...0xcf 245 new Instruction(1, "and-long/2addr vA, vB"), 246 new Instruction(1, "or-long/2addr vA, vB"), 247 new Instruction(1, "xor-long/2addr vA, vB"), 248 new Instruction(1, "shl-long/2addr vA, vB"), 249 new Instruction(1, "shr-long/2addr vA, vB"), 250 new Instruction(1, "ushr-long/2addr vA, vB"), 251 new Instruction(1, "add-float/2addr vA, vB"), 252 new Instruction(1, "sub-float/2addr vA, vB"), 253 new Instruction(1, "mul-float/2addr vA, vB"), 254 new Instruction(1, "div-float/2addr vA, vB"), 255 new Instruction(1, "rem-float/2addr vA, vB"), 256 new Instruction(1, "add-double/2addr vA, vB"), 257 new Instruction(1, "sub-double/2addr vA, vB"), 258 new Instruction(1, "mul-double/2addr vA, vB"), 259 new Instruction(1, "div-double/2addr vA, vB"), 260 new Instruction(1, "rem-double/2addr vA, vB"), 261 262 // 0xd0...0xdf 263 new Instruction(2, "add-int/lit16 vA, vB, #+CCCC"), 264 new Instruction(2, "rsub-int (reverse subtract) vA, vB, #+CCCC"), 265 new Instruction(2, "mul-int/lit16 vA, vB, #+CCCC"), 266 new Instruction(2, "div-int/lit16 vA, vB, #+CCCC"), 267 new Instruction(2, "rem-int/lit16 vA, vB, #+CCCC"), 268 new Instruction(2, "and-int/lit16 vA, vB, #+CCCC"), 269 new Instruction(2, "or-int/lit16 vA, vB, #+CCCC"), 270 new Instruction(2, "xor-int/lit16 vA, vB, #+CCCC"), 271 new Instruction(2, "add-int/lit8 vAA, vBB, #+CC"), 272 new Instruction(2, "rsub-int/lit8 vAA, vBB, #+CC"), 273 new Instruction(2, "mul-int/lit8 vAA, vBB, #+CC"), 274 new Instruction(2, "div-int/lit8 vAA, vBB, #+CC"), 275 new Instruction(2, "rem-int/lit8 vAA, vBB, #+CC"), 276 new Instruction(2, "and-int/lit8 vAA, vBB, #+CC"), 277 new Instruction(2, "or-int/lit8 vAA, vBB, #+CC"), 278 new Instruction(2, "xor-int/lit8 vAA, vBB, #+CC"), 279 280 // 0xe0...0xef 281 new Instruction(2, "shl-int/lit8 vAA, vBB, #+CC"), 282 new Instruction(2, "shr-int/lit8 vAA, vBB, #+CC"), 283 new Instruction(2, "ushr-int/lit8 vAA, vBB, #+CC"), 284 }; 285 286 /** 287 * Sets {@code visitor} as the visitor for all string instructions. 288 */ 289 public void setStringVisitor(Visitor visitor) { 290 instructions[0x1a].setVisitor("const-string vAA, string@BBBB", visitor); 291 } 292 293 /** 294 * Sets {@code visitor} as the visitor for all jumbo string instructions. 295 */ 296 public void setJumboStringVisitor(Visitor visitor) { 297 instructions[0x1b].setVisitor("const-string/jumbo vAA, string@BBBBBBBB", visitor); 298 } 299 300 /** 301 * Sets {@code visitor} as the visitor for all type instructions. 302 */ 303 public void setTypeVisitor(Visitor visitor) { 304 instructions[0x1c].setVisitor("const-class vAA, type@BBBB", visitor); 305 instructions[0x1f].setVisitor("check-cast vAA type@BBBB", visitor); 306 instructions[0x20].setVisitor("instance-of vA, vB, type@CCCC", visitor); 307 instructions[0x22].setVisitor("new-instance vAA, type@BBBB", visitor); 308 instructions[0x23].setVisitor("new-array vA, vB, type@CCCC", visitor); 309 instructions[0x24].setVisitor("filled-new-array {vD, vE, vF, vG, vA}, type@CCCC", visitor); 310 instructions[0x25].setVisitor("filled-new-array/range {vCCCC..vNNNN}, type@BBBB", visitor); 311 } 312 313 /** 314 * Sets {@code visitor} as the visitor for all field instructions. 315 */ 316 public void setFieldVisitor(Visitor visitor) { 317 instructions[0x52].setVisitor("iget vA, vB, field@CCCC", visitor); 318 instructions[0x53].setVisitor("iget-wide vA, vB, field@CCCC", visitor); 319 instructions[0x54].setVisitor("iget-object vA, vB, field@CCCC", visitor); 320 instructions[0x55].setVisitor("iget-boolean vA, vB, field@CCCC", visitor); 321 instructions[0x56].setVisitor("iget-byte vA, vB, field@CCCC", visitor); 322 instructions[0x57].setVisitor("iget-char vA, vB, field@CCCC", visitor); 323 instructions[0x58].setVisitor("iget-short vA, vB, field@CCCC", visitor); 324 instructions[0x59].setVisitor("iput vA, vB, field@CCCC", visitor); 325 instructions[0x5a].setVisitor("iput-wide vA, vB, field@CCCC", visitor); 326 instructions[0x5b].setVisitor("iput-object vA, vB, field@CCCC", visitor); 327 instructions[0x5c].setVisitor("iput-boolean vA, vB, field@CCCC", visitor); 328 instructions[0x5d].setVisitor("iput-byte vA, vB, field@CCCC", visitor); 329 instructions[0x5e].setVisitor("iput-char vA, vB, field@CCCC", visitor); 330 instructions[0x5f].setVisitor("iput-short vA, vB, field@CCCC", visitor); 331 instructions[0x60].setVisitor("sget vAA, field@BBBB", visitor); 332 instructions[0x61].setVisitor("sget-wide vAA, field@BBBB", visitor); 333 instructions[0x62].setVisitor("sget-object vAA, field@BBBB", visitor); 334 instructions[0x63].setVisitor("sget-boolean vAA, field@BBBB", visitor); 335 instructions[0x64].setVisitor("sget-byte vAA, field@BBBB", visitor); 336 instructions[0x65].setVisitor("sget-char vAA, field@BBBB", visitor); 337 instructions[0x66].setVisitor("sget-short vAA, field@BBBB", visitor); 338 instructions[0x67].setVisitor("sput vAA, field@BBBB", visitor); 339 instructions[0x68].setVisitor("sput-wide vAA, field@BBBB", visitor); 340 instructions[0x69].setVisitor("sput-object vAA, field@BBBB", visitor); 341 instructions[0x6a].setVisitor("sput-boolean vAA, field@BBBB", visitor); 342 instructions[0x6b].setVisitor("sput-byte vAA, field@BBBB", visitor); 343 instructions[0x6c].setVisitor("sput-char vAA, field@BBBB", visitor); 344 instructions[0x6d].setVisitor("sput-short vAA, field@BBBB", visitor); 345 } 346 347 /** 348 * Sets {@code visitor} as the visitor for all method instructions. 349 */ 350 public void setMethodVisitor(Visitor visitor) { 351 instructions[0x6e].setVisitor("invoke-virtual {vD, vE, vF, vG, vA}, meth@CCCC", visitor); 352 instructions[0x6f].setVisitor("invoke-super {vD, vE, vF, vG, vA}, meth@CCCC", visitor); 353 instructions[0x70].setVisitor("invoke-direct {vD, vE, vF, vG, vA}, meth@CCCC", visitor); 354 instructions[0x71].setVisitor("invoke-static {vD, vE, vF, vG, vA}, meth@CCCC", visitor); 355 instructions[0x72].setVisitor("invoke-interface {vD, vE, vF, vG, vA}, meth@CCCC", visitor); 356 instructions[0x74].setVisitor("invoke-virtual/range {vCCCC..vNNNN}, meth@BBBB", visitor); 357 instructions[0x75].setVisitor("invoke-super/range {vCCCC..vNNNN}, meth@BBBB", visitor); 358 instructions[0x76].setVisitor("invoke-direct/range {vCCCC..vNNNN}, meth@BBBB", visitor); 359 instructions[0x77].setVisitor("invoke-static/range {vCCCC..vNNNN}, meth@BBBB", visitor); 360 instructions[0x78].setVisitor("invoke-interface/range {vCCCC..vNNNN}, meth@BBBB", visitor); 361 } 362 363 public void visitAll(short[] instructions) throws DexException { 364 BitSet skippedInstructions = new BitSet(); 365 366 for (int i = 0; i < instructions.length; ) { 367 if (skippedInstructions.get(i)) { 368 i++; 369 continue; 370 } 371 372 int index = instructions[i] & 0xFF; 373 if (index < 0 || index >= this.instructions.length) { 374 throw new DexException("Unhandled instruction at " + i 375 + ": " + Integer.toHexString(index)); 376 } 377 378 Instruction instruction = this.instructions[index]; 379 instruction.mask(instructions, i, skippedInstructions); 380 if (instruction.visitor != null) { 381 instruction.visitor.visit(instruction, instructions, i); 382 } 383 i += instruction.codeUnits; 384 } 385 } 386 387 public static class Instruction { 388 private final String name; 389 private final int codeUnits; 390 private Visitor visitor; 391 392 private Instruction(int codeUnits, String name) { 393 this.name = name; 394 this.codeUnits = codeUnits; 395 } 396 397 public String getName() { 398 return name; 399 } 400 401 /** 402 * Sets the visitor to be notified when this instruction is encountered, 403 * or null if this instruction has no visitor. 404 */ 405 public void setVisitor(String name, Visitor visitor) { 406 if (!this.name.equals(name)) { 407 throw new IllegalArgumentException("Expected " + this.name + " but was " + name); 408 } 409 this.visitor = visitor; 410 } 411 412 protected void mask(short[] instructions, int offset, BitSet skippedInstructions) {} 413 414 @Override public String toString() { 415 return name; 416 } 417 } 418 419 public interface Visitor { 420 void visit(Instruction instruction, short[] instructions, int offset); 421 } 422 423 private static class UnusedInstruction extends Instruction { 424 UnusedInstruction() { 425 super(1, "unused"); 426 } 427 } 428 429 private static class PackedSwitchInstruction extends Instruction { 430 public PackedSwitchInstruction(int codeUnits, String name) { 431 super(codeUnits, name); 432 } 433 @Override protected void mask(short[] instructions, int i, BitSet skippedInstructions) { 434 int offset = (instructions[i + 1] & 0xFFFF) 435 + ((instructions[i + 2] & 0xFFFF) << 16); 436 if (instructions[i + offset] != 0x100) { 437 throw new DexException("Expected packed-switch-payload opcode but was 0x" 438 + Integer.toHexString(instructions[i + offset])); 439 } 440 short size = instructions[i + offset + 1]; 441 skippedInstructions.set(i + offset, i + offset + 4 + (size * 2)); 442 } 443 } 444 445 private static class SparseSwitchInstruction extends Instruction { 446 public SparseSwitchInstruction(int codeUnits, String name) { 447 super(codeUnits, name); 448 } 449 @Override protected void mask(short[] instructions, int i, BitSet skippedInstructions) { 450 int offset = (instructions[i + 1] & 0xFFFF) 451 + ((instructions[i + 2] & 0xFFFF) << 16); 452 if (instructions[i + offset] != 0x200) { 453 throw new DexException("Expected sparse-switch-payload opcode but was 0x" 454 + Integer.toHexString(instructions[i + offset])); 455 } 456 short size = instructions[i + offset + 1]; 457 skippedInstructions.set(i + offset, i + offset + 2 + (size * 4)); 458 } 459 } 460 461 private static class FillArrayInstruction extends Instruction { 462 public FillArrayInstruction(int codeUnits, String name) { 463 super(codeUnits, name); 464 } 465 @Override protected void mask(short[] instructions, int i, BitSet skippedInstructions) { 466 int offset = (instructions[i + 1] & 0xFFFF) 467 + ((instructions[i + 2] & 0xFFFF) << 16); 468 if (instructions[i + offset] != 0x300) { 469 throw new DexException("Expected fill-array-data-payload opcode but was 0x" 470 + Integer.toHexString(instructions[i + offset])); 471 } 472 int bytesPerElement = instructions[i + offset + 1]; 473 int size = (instructions[i + offset + 2] & 0xFFFF) 474 + ((instructions[i + offset + 3] & 0xFFFF) << 4); 475 int totalBytes = size * bytesPerElement; 476 int totalShorts = (totalBytes + 1) / 2; // round up! 477 skippedInstructions.set(i + offset, i + offset + 4 + totalShorts); 478 } 479 } 480} 481