1 15 16 package javassist.bytecode; 17 18 27 public class CodeIterator implements Opcode { 28 protected CodeAttribute codeAttr; 29 protected byte[] bytecode; 30 protected int endPos; 31 protected int currentPos; 32 33 CodeIterator(CodeAttribute ca) { 34 codeAttr = ca; 35 bytecode = ca.getCode(); 36 begin(); 37 } 38 39 42 public void begin() { 43 currentPos = 0; 44 endPos = getCodeLength(); 45 } 46 47 59 public void move(int index) { 60 currentPos = index; 61 } 62 63 66 public CodeAttribute get() { 67 return codeAttr; 68 } 69 70 73 public int getCodeLength() { 74 return bytecode.length; 75 } 76 77 80 public int byteAt(int index) { return bytecode[index] & 0xff; } 81 82 85 public void writeByte(int value, int index) { 86 bytecode[index] = (byte)value; 87 } 88 89 92 public int u16bitAt(int index) { 93 return ByteArray.readU16bit(bytecode, index); 94 } 95 96 99 public int s16bitAt(int index) { 100 return ByteArray.readS16bit(bytecode, index); 101 } 102 103 106 public void write16bit(int value, int index) { 107 ByteArray.write16bit(value, bytecode, index); 108 } 109 110 113 public int s32bitAt(int index) { 114 return ByteArray.read32bit(bytecode, index); 115 } 116 117 120 public void write32bit(int value, int index) { 121 ByteArray.write32bit(value, bytecode, index); 122 } 123 124 129 public void write(byte[] code, int index) { 130 int len = code.length; 131 for (int j = 0; j < len; ++j) 132 bytecode[index++] = code[j]; 133 } 134 135 138 public boolean hasNext() { return currentPos < endPos; } 139 140 150 public int next() throws BadBytecode { 151 int pos = currentPos; 152 currentPos = nextOpcode(bytecode, pos); 153 return pos; 154 } 155 156 174 public int skipConstructor() throws BadBytecode { 175 return skipSuperConstructor0(-1); 176 } 177 178 197 public int skipSuperConstructor() throws BadBytecode { 198 return skipSuperConstructor0(0); 199 } 200 201 220 public int skipThisConstructor() throws BadBytecode { 221 return skipSuperConstructor0(1); 222 } 223 224 226 private int skipSuperConstructor0(int skipThis) throws BadBytecode { 227 begin(); 228 ConstPool cp = codeAttr.getConstPool(); 229 String thisClassName = codeAttr.getDeclaringClass(); 230 int nested = 0; 231 while (hasNext()) { 232 int index = next(); 233 int c = byteAt(index); 234 if (c == NEW) 235 ++nested; 236 else if (c == INVOKESPECIAL) { 237 int mref = ByteArray.readU16bit(bytecode, index + 1); 238 if (cp.getMethodrefName(mref).equals(MethodInfo.nameInit)) 239 if (--nested < 0) { 240 if (skipThis < 0) 241 return index; 242 243 String cname = cp.getMethodrefClassName(mref); 244 if (cname.equals(thisClassName) == (skipThis > 0)) 245 return index; 246 else 247 break; 248 } 249 } 250 } 251 252 begin(); 253 return -1; 254 } 255 256 274 public int insert(byte[] code) 275 throws BadBytecode 276 { 277 int pos = currentPos; 278 insert0(currentPos, code, false); 279 return pos; 280 } 281 282 298 public void insert(int pos, byte[] code) throws BadBytecode { 299 insert0(pos, code, false); 300 } 301 302 320 public int insertEx(byte[] code) 321 throws BadBytecode 322 { 323 int pos = currentPos; 324 insert0(currentPos, code, true); 325 return pos; 326 } 327 328 344 public void insertEx(int pos, byte[] code) throws BadBytecode { 345 insert0(pos, code, true); 346 } 347 348 private void insert0(int pos, byte[] code, boolean exclusive) 349 throws BadBytecode 350 { 351 int len = code.length; 352 if (len <= 0) 353 return; 354 355 insertGapCore(pos, len, exclusive); for (int j = 0; j < len; ++j) 357 bytecode[pos++] = code[j]; 358 } 359 360 375 public int insertGap(int length) throws BadBytecode { 376 int pos = currentPos; 377 insertGapCore(currentPos, length, false); 378 return pos; 379 } 380 381 397 public int insertGap(int pos, int length) throws BadBytecode { 398 return insertGapCore(pos, length, false); 399 } 400 401 416 public int insertExGap(int length) throws BadBytecode { 417 int pos = currentPos; 418 insertGapCore(currentPos, length, true); 419 return pos; 420 } 421 422 438 public int insertExGap(int pos, int length) throws BadBytecode { 439 return insertGapCore(pos, length, true); 440 } 441 442 445 private int insertGapCore(int pos, int length, boolean exclusive) 446 throws BadBytecode 447 { 448 if (length <= 0) 449 return 0; 450 451 int cur = currentPos; 452 byte[] c = insertGap(bytecode, pos, length, exclusive, 453 get().getExceptionTable(), codeAttr); 454 int length2 = c.length - bytecode.length; 455 if (cur >= pos) 456 currentPos = cur + length2; 457 458 codeAttr.setCode(c); 459 bytecode = c; 460 endPos = getCodeLength(); 461 return length2; 462 } 463 464 472 public void insert(ExceptionTable et, int offset) { 473 codeAttr.getExceptionTable().add(0, et, offset); 474 } 475 476 482 public int append(byte[] code) { 483 int size = getCodeLength(); 484 int len = code.length; 485 if (len <= 0) 486 return size; 487 488 appendGap(len); 489 byte[] dest = bytecode; 490 for (int i = 0; i < len; ++i) 491 dest[i + size] = code[i]; 492 493 return size; 494 } 495 496 501 public void appendGap(int gapLength) { 502 byte[] code = bytecode; 503 int codeLength = code.length; 504 byte[] newcode = new byte[codeLength + gapLength]; 505 506 int i; 507 for (i = 0; i < codeLength; ++i) 508 newcode[i] = code[i]; 509 510 for (i = codeLength; i < codeLength + gapLength; ++i) 511 newcode[i] = NOP; 512 513 codeAttr.setCode(newcode); 514 bytecode = newcode; 515 endPos = getCodeLength(); 516 } 517 518 526 public void append(ExceptionTable et, int offset) { 527 ExceptionTable table = codeAttr.getExceptionTable(); 528 table.add(table.size(), et, offset); 529 } 530 531 533 private static final int opcodeLength[] = { 534 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 3, 535 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 536 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 537 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 538 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 539 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 540 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 541 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 542 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 543 3, 3, 3, 3, 3, 5, 0, 3, 2, 3, 1, 1, 3, 3, 1, 1, 0, 4, 3, 3, 544 5, 5 545 }; 546 548 551 static int nextOpcode(byte[] code, int index) 552 throws BadBytecode 553 { 554 int opcode; 555 try { 556 opcode = code[index] & 0xff; 557 } 558 catch (IndexOutOfBoundsException e) { 559 throw new BadBytecode("invalid opcode address"); 560 } 561 562 try { 563 int len = opcodeLength[opcode]; 564 if (len > 0) 565 return index + len; 566 else if (opcode == WIDE) 567 if (code[index + 1] == (byte)IINC) return index + 6; 569 else 570 return index + 4; else { 572 int index2 = (index & ~3) + 8; 573 if (opcode == LOOKUPSWITCH) { 574 int npairs = ByteArray.read32bit(code, index2); 575 return index2 + npairs * 8 + 4; 576 } 577 else if (opcode == TABLESWITCH) { 578 int low = ByteArray.read32bit(code, index2); 579 int high = ByteArray.read32bit(code, index2 + 4); 580 return index2 + (high - low + 1) * 4 + 8; 581 } 582 } 585 } 586 catch (IndexOutOfBoundsException e) { 587 } 588 589 throw new BadBytecode(opcode); 591 } 592 593 595 601 static byte[] insertGap(byte[] code, int where, int gapLength, 602 boolean exclusive, ExceptionTable etable, CodeAttribute ca) 603 throws BadBytecode 604 { 605 if (gapLength <= 0) 606 return code; 607 608 try { 609 return insertGap0(code, where, gapLength, exclusive, etable, ca); 610 } 611 catch (AlignmentException e) { 612 try { 613 return insertGap0(code, where, (gapLength + 3) & ~3, 614 exclusive, etable, ca); 615 } 616 catch (AlignmentException e2) { 617 throw new RuntimeException ("fatal error?"); 618 } 619 } 620 } 621 622 private static byte[] insertGap0(byte[] code, int where, int gapLength, 623 boolean exclusive, ExceptionTable etable, 624 CodeAttribute ca) 625 throws BadBytecode, AlignmentException 626 { 627 int codeLength = code.length; 628 byte[] newcode = new byte[codeLength + gapLength]; 629 insertGap2(code, where, gapLength, codeLength, newcode, exclusive); 630 etable.shiftPc(where, gapLength, exclusive); 631 LineNumberAttribute na 632 = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag); 633 if (na != null) 634 na.shiftPc(where, gapLength, exclusive); 635 636 LocalVariableAttribute va = (LocalVariableAttribute)ca.getAttribute( 637 LocalVariableAttribute.tag); 638 if (va != null) 639 va.shiftPc(where, gapLength, exclusive); 640 641 LocalVariableAttribute vta 642 = (LocalVariableAttribute)ca.getAttribute( 643 LocalVariableAttribute.typeTag); 644 if (vta != null) 645 vta.shiftPc(where, gapLength, exclusive); 646 647 return newcode; 648 } 649 650 private static void insertGap2(byte[] code, int where, int gapLength, 651 int endPos, byte[] newcode, boolean exclusive) 652 throws BadBytecode, AlignmentException 653 { 654 int nextPos; 655 int i = 0; 656 int j = 0; 657 for (; i < endPos; i = nextPos) { 658 if (i == where) { 659 int j2 = j + gapLength; 660 while (j < j2) 661 newcode[j++] = NOP; 662 } 663 664 nextPos = nextOpcode(code, i); 665 int inst = code[i] & 0xff; 666 if ((153 <= inst && inst <= 168) 668 || inst == IFNULL || inst == IFNONNULL) { 669 670 int offset = (code[i + 1] << 8) | (code[i + 2] & 0xff); 671 offset = newOffset(i, offset, where, gapLength, exclusive); 672 newcode[j] = code[i]; 673 ByteArray.write16bit(offset, newcode, j + 1); 674 j += 3; 675 } 676 else if (inst == GOTO_W || inst == JSR_W) { 677 678 int offset = ByteArray.read32bit(code, i + 1); 679 offset = newOffset(i, offset, where, gapLength, exclusive); 680 newcode[j++] = code[i]; 681 ByteArray.write32bit(offset, newcode, j); 682 j += 4; 683 } 684 else if (inst == TABLESWITCH) { 685 if (i != j && (gapLength & 3) != 0) 686 throw new AlignmentException(); 687 688 int i0 = i; 689 int i2 = (i & ~3) + 4; while (i0 < i2) 691 newcode[j++] = code[i0++]; 692 693 int defaultbyte = newOffset(i, ByteArray.read32bit(code, i2), 694 where, gapLength, exclusive); 695 ByteArray.write32bit(defaultbyte, newcode, j); 696 int lowbyte = ByteArray.read32bit(code, i2 + 4); 697 ByteArray.write32bit(lowbyte, newcode, j + 4); 698 int highbyte = ByteArray.read32bit(code, i2 + 8); 699 ByteArray.write32bit(highbyte, newcode, j + 8); 700 j += 12; 701 i0 = i2 + 12; 702 i2 = i0 + (highbyte - lowbyte + 1) * 4; 703 while (i0 < i2) { 704 int offset = newOffset(i, ByteArray.read32bit(code, i0), 705 where, gapLength, exclusive); 706 ByteArray.write32bit(offset, newcode, j); 707 j += 4; 708 i0 += 4; 709 } 710 } 711 else if (inst == LOOKUPSWITCH) { 712 if (i != j && (gapLength & 3) != 0) 713 throw new AlignmentException(); 714 715 int i0 = i; 716 int i2 = (i & ~3) + 4; while (i0 < i2) 718 newcode[j++] = code[i0++]; 719 720 int defaultbyte = newOffset(i, ByteArray.read32bit(code, i2), 721 where, gapLength, exclusive); 722 ByteArray.write32bit(defaultbyte, newcode, j); 723 int npairs = ByteArray.read32bit(code, i2 + 4); 724 ByteArray.write32bit(npairs, newcode, j + 4); 725 j += 8; 726 i0 = i2 + 8; 727 i2 = i0 + npairs * 8; 728 while (i0 < i2) { 729 ByteArray.copy32bit(code, i0, newcode, j); 730 int offset = newOffset(i, 731 ByteArray.read32bit(code, i0 + 4), 732 where, gapLength, exclusive); 733 ByteArray.write32bit(offset, newcode, j + 4); 734 j += 8; 735 i0 += 8; 736 } 737 } 738 else 739 while (i < nextPos) 740 newcode[j++] = code[i++]; 741 } 742 } 743 744 private static int newOffset(int i, int offset, int where, 745 int gapLength, boolean exclusive) { 746 int target = i + offset; 747 if (i < where) { 748 if (where < target || (exclusive && where == target)) 749 offset += gapLength; 750 } 751 else 752 if (target < where || (!exclusive && where == target)) 753 offset -= gapLength; 754 755 return offset; 756 } 757 } 758 759 760 class AlignmentException extends Exception { 761 } 762 | Popular Tags |