1 19 20 package edu.umd.cs.findbugs.visitclass; 21 22 import java.io.ByteArrayInputStream ; 23 import java.io.DataInputStream ; 24 import java.io.IOException ; 25 import java.text.NumberFormat ; 26 import java.util.HashMap ; 27 28 import org.apache.bcel.classfile.Code; 29 import org.apache.bcel.classfile.CodeException; 30 import org.apache.bcel.classfile.Constant; 31 import org.apache.bcel.classfile.ConstantCP; 32 import org.apache.bcel.classfile.ConstantClass; 33 import org.apache.bcel.classfile.ConstantDouble; 34 import org.apache.bcel.classfile.ConstantFieldref; 35 import org.apache.bcel.classfile.ConstantFloat; 36 import org.apache.bcel.classfile.ConstantInteger; 37 import org.apache.bcel.classfile.ConstantInterfaceMethodref; 38 import org.apache.bcel.classfile.ConstantLong; 39 import org.apache.bcel.classfile.ConstantMethodref; 40 import org.apache.bcel.classfile.ConstantNameAndType; 41 import org.apache.bcel.classfile.ConstantString; 42 import org.apache.bcel.classfile.LineNumberTable; 43 44 import edu.umd.cs.findbugs.annotations.SuppressWarnings; 45 46 abstract public class DismantleBytecode extends AnnotationVisitor { 47 48 private int opcode; 49 private boolean opcodeIsWide; 50 private int PC,nextPC; 51 private int branchOffset; 52 private int branchTarget; 53 private int branchFallThrough; 54 private int[] switchOffsets; 55 private int[] switchLabels; 56 private int[] prevOpcode = new int[32]; 57 private int currentPosInPrevOpcodeBuffer; 58 private int sizePrevOpcodeBuffer; 59 private int defaultSwitchOffset; 60 private String classConstantOperand; 61 private String dottedClassConstantOperand; 62 private String nameConstantOperand; 63 private String sigConstantOperand; 64 private String dottedSigConstantOperand; 65 private String stringConstantOperand; 66 private String refConstantOperand; 67 private boolean refFieldIsStatic; 68 private Constant constantRefOperand; 69 private int intConstant; 70 private long longConstant; 71 private float floatConstant; 72 private double doubleConstant; 73 private int registerOperand; 74 private boolean isRegisterLoad; 75 private boolean isRegisterStore; 76 77 private static final int INVALID_OFFSET = Integer.MIN_VALUE; 78 private static final String NOT_AVAILABLE = "none"; 79 80 88 89 private static HashMap <String , String > replaceSlashesWithDotsCache = new HashMap <String , String >(); 90 91 synchronized static String replaceSlashesWithDots(String c) { 92 String result = replaceSlashesWithDotsCache.get(c); 93 if (result != null) return result; 94 result = c.replace('/', '.'); 95 replaceSlashesWithDotsCache.put(c, result); 96 return result; 97 } 98 99 102 public static final byte M_INT = 1; 103 public static final byte M_UINT = 2; 104 public static final byte M_CP = 3; 105 public static final byte M_R = 4; 106 public static final byte M_BR = 5; 107 public static final byte M_PAD = 6; 108 111 static final byte[][] MEANING_OF_OPERANDS = { 112 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 114 {}, {}, {}, {}, {}, {}, {M_INT}, {M_INT}, {M_CP}, {M_CP}, 115 {M_CP}, {M_R}, {M_R}, {M_R}, {M_R}, {M_R}, {}, {}, {}, {}, 116 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 117 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 118 {}, {}, {}, {}, {M_R}, {M_R}, {M_R}, {M_R}, {M_R}, {}, 119 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 120 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 121 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 122 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 123 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 124 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 125 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 126 {}, {}, {M_R, M_INT}, {}, {}, {}, {}, {}, {}, {}, 128 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 129 {}, {}, {}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, 130 {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_BR}, {M_R}, 131 {}, {}, {}, {}, {}, {}, {}, {}, {M_CP}, {M_CP}, 133 {M_CP}, {M_CP}, {M_CP}, {M_CP}, {M_CP}, 134 {M_CP, M_PAD, M_PAD}, {}, {M_CP}, {M_UINT}, {M_CP}, 135 {}, {}, {M_CP}, {M_CP}, {}, {}, {M_PAD}, {M_CP, M_UINT}, {M_BR}, {M_BR}, 137 {M_BR}, {M_BR}, {}, {}, {}, {}, {}, 138 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 139 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, 140 {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} 141 }; 142 143 144 protected byte[] codeBytes; 145 protected LineNumberTable lineNumberTable; 146 147 149 150 public String getDottedClassConstantOperand() { 151 if (dottedClassConstantOperand == NOT_AVAILABLE) 152 throw new IllegalStateException ("getDottedClassConstantOperand called but value not available"); 153 return dottedClassConstantOperand; 154 } 155 156 157 public String getRefConstantOperand() { 158 if (refConstantOperand == NOT_AVAILABLE) 159 throw new IllegalStateException ("getRefConstantOperand called but value not available"); 160 if (refConstantOperand == null) { 161 StringBuffer ref = new StringBuffer (dottedClassConstantOperand.length() + nameConstantOperand.length() + dottedSigConstantOperand.length() + 5); 162 ref.append(dottedClassConstantOperand) 163 .append(".") 164 .append(nameConstantOperand) 165 .append(" : ") 166 .append(dottedSigConstantOperand); 167 refConstantOperand = ref.toString(); 168 } 169 return refConstantOperand; 170 } 171 172 173 public String getNameConstantOperand() { 174 if (nameConstantOperand == NOT_AVAILABLE) 175 throw new IllegalStateException ("getNameConstantOperand called but value not available"); 176 return nameConstantOperand; 177 } 178 179 180 @Deprecated 181 public String getDottedSigConstantOperand() { 182 if (dottedSigConstantOperand == NOT_AVAILABLE) 183 throw new IllegalStateException ("getDottedSigConstantOperand called but value not available"); 184 return dottedSigConstantOperand; 185 } 186 187 188 public String getSigConstantOperand() { 189 if (sigConstantOperand == NOT_AVAILABLE) 190 throw new IllegalStateException ("getSigConstantOperand called but value not available"); 191 return sigConstantOperand; 192 } 193 194 public String getClassConstantOperand() { 195 if (classConstantOperand == NOT_AVAILABLE) 196 throw new IllegalStateException ("getClassConstantOperand called but value not available"); 197 return classConstantOperand; 198 } 199 200 201 public String getStringConstantOperand() { 202 if (stringConstantOperand == NOT_AVAILABLE) 203 throw new IllegalStateException ("getStringConstantOperand called but value not available"); 204 return stringConstantOperand; 205 } 206 207 public Constant getConstantRefOperand() { 208 if (constantRefOperand == null) 209 throw new IllegalStateException ("getConstantRefOperand called but value not available"); 210 return constantRefOperand; 211 } 212 213 public boolean isRegisterLoad() { 214 return isRegisterLoad; 215 } 216 public boolean isRegisterStore() { 217 return isRegisterStore; 218 } 219 220 public int getRegisterOperand() { 221 if (registerOperand == -1) 222 throw new IllegalStateException ("getRegisterOperand called but value not available"); 223 return registerOperand; 224 } 225 226 public int getIntConstant() { 227 return intConstant; 228 } 229 230 public int getBranchOffset() { 231 if (branchOffset == INVALID_OFFSET) 232 throw new IllegalStateException ("getBranchOffset called but value not available"); 233 return branchOffset; 234 } 235 236 public int getBranchTarget() { 237 if (branchTarget == INVALID_OFFSET) 238 throw new IllegalStateException ("getBranchTarget called but value not available"); 239 return branchTarget; 240 } 241 242 public int getBranchFallThrough() { 243 if (branchFallThrough == INVALID_OFFSET) 244 throw new IllegalStateException ("getBranchFallThrough called but value not available"); 245 return branchFallThrough; 246 } 247 248 public int getDefaultSwitchOffset() { 249 if (defaultSwitchOffset == INVALID_OFFSET) 250 throw new IllegalStateException ("getDefaultSwitchOffset called but value not available"); 251 return defaultSwitchOffset; 252 } 253 254 public boolean getRefFieldIsStatic() { 255 return refFieldIsStatic; 256 } 257 258 public int getPC() { 259 return PC; 260 } 261 262 266 public int getPrevOpcode(int offset) { 267 if (offset >= prevOpcode.length || offset > sizePrevOpcodeBuffer) 268 return NOP; 269 int pos = currentPosInPrevOpcodeBuffer - offset; 270 if (pos < 0) pos += prevOpcode.length; 271 return prevOpcode[pos]; 272 } 273 274 280 public static boolean isBranch(int opcode) { 281 byte[] operands = MEANING_OF_OPERANDS[opcode]; 282 return operands.length > 0 && operands[0] == M_BR; 283 } 284 285 291 public static boolean isSwitch(int opcode) { 292 return opcode == LOOKUPSWITCH || opcode == TABLESWITCH; 293 } 294 295 @SuppressWarnings ("EI") 296 public int[] getSwitchOffsets() { 297 if (switchOffsets == null) 298 throw new IllegalStateException ("getSwitchOffsets called but value not available"); 299 return switchOffsets; 300 } 301 302 @SuppressWarnings ("EI") 303 public int[] getSwitchLabels() { 304 if (switchLabels == null) 305 throw new IllegalStateException ("getSwitchOffsets called but value not available"); 306 return switchLabels; 307 } 308 309 private void resetState() { 310 dottedClassConstantOperand = classConstantOperand = nameConstantOperand = sigConstantOperand = dottedSigConstantOperand = stringConstantOperand = refConstantOperand = NOT_AVAILABLE; 311 refFieldIsStatic = false; 312 constantRefOperand = null; 313 registerOperand = -1; 314 isRegisterLoad = false; 315 isRegisterStore = false; 316 branchOffset = branchTarget = branchFallThrough = defaultSwitchOffset = INVALID_OFFSET; 317 switchOffsets = switchLabels = null; 318 } 319 320 private static void sortByOffset(int[] switchOffsets, int[] switchLabels) { 321 int npairs = switchOffsets.length; 322 for (int j = 0; j < npairs; j++) { 324 int min = j; 325 for (int k = j + 1; k < npairs; k++) 326 if (switchOffsets[min] > switchOffsets[k]) 327 min = k; 328 if (min > j) { 329 int tmp = switchOffsets[min]; 330 switchOffsets[min] = switchOffsets[j]; 331 switchOffsets[j] = tmp; 332 tmp = switchLabels[min]; 333 switchLabels[min] = switchLabels[j]; 334 switchLabels[j] = tmp; 335 } 336 } 337 } 338 339 public int getMaxPC() { 340 return codeBytes.length-1; 341 } 342 public int getCodeByte(int offset) { 343 return 0xff & codeBytes[offset]; 344 } 345 public int getOpcode() { 346 return opcode; 347 } 348 349 public boolean atCatchBlock() { 350 for(CodeException e : getCode().getExceptionTable()) 351 if (e.getHandlerPC() == getPC()) return true; 352 return false; 353 } 354 @Override 355 public void visit(Code obj) { 356 sizePrevOpcodeBuffer = 0; 357 currentPosInPrevOpcodeBuffer = prevOpcode.length-1; 358 359 int switchLow = 1000000; 360 int switchHigh = -1000000; 361 codeBytes = obj.getCode(); 362 DataInputStream byteStream = new DataInputStream (new ByteArrayInputStream (codeBytes)); 363 364 lineNumberTable = obj.getLineNumberTable(); 365 366 try { 367 for (int i = 0; i < codeBytes.length;) { 368 resetState(); 369 PC = i; 370 opcodeIsWide = false; 371 opcode = byteStream.readUnsignedByte(); 372 sizePrevOpcodeBuffer++; 373 currentPosInPrevOpcodeBuffer++; 374 if (currentPosInPrevOpcodeBuffer >= prevOpcode.length) 375 currentPosInPrevOpcodeBuffer = 0; 376 prevOpcode[currentPosInPrevOpcodeBuffer] = opcode; 377 i++; 378 int byteStreamArgCount = NO_OF_OPERANDS[opcode]; 380 if (byteStreamArgCount == UNPREDICTABLE) { 381 382 if (opcode == LOOKUPSWITCH) { 383 int pad = 4 - (i & 3); 384 if (pad == 4) pad = 0; 385 int count = pad; 386 while (count > 0) 387 count -= byteStream.skipBytes(count); 388 i += pad; 389 defaultSwitchOffset = byteStream.readInt(); 390 branchOffset = defaultSwitchOffset; 391 branchTarget = branchOffset + PC; 392 i += 4; 393 int npairs = byteStream.readInt(); 394 i += 4; 395 switchOffsets = new int[npairs]; 396 switchLabels = new int[npairs]; 397 for (int o = 0; o < npairs; o++) { 398 switchLabels[o] = byteStream.readInt(); 399 switchOffsets[o] = byteStream.readInt(); 400 i += 8; 401 } 402 sortByOffset(switchOffsets, switchLabels); 403 } else if (opcode == TABLESWITCH) { 404 int pad = 4 - (i & 3); 405 if (pad == 4) pad = 0; 406 int count = pad; 407 while (count > 0) 408 count -= byteStream.skipBytes(count); 409 i += pad; 410 defaultSwitchOffset = byteStream.readInt(); 411 branchOffset = defaultSwitchOffset; 412 branchTarget = branchOffset + PC; 413 i += 4; 414 switchLow = byteStream.readInt(); 415 i += 4; 416 switchHigh = byteStream.readInt(); 417 i += 4; 418 int npairs = switchHigh - switchLow + 1; 419 switchOffsets = new int[npairs]; 420 switchLabels = new int[npairs]; 421 for (int o = 0; o < npairs; o++) { 422 switchLabels[o] = o + switchLow; 423 switchOffsets[o] = byteStream.readInt(); 424 i += 4; 425 } 426 sortByOffset(switchOffsets, switchLabels); 427 } else if (opcode == WIDE) { 428 opcodeIsWide = true; 429 opcode = byteStream.readUnsignedByte(); 430 i++; 431 switch (opcode) { 432 case ILOAD: 433 case FLOAD: 434 case ALOAD: 435 case LLOAD: 436 case DLOAD: 437 case ISTORE: 438 case FSTORE: 439 case ASTORE: 440 case LSTORE: 441 case DSTORE: 442 case RET: 443 registerOperand = byteStream.readUnsignedShort(); 444 i += 2; 445 break; 446 case IINC: 447 registerOperand = byteStream.readUnsignedShort(); 448 i += 2; 449 intConstant = byteStream.readShort(); 450 i += 2; 451 break; 452 default: 453 throw new IllegalStateException ("bad wide bytecode: " + OPCODE_NAMES[opcode]); 454 } 455 } else 456 throw new IllegalStateException ("bad unpredicatable bytecode: " + OPCODE_NAMES[opcode]); 457 } else { 458 if (byteStreamArgCount < 0) throw new IllegalStateException ("bad length for bytecode: " + OPCODE_NAMES[opcode]); 459 for (int k = 0; k < TYPE_OF_OPERANDS[opcode].length; k++) { 460 461 int v; 462 int t = TYPE_OF_OPERANDS[opcode][k]; 463 int m = MEANING_OF_OPERANDS[opcode][k]; 464 boolean unsigned = (m == M_CP || m == M_R || m == M_UINT); 465 switch (t) { 466 case T_BYTE: 467 if (unsigned) 468 v = byteStream.readUnsignedByte(); 469 else 470 v = byteStream.readByte(); 471 475 i++; 476 break; 477 case T_SHORT: 478 if (unsigned) 479 v = byteStream.readUnsignedShort(); 480 else 481 v = byteStream.readShort(); 482 i += 2; 483 break; 484 case T_INT: 485 v = byteStream.readInt(); 486 i += 4; 487 break; 488 default: 489 throw new IllegalStateException (); 490 } 491 switch (m) { 492 case M_BR: 493 branchOffset = v; 494 branchTarget = v + PC; 495 branchFallThrough = i; 496 break; 497 case M_CP: 498 constantRefOperand = getConstantPool().getConstant(v); 499 if (constantRefOperand instanceof ConstantClass) { 500 ConstantClass clazz = (ConstantClass) constantRefOperand; 501 classConstantOperand = getStringFromIndex(clazz.getNameIndex()); 502 dottedClassConstantOperand = replaceSlashesWithDots(classConstantOperand); 503 } 504 if (constantRefOperand instanceof ConstantInteger) 505 intConstant = ((ConstantInteger) constantRefOperand).getBytes(); 506 else if (constantRefOperand instanceof ConstantLong) 507 longConstant = ((ConstantLong) constantRefOperand).getBytes(); 508 else if (constantRefOperand instanceof ConstantFloat) 509 floatConstant = ((ConstantFloat) constantRefOperand).getBytes(); 510 else if (constantRefOperand instanceof ConstantDouble) 511 doubleConstant = ((ConstantDouble) constantRefOperand).getBytes(); 512 else if (constantRefOperand instanceof ConstantString) { 513 int s = ((ConstantString) constantRefOperand).getStringIndex(); 514 515 stringConstantOperand = getStringFromIndex(s); 516 } else if (constantRefOperand instanceof ConstantCP) { 517 ConstantCP cp = (ConstantCP) constantRefOperand; 518 ConstantClass clazz 519 = (ConstantClass) getConstantPool().getConstant(cp.getClassIndex()); 520 classConstantOperand = getStringFromIndex(clazz.getNameIndex()); 521 dottedClassConstantOperand = replaceSlashesWithDots(classConstantOperand); 522 ConstantNameAndType sig 523 = (ConstantNameAndType) getConstantPool().getConstant(cp.getNameAndTypeIndex()); 524 nameConstantOperand = getStringFromIndex(sig.getNameIndex()); 525 sigConstantOperand = getStringFromIndex(sig.getSignatureIndex()); 526 dottedSigConstantOperand = replaceSlashesWithDots(sigConstantOperand); 527 528 refConstantOperand = null; 529 } 530 break; 531 case M_R: 532 registerOperand = v; 533 break; 534 case M_UINT: 535 case M_INT: 536 intConstant = v; 537 } 538 } 539 540 } 541 switch (opcode) { 542 case IINC: 543 isRegisterLoad = true; 544 isRegisterStore = true; 545 break; 546 case ILOAD_0: 547 case ILOAD_1: 548 case ILOAD_2: 549 case ILOAD_3: 550 registerOperand = opcode - ILOAD_0; 551 isRegisterLoad = true; 552 break; 553 554 case ALOAD_0: 555 case ALOAD_1: 556 case ALOAD_2: 557 case ALOAD_3: 558 registerOperand = opcode - ALOAD_0; 559 isRegisterLoad = true; 560 break; 561 562 case FLOAD_0: 563 case FLOAD_1: 564 case FLOAD_2: 565 case FLOAD_3: 566 registerOperand = opcode - FLOAD_0; 567 isRegisterLoad = true; 568 break; 569 570 case DLOAD_0: 571 case DLOAD_1: 572 case DLOAD_2: 573 case DLOAD_3: 574 registerOperand = opcode - DLOAD_0; 575 isRegisterLoad = true; 576 break; 577 578 case LLOAD_0: 579 case LLOAD_1: 580 case LLOAD_2: 581 case LLOAD_3: 582 registerOperand = opcode - LLOAD_0; 583 isRegisterLoad = true; 584 break; 585 case ILOAD: 586 case FLOAD: 587 case ALOAD: 588 case LLOAD: 589 case DLOAD: 590 isRegisterLoad = true; 591 break; 592 593 594 595 596 case ISTORE_0: 597 case ISTORE_1: 598 case ISTORE_2: 599 case ISTORE_3: 600 registerOperand = opcode - ISTORE_0; 601 isRegisterStore = true; 602 break; 603 604 case ASTORE_0: 605 case ASTORE_1: 606 case ASTORE_2: 607 case ASTORE_3: 608 registerOperand = opcode - ASTORE_0; 609 isRegisterStore = true; 610 break; 611 612 case FSTORE_0: 613 case FSTORE_1: 614 case FSTORE_2: 615 case FSTORE_3: 616 registerOperand = opcode - FSTORE_0; 617 isRegisterStore = true; 618 break; 619 620 case DSTORE_0: 621 case DSTORE_1: 622 case DSTORE_2: 623 case DSTORE_3: 624 registerOperand = opcode - DSTORE_0; 625 isRegisterStore = true; 626 break; 627 628 case LSTORE_0: 629 case LSTORE_1: 630 case LSTORE_2: 631 case LSTORE_3: 632 registerOperand = opcode - LSTORE_0; 633 isRegisterStore = true; 634 break; 635 case ISTORE: 636 case FSTORE: 637 case ASTORE: 638 case LSTORE: 639 case DSTORE: 640 isRegisterStore = true; 641 break; 642 643 } 644 645 646 switch (opcode) { 647 case ILOAD: 648 case FLOAD: 649 case ALOAD: 650 case LLOAD: 651 case DLOAD: 652 break; 654 case ISTORE: 655 case FSTORE: 656 case ASTORE: 657 case LSTORE: 658 case DSTORE: 659 break; 661 case RET: 662 break; 664 case GETSTATIC: 665 case PUTSTATIC: 666 refFieldIsStatic = true; 667 break; 668 case GETFIELD: 669 case PUTFIELD: 670 refFieldIsStatic = false; 671 break; 672 } 673 nextPC = i; 674 sawOpcode(opcode); 675 676 if (opcode == TABLESWITCH) { 677 sawInt(switchLow); 678 sawInt(switchHigh); 679 int prevOffset = i - PC; 680 for (int o = 0; o <= switchHigh - switchLow; o++) { 681 sawBranchTo(switchOffsets[o] + PC); 682 sawOffset(switchOffsets[o] - prevOffset); 683 prevOffset = switchOffsets[o]; 684 } 685 sawOffset(defaultSwitchOffset - prevOffset); 686 sawBranchTo(defaultSwitchOffset + PC); 687 } else if (opcode == LOOKUPSWITCH) { 688 sawInt(switchOffsets.length); 689 int prevOffset = i - PC; 690 for (int o = 0; o < switchOffsets.length; o++) { 691 sawBranchTo(switchOffsets[o] + PC); 692 prevOffset = switchOffsets[o]; 693 sawInt(switchLabels[o]); 694 } 695 sawOffset(defaultSwitchOffset - prevOffset); 696 sawBranchTo(defaultSwitchOffset + PC); 697 } else 698 for (int k = 0; k < TYPE_OF_OPERANDS[opcode].length; k++) { 699 int m = MEANING_OF_OPERANDS[opcode][k]; 700 switch (m) { 701 case M_BR: 702 sawBranchTo(branchOffset + PC); 703 if (branchOffset > 0) 704 sawOffset(branchOffset - (i - PC)); 705 else 706 sawOffset(branchOffset); 707 break; 708 case M_CP: 709 if (constantRefOperand instanceof ConstantInteger) 710 sawInt(intConstant); 711 else if (constantRefOperand instanceof ConstantLong) 712 sawLong(longConstant); 713 else if (constantRefOperand instanceof ConstantFloat) 714 sawFloat(floatConstant); 715 else if (constantRefOperand instanceof ConstantDouble) 716 sawDouble(doubleConstant); 717 else if (constantRefOperand instanceof ConstantString) 718 sawString(stringConstantOperand); 719 else if (constantRefOperand instanceof ConstantFieldref) 720 sawField(); 721 else if (constantRefOperand instanceof ConstantMethodref) 722 sawMethod(); 723 else if (constantRefOperand instanceof ConstantInterfaceMethodref) 724 sawIMethod(); 725 else if (constantRefOperand instanceof ConstantClass) 726 sawClass(); 727 break; 728 case M_R: 729 sawRegister(registerOperand); 730 break; 731 case M_INT: 732 sawInt(intConstant); 733 break; 734 } 735 } 736 } 737 } catch (IOException e) { 738 System.out.println("Got IO Exception:"); 739 e.printStackTrace(); 740 } 741 742 try { 743 byteStream.close(); 744 } catch (IOException e) { 745 assert false; 746 } 747 } 748 749 public void sawDouble(double seen) { 750 } 751 752 public void sawFloat(float seen) { 753 } 754 755 public void sawRegister(int r) { 756 } 757 758 public void sawInt(int seen) { 759 } 760 761 public void sawLong(long seen) { 762 } 763 764 public void sawBranchTo(int seen) { 765 } 766 public void sawOffset(int seen) { 767 } 768 769 public void sawOpcode(int seen) { 770 } 771 772 public void sawString(String seen) { 773 } 774 775 public void sawField() { 776 } 777 778 public void sawMethod() { 779 } 780 781 public void sawIMethod() { 782 } 783 784 public void sawClass() { 785 } 786 787 static private NumberFormat formatter = NumberFormat.getIntegerInstance(); 788 static { 789 formatter.setMinimumIntegerDigits(4); 790 formatter.setGroupingUsed(false); 791 } 792 public void printOpCode( int seen) { 793 System.out.print(" TestingGround: [" + formatter.format(getPC()) + "] " + OPCODE_NAMES[seen]); 794 if ((seen == INVOKEVIRTUAL) || (seen == INVOKESPECIAL) || (seen == INVOKEINTERFACE) || (seen == INVOKESTATIC)) 795 System.out.print(" " + getClassConstantOperand() + "." + getNameConstantOperand() + " " + getSigConstantOperand()); 796 else if (seen == LDC || seen == LDC_W || seen == LDC2_W) { 797 Constant c = getConstantRefOperand(); 798 if (c instanceof ConstantString) 799 System.out.print(" \"" + getStringConstantOperand() + "\""); 800 else if (c instanceof ConstantClass) 801 System.out.print(" " + getClassConstantOperand()); 802 else 803 System.out.print(" " + c); 804 } else if ((seen == ALOAD) || (seen == ASTORE)) 805 System.out.print(" " + getRegisterOperand()); 806 else if ((seen == GOTO) || (seen == GOTO_W) 807 || (seen == IF_ACMPEQ) || (seen == IF_ACMPNE) 808 || (seen == IF_ICMPEQ) || (seen == IF_ICMPGE) 809 || (seen == IF_ICMPGT) || (seen == IF_ICMPLE) 810 || (seen == IF_ICMPLT) || (seen == IF_ICMPNE) 811 || (seen == IFEQ) || (seen == IFGE) 812 || (seen == IFGT) || (seen == IFLE) 813 || (seen == IFLT) || (seen == IFNE) 814 || (seen == IFNONNULL) || (seen == IFNULL)) 815 System.out.print(" " + getBranchTarget()); 816 else if ((seen == NEW) || (seen == INSTANCEOF)) 817 System.out.print(" " + getClassConstantOperand()); 818 else if ((seen == TABLESWITCH) || (seen == LOOKUPSWITCH)) { 819 System.out.print(" ["); 820 int switchPC = getPC(); 821 int[] offsets = getSwitchOffsets(); 822 for (int offset : offsets) { 823 System.out.print((switchPC + offset) + ","); 824 } 825 System.out.print((switchPC + getDefaultSwitchOffset()) + "]"); 826 } 827 828 System.out.println(); 829 } 830 831 832 835 public int getNextPC() { 836 return nextPC; 837 } 838 } 839 | Popular Tags |