1 34 35 package org.logicalcobwebs.asm; 36 37 import java.io.InputStream ; 38 import java.io.IOException ; 39 40 46 47 public class ClassReader { 48 49 53 54 protected final byte[] b; 55 56 60 61 private int[] items; 62 63 71 72 private String [] strings; 73 74 77 78 private int maxStringLength; 79 80 84 85 private int header; 86 87 91 96 97 public ClassReader (final byte[] b) { 98 this(b, 0, b.length); 99 } 100 101 108 109 public ClassReader (final byte[] b, final int off, final int len) { 110 this.b = b; 111 items = new int[readUnsignedShort(off + 8)]; 113 strings = new String [items.length]; 114 int max = 0; 115 int index = off + 10; 116 for (int i = 1; i < items.length; ++i) { 117 items[i] = index + 1; 118 int tag = b[index]; 119 int size; 120 switch (tag) { 121 case ClassWriter.FIELD: 122 case ClassWriter.METH: 123 case ClassWriter.IMETH: 124 case ClassWriter.INT: 125 case ClassWriter.FLOAT: 126 case ClassWriter.NAME_TYPE: 127 size = 5; 128 break; 129 case ClassWriter.LONG: 130 case ClassWriter.DOUBLE: 131 size = 9; 132 ++i; 133 break; 134 case ClassWriter.UTF8: 135 size = 3 + readUnsignedShort(index + 1); 136 max = (size > max ? size : max); 137 break; 138 default: 141 size = 3; 142 break; 143 } 144 index += size; 145 } 146 maxStringLength = max; 147 header = index; 149 } 150 151 157 158 public ClassReader (final InputStream is) throws IOException { 159 this(readClass(is)); 160 } 161 162 168 169 public ClassReader (final String name) throws IOException { 170 this((ClassReader.class.getClassLoader() == null 171 ? ClassLoader.getSystemClassLoader() 172 : ClassReader.class.getClassLoader()) 173 .getSystemResourceAsStream(name.replace('.','/') + ".class")); 174 } 175 176 183 184 private static byte[] readClass (final InputStream is) throws IOException { 185 if (is == null) { 186 throw new IOException ("Class not found"); 187 } 188 byte[] b = new byte[is.available()]; 189 int len = 0; 190 while (true) { 191 int n = is.read(b, len, b.length - len); 192 if (n == -1) { 193 if (len < b.length) { 194 byte[] c = new byte[len]; 195 System.arraycopy(b, 0, c, 0, len); 196 b = c; 197 } 198 return b; 199 } else { 200 len += n; 201 if (len == b.length) { 202 byte[] c = new byte[b.length + 1000]; 203 System.arraycopy(b, 0, c, 0, len); 204 b = c; 205 } 206 } 207 } 208 } 209 210 214 225 226 public void accept ( 227 final ClassVisitor classVisitor, 228 final boolean skipDebug) 229 { 230 byte[] b = this.b; char[] c = new char[maxStringLength]; int i, j, k; int u, v, w; Attribute attr; 235 236 u = header; 238 int access = readUnsignedShort(u); 239 String className = readClass(u + 2, c); 240 v = items[readUnsignedShort(u + 4)]; 241 String superClassName = v == 0 ? null : readUTF8(v, c); 242 String [] implementedItfs = new String [readUnsignedShort(u + 6)]; 243 String sourceFile = null; 244 Attribute clattrs = null; 245 w = 0; 246 u += 8; 247 for (i = 0; i < implementedItfs.length; ++i) { 248 implementedItfs[i] = readClass(u, c); u += 2; 249 } 250 v = u; 252 i = readUnsignedShort(v); v += 2; 253 for ( ; i > 0; --i) { 254 j = readUnsignedShort(v + 6); 255 v += 8; 256 for ( ; j > 0; --j) { 257 v += 6 + readInt(v + 2); 258 } 259 } 260 i = readUnsignedShort(v); v += 2; 261 for ( ; i > 0; --i) { 262 j = readUnsignedShort(v + 6); 263 v += 8; 264 for ( ; j > 0; --j) { 265 v += 6 + readInt(v + 2); 266 } 267 } 268 i = readUnsignedShort(v); v += 2; 270 for ( ; i > 0; --i) { 271 String attrName = readUTF8(v, c); 272 if (attrName.equals("SourceFile")) { 273 sourceFile = readUTF8(v + 6, c); 274 } else if (attrName.equals("Deprecated")) { 275 access |= Constants.ACC_DEPRECATED; 276 } else if (attrName.equals("InnerClasses")) { 277 w = v + 6; 278 } else { 279 attr = readAttribute(attrName, v + 6, readInt(v + 2), c); 280 attr.next = clattrs; 281 clattrs = attr; 282 } 283 v += 6 + readInt(v + 2); 284 } 285 classVisitor.visit( 287 access, className, superClassName, implementedItfs, sourceFile); 288 289 if (w != 0) { 291 i = readUnsignedShort(w); w += 2; 292 for ( ; i > 0; --i) { 293 classVisitor.visitInnerClass( 294 readUnsignedShort(w) == 0 ? null : readClass(w, c), 295 readUnsignedShort(w + 2) == 0 ? null : readClass(w + 2, c), 296 readUnsignedShort(w + 4) == 0 ? null : readUTF8(w + 4, c), 297 readUnsignedShort(w + 6)); 298 w += 8; 299 } 300 } 301 302 i = readUnsignedShort(u); u += 2; 304 for ( ; i > 0; --i) { 305 access = readUnsignedShort(u); 306 String fieldName = readUTF8(u + 2, c); 307 String fieldDesc = readUTF8(u + 4, c); 308 Attribute fattrs = null; 309 int fieldValueItem = 0; 311 j = readUnsignedShort(u + 6); 312 u += 8; 313 for ( ; j > 0; --j) { 314 String attrName = readUTF8(u, c); 315 if (attrName.equals("ConstantValue")) { 316 fieldValueItem = readUnsignedShort(u + 6); 317 } else if (attrName.equals("Synthetic")) { 318 access |= Constants.ACC_SYNTHETIC; 319 } else if (attrName.equals("Deprecated")) { 320 access |= Constants.ACC_DEPRECATED; 321 } else { 322 attr = readAttribute(attrName, u + 6, readInt(u + 2), c); 323 attr.next = fattrs; 324 fattrs = attr; 325 } 326 u += 6 + readInt(u + 2); 327 } 328 Object value = (fieldValueItem == 0 ? null : readConst(fieldValueItem, c)); 330 classVisitor.visitField(access, fieldName, fieldDesc, value, fattrs); 332 } 333 334 i = readUnsignedShort(u); u += 2; 336 for ( ; i > 0; --i) { 337 access = readUnsignedShort(u); 338 String methName = readUTF8(u + 2, c); 339 String methDesc = readUTF8(u + 4, c); 340 Attribute mattrs = null; 341 v = 0; 342 w = 0; 343 j = readUnsignedShort(u + 6); 345 u += 8; 346 for ( ; j > 0; --j) { 347 String attrName = readUTF8(u, c); u += 2; 348 int attrSize = readInt(u); u += 4; 349 if (attrName.equals("Code")) { 350 v = u; 351 } else if (attrName.equals("Exceptions")) { 352 w = u; 353 } else if (attrName.equals("Synthetic")) { 354 access |= Constants.ACC_SYNTHETIC; 355 } else if (attrName.equals("Deprecated")) { 356 access |= Constants.ACC_DEPRECATED; 357 } else { 358 attr = readAttribute(attrName, u, attrSize, c); 359 attr.next = mattrs; 360 mattrs = attr; 361 } 362 u += attrSize; 363 } 364 String [] exceptions; 366 if (w == 0) { 367 exceptions = null; 368 } else { 369 exceptions = new String [readUnsignedShort(w)]; w += 2; 370 for (j = 0; j < exceptions.length; ++j) { 371 exceptions[j] = readClass(w, c); w += 2; 372 } 373 } 374 375 CodeVisitor cv; 377 cv = classVisitor.visitMethod( 378 access, methName, methDesc, exceptions, mattrs); 379 if (cv != null && v != 0) { 380 int maxStack = readUnsignedShort(v); 381 int maxLocals = readUnsignedShort(v + 2); 382 int codeLength = readInt(v + 4); 383 Attribute cattrs = null; 384 v += 8; 385 386 int codeStart = v; 387 int codeEnd = v + codeLength; 388 389 int label; 391 Label[] labels = new Label[codeLength + 1]; 392 while (v < codeEnd) { 393 int opcode = b[v] & 0xFF; 394 switch (ClassWriter.TYPE[opcode]) { 395 case ClassWriter.NOARG_INSN: 396 case ClassWriter.IMPLVAR_INSN: 397 v += 1; 398 break; 399 case ClassWriter.LABEL_INSN: 400 label = v - codeStart + readShort(v + 1); 401 if (labels[label] == null) { 402 labels[label] = new Label(); 403 } 404 v += 3; 405 break; 406 case ClassWriter.LABELW_INSN: 407 label = v - codeStart + readInt(v + 1); 408 if (labels[label] == null) { 409 labels[label] = new Label(); 410 } 411 v += 5; 412 break; 413 case ClassWriter.WIDE_INSN: 414 opcode = b[v + 1] & 0xFF; 415 if (opcode == Constants.IINC) { 416 v += 6; 417 } else { 418 v += 4; 419 } 420 break; 421 case ClassWriter.TABL_INSN: 422 w = v - codeStart; 424 v = v + 4 - (w & 3); 425 label = w + readInt(v); v += 4; 427 if (labels[label] == null) { 428 labels[label] = new Label(); 429 } 430 j = readInt(v); v += 4; 431 j = readInt(v) - j + 1; v += 4; 432 for ( ; j > 0; --j) { 433 label = w + readInt(v); v += 4; 434 if (labels[label] == null) { 435 labels[label] = new Label(); 436 } 437 } 438 break; 439 case ClassWriter.LOOK_INSN: 440 w = v - codeStart; 442 v = v + 4 - (w & 3); 443 label = w + readInt(v); v += 4; 445 if (labels[label] == null) { 446 labels[label] = new Label(); 447 } 448 j = readInt(v); v += 4; 449 for ( ; j > 0; --j) { 450 v += 4; label = w + readInt(v); v += 4; 452 if (labels[label] == null) { 453 labels[label] = new Label(); 454 } 455 } 456 break; 457 case ClassWriter.VAR_INSN: 458 case ClassWriter.SBYTE_INSN: 459 case ClassWriter.LDC_INSN: 460 v += 2; 461 break; 462 case ClassWriter.SHORT_INSN: 463 case ClassWriter.LDCW_INSN: 464 case ClassWriter.FIELDORMETH_INSN: 465 case ClassWriter.TYPE_INSN: 466 case ClassWriter.IINC_INSN: 467 v += 3; 468 break; 469 case ClassWriter.ITFMETH_INSN: 470 v += 5; 471 break; 472 default: 474 v += 4; 475 break; 476 } 477 } 478 j = readUnsignedShort(v); v += 2; 480 for ( ; j > 0; --j) { 481 label = readUnsignedShort(v); 482 if (labels[label] == null) { 483 labels[label] = new Label(); 484 } 485 label = readUnsignedShort(v + 2); 486 if (labels[label] == null) { 487 labels[label] = new Label(); 488 } 489 label = readUnsignedShort(v + 4); 490 if (labels[label] == null) { 491 labels[label] = new Label(); 492 } 493 v += 8; 494 } 495 if (!skipDebug) { 496 j = readUnsignedShort(v); v += 2; 498 for ( ; j > 0; --j) { 499 String attrName = readUTF8(v, c); 500 if (attrName.equals("LocalVariableTable")) { 501 k = readUnsignedShort(v + 6); 502 w = v + 8; 503 for ( ; k > 0; --k) { 504 label = readUnsignedShort(w); 505 if (labels[label] == null) { 506 labels[label] = new Label(); 507 } 508 label += readUnsignedShort(w + 2); 509 if (labels[label] == null) { 510 labels[label] = new Label(); 511 } 512 w += 10; 513 } 514 } else if (attrName.equals("LineNumberTable")) { 515 k = readUnsignedShort(v + 6); 516 w = v + 8; 517 for ( ; k > 0; --k) { 518 label = readUnsignedShort(w); 519 if (labels[label] == null) { 520 labels[label] = new Label(); 521 } 522 w += 4; 523 } 524 } else { 525 attr = readAttribute(attrName, v + 6, readInt(v + 2), c); 526 attr.next = cattrs; 527 cattrs = attr; 528 } 529 v += 6 + readInt(v + 2); 530 } 531 } 532 533 v = codeStart; 535 Label l; 536 while (v < codeEnd) { 537 w = v - codeStart; 538 l = labels[w]; 539 if (l != null) { 540 cv.visitLabel(l); 541 } 542 int opcode = b[v] & 0xFF; 543 switch (ClassWriter.TYPE[opcode]) { 544 case ClassWriter.NOARG_INSN: 545 cv.visitInsn(opcode); 546 v += 1; 547 break; 548 case ClassWriter.IMPLVAR_INSN: 549 if (opcode > Constants.ISTORE) { 550 opcode -= 59; cv.visitVarInsn(Constants.ISTORE + (opcode >> 2), opcode & 0x3); 552 } else { 553 opcode -= 26; cv.visitVarInsn(Constants.ILOAD + (opcode >> 2), opcode & 0x3); 555 } 556 v += 1; 557 break; 558 case ClassWriter.LABEL_INSN: 559 cv.visitJumpInsn(opcode, labels[w + readShort(v + 1)]); 560 v += 3; 561 break; 562 case ClassWriter.LABELW_INSN: 563 cv.visitJumpInsn(opcode, labels[w + readInt(v + 1)]); 564 v += 5; 565 break; 566 case ClassWriter.WIDE_INSN: 567 opcode = b[v + 1] & 0xFF; 568 if (opcode == Constants.IINC) { 569 cv.visitIincInsn(readUnsignedShort(v + 2), readShort(v + 4)); 570 v += 6; 571 } else { 572 cv.visitVarInsn(opcode, readUnsignedShort(v + 2)); 573 v += 4; 574 } 575 break; 576 case ClassWriter.TABL_INSN: 577 v = v + 4 - (w & 3); 579 label = w + readInt(v); v += 4; 581 int min = readInt(v); v += 4; 582 int max = readInt(v); v += 4; 583 Label[] table = new Label[max - min + 1]; 584 for (j = 0; j < table.length; ++j) { 585 table[j] = labels[w + readInt(v)]; 586 v += 4; 587 } 588 cv.visitTableSwitchInsn(min, max, labels[label], table); 589 break; 590 case ClassWriter.LOOK_INSN: 591 v = v + 4 - (w & 3); 593 label = w + readInt(v); v += 4; 595 j = readInt(v); v += 4; 596 int[] keys = new int[j]; 597 Label[] values = new Label[j]; 598 for (j = 0; j < keys.length; ++j) { 599 keys[j] = readInt(v); v += 4; 600 values[j] = labels[w + readInt(v)]; v += 4; 601 } 602 cv.visitLookupSwitchInsn(labels[label], keys, values); 603 break; 604 case ClassWriter.VAR_INSN: 605 cv.visitVarInsn(opcode, b[v + 1] & 0xFF); 606 v += 2; 607 break; 608 case ClassWriter.SBYTE_INSN: 609 cv.visitIntInsn(opcode, b[v + 1]); 610 v += 2; 611 break; 612 case ClassWriter.SHORT_INSN: 613 cv.visitIntInsn(opcode, readShort(v + 1)); 614 v += 3; 615 break; 616 case ClassWriter.LDC_INSN: 617 cv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c)); 618 v += 2; 619 break; 620 case ClassWriter.LDCW_INSN: 621 cv.visitLdcInsn(readConst(readUnsignedShort(v + 1), c)); 622 v += 3; 623 break; 624 case ClassWriter.FIELDORMETH_INSN: 625 case ClassWriter.ITFMETH_INSN: 626 int cpIndex = items[readUnsignedShort(v + 1)]; 627 String iowner = readClass(cpIndex, c); 628 cpIndex = items[readUnsignedShort(cpIndex + 2)]; 629 String iname = readUTF8(cpIndex, c); 630 String idesc = readUTF8(cpIndex + 2, c); 631 if (opcode < Constants.INVOKEVIRTUAL) { 632 cv.visitFieldInsn(opcode, iowner, iname, idesc); 633 } else { 634 cv.visitMethodInsn(opcode, iowner, iname, idesc); 635 } 636 if (opcode == Constants.INVOKEINTERFACE) { 637 v += 5; 638 } else { 639 v += 3; 640 } 641 break; 642 case ClassWriter.TYPE_INSN: 643 cv.visitTypeInsn(opcode, readClass(v + 1, c)); 644 v += 3; 645 break; 646 case ClassWriter.IINC_INSN: 647 cv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]); 648 v += 3; 649 break; 650 default: 652 cv.visitMultiANewArrayInsn(readClass(v + 1, c), b[v + 3] & 0xFF); 653 v += 4; 654 break; 655 } 656 } 657 l = labels[codeEnd - codeStart]; 658 if (l != null) { 659 cv.visitLabel(l); 660 } 661 j = readUnsignedShort(v); v += 2; 663 for ( ; j > 0; --j) { 664 Label start = labels[readUnsignedShort(v)]; 665 Label end = labels[readUnsignedShort(v + 2)]; 666 Label handler = labels[readUnsignedShort(v + 4)]; 667 int type = readUnsignedShort(v + 6); 668 if (type == 0) { 669 cv.visitTryCatchBlock(start, end, handler, null); 670 } else { 671 cv.visitTryCatchBlock(start, end, handler, readUTF8(items[type], c)); 672 } 673 v += 8; 674 } 675 if (!skipDebug) { 676 j = readUnsignedShort(v); v += 2; 678 for ( ; j > 0; --j) { 679 String attrName = readUTF8(v, c); 680 if (attrName.equals("LocalVariableTable")) { 681 k = readUnsignedShort(v + 6); 682 w = v + 8; 683 for ( ; k > 0; --k) { 684 label = readUnsignedShort(w); 685 Label start = labels[label]; 686 label += readUnsignedShort(w + 2); 687 Label end = labels[label]; 688 cv.visitLocalVariable( 689 readUTF8(w + 4, c), 690 readUTF8(w + 6, c), 691 start, 692 end, 693 readUnsignedShort(w + 8)); 694 w += 10; 695 } 696 } else if (attrName.equals("LineNumberTable")) { 697 k = readUnsignedShort(v + 6); 698 w = v + 8; 699 for ( ; k > 0; --k) { 700 cv.visitLineNumber( 701 readUnsignedShort(w + 2), 702 labels[readUnsignedShort(w)]); 703 w += 4; 704 } 705 } 706 v += 6 + readInt(v + 2); 707 } 708 } 709 while (cattrs != null) { 711 cv.visitAttribute(cattrs); 712 cattrs = cattrs.next; 713 } 714 cv.visitMaxs(maxStack, maxLocals); 716 } 717 } 718 while (clattrs != null) { 720 classVisitor.visitAttribute(clattrs); 721 clattrs = clattrs.next; 722 } 723 classVisitor.visitEnd(); 725 } 726 727 731 737 738 protected int readUnsignedShort (final int index) { 739 byte[] b = this.b; 740 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 741 } 742 743 749 750 protected short readShort (final int index) { 751 byte[] b = this.b; 752 return (short)(((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 753 } 754 755 761 762 protected int readInt (final int index) { 763 byte[] b = this.b; 764 return ((b[index] & 0xFF) << 24) | 765 ((b[index + 1] & 0xFF) << 16) | 766 ((b[index + 2] & 0xFF) << 8) | 767 (b[index + 3] & 0xFF); 768 } 769 770 776 777 protected long readLong (final int index) { 778 long l1 = readInt(index); 779 long l0 = readInt(index + 4) & 0xFFFFFFFFL; 780 return (l1 << 32) | l0; 781 } 782 783 792 793 protected String readUTF8 (int index, final char[] buf) { 794 int item = readUnsignedShort(index); 796 String s = strings[item]; 797 if (s != null) { 798 return s; 799 } 800 index = items[item]; 802 int utfLen = readUnsignedShort(index); 804 index += 2; 805 int endIndex = index + utfLen; 807 byte[] b = this.b; 808 int strLen = 0; 809 int c, d, e; 810 while (index < endIndex) { 811 c = b[index++] & 0xFF; 812 switch (c >> 4) { 813 case 0: 814 case 1: 815 case 2: 816 case 3: 817 case 4: 818 case 5: 819 case 6: 820 case 7: 821 buf[strLen++] = (char)c; 823 break; 824 case 12: 825 case 13: 826 d = b[index++]; 828 buf[strLen++] = (char)(((c & 0x1F) << 6) | (d & 0x3F)); 829 break; 830 default: 831 d = b[index++]; 833 e = b[index++]; 834 buf[strLen++] = 835 (char)(((c & 0x0F) << 12) | ((d & 0x3F) << 6) | (e & 0x3F)); 836 break; 837 } 838 } 839 s = new String (buf, 0, strLen); 840 strings[item] = s; 841 return s; 842 } 843 844 853 854 protected String readClass (final int index, final char[] buf) { 855 return readUTF8(items[readUnsignedShort(index)], buf); 859 } 860 861 872 873 protected Object readConst (final int item, final char[] buf) { 874 int index = items[item]; 875 switch (b[index - 1]) { 876 case ClassWriter.INT: 877 return new Integer (readInt(index)); 878 case ClassWriter.FLOAT: 879 return new Float (Float.intBitsToFloat(readInt(index))); 880 case ClassWriter.LONG: 881 return new Long (readLong(index)); 882 case ClassWriter.DOUBLE: 883 return new Double (Double.longBitsToDouble(readLong(index))); 884 default: 886 return readUTF8(index, buf); 887 } 888 } 889 890 904 905 protected Attribute readAttribute ( 906 final String type, 907 final int off, 908 final int len, 909 final char[] buf) 910 { 911 return new Attribute(type, b, off, len); 912 } 913 } 914 | Popular Tags |