1 19 20 25 26 27 28 29 30 31 32 package soot.coffi; 33 import soot.*; 34 35 import java.io.*; 36 import java.util.*; 37 import java.util.Enumeration ; 38 import java.util.Vector ; 39 import java.util.*; 40 import soot.*; 41 42 48 public class ClassFile { 49 50 51 static final long MAGIC = 0xCAFEBABEL; 52 53 54 static final short ACC_PUBLIC = 0x0001; 55 56 static final short ACC_PRIVATE = 0x0002; 57 58 static final short ACC_PROTECTED = 0x0004; 59 60 static final short ACC_STATIC = 0x0008; 61 62 static final short ACC_FINAL = 0x0010; 63 64 static final short ACC_SUPER = 0x0020; 65 66 static final short ACC_VOLATILE = 0x0040; 67 68 static final short ACC_TRANSIENT = 0x0080; 69 70 static final short ACC_INTERFACE = 0x0200; 71 72 static final short ACC_ABSTRACT = 0x0400; 73 74 static final short ACC_STRICT = 0x0800; 75 76 static final short ACC_ANNOTATION = 0x2000; 77 78 static final short ACC_ENUM = 0x4000; 79 80 static final short ACC_UNKNOWN = 0x7000; 81 82 83 static final String DESC_BYTE = "B"; 84 85 static final String DESC_CHAR = "C"; 86 87 static final String DESC_DOUBLE = "D"; 88 89 static final String DESC_FLOAT= "F"; 90 91 static final String DESC_INT = "I"; 92 93 static final String DESC_LONG = "J"; 94 95 static final String DESC_OBJECT = "L"; 96 97 static final String DESC_SHORT = "S"; 98 99 static final String DESC_BOOLEAN = "Z"; 100 101 static final String DESC_VOID = "V"; 102 103 static final String DESC_ARRAY = "["; 104 105 106 boolean debug; 107 108 109 String fn; 110 111 113 114 117 long magic; 118 119 int minor_version; 120 121 int major_version; 122 123 public int constant_pool_count; 124 127 public cp_info constant_pool[]; 128 130 public int access_flags; 131 134 public int this_class; 135 138 public int super_class; 139 140 public int interfaces_count; 141 146 public int interfaces[]; 147 148 public int fields_count; 149 152 public field_info fields[]; 153 154 public int methods_count; 155 158 public method_info methods[]; 159 160 public int attributes_count; 161 164 attribute_info attributes[]; 165 166 169 public ClassFile(String nfn) { fn = nfn; } 170 171 172 public String toString() { 173 return (constant_pool[this_class].toString(constant_pool)); 174 } 175 176 public boolean loadClassFile(InputStream is) 177 { 178 InputStream f = null; 179 InputStream classFileStream; 180 DataInputStream d; 181 boolean b; 182 183 classFileStream = is; 184 185 byte[] data; 186 187 188 Timers.v().readTimer.start(); 189 190 try 191 { 192 data = new byte[classFileStream.available()]; 193 classFileStream.read(data); 194 f = new ByteArrayInputStream(data); 195 196 } catch(IOException e) 197 { 198 } 199 200 Timers.v().readTimer.end(); 201 202 d = new DataInputStream(f); 203 b = readClass(d); 204 205 try { 206 classFileStream.close(); 207 d.close(); 208 f.close(); 209 } catch(IOException e) { 210 G.v().out.println("IOException with " + fn + ": " + e.getMessage()); 211 return false; 212 } 213 214 if (!b) return false; 215 return true; 218 } 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 242 boolean saveClassFile() { 243 FileOutputStream f; 244 DataOutputStream d; 245 boolean b; 246 try { 247 f = new FileOutputStream(fn); 248 } catch(FileNotFoundException e) { 249 if (fn.indexOf(".class")>=0) { 250 G.v().out.println("Can't find " + fn); 251 return false; 252 } 253 fn = fn + ".class"; 254 try { 255 f = new FileOutputStream(fn); 256 } catch(FileNotFoundException ee) { 257 G.v().out.println("Can't find " + fn); 258 return false; 259 } catch(IOException ee) { 260 G.v().out.println("IOException with " + fn + ": " + ee.getMessage()); 261 return false; 262 } 263 } catch(IOException e) { 264 G.v().out.println("IOException with " + fn + ": " + e.getMessage()); 265 return false; 266 } 267 d = new DataOutputStream(f); 268 if (d==null) { 269 try { 270 f.close(); 271 } catch(IOException e) { } 272 return false; 273 } 274 b = writeClass(d); 275 try { 276 d.close(); 277 f.close(); 278 } catch(IOException e) { 279 G.v().out.println("IOException with " + fn + ": " + e.getMessage()); 280 return false; 281 } 282 return b; 283 } 284 285 293 static String access_string(int af,String separator) { 294 boolean hasone = false; 295 String s = ""; 296 if ((af & ACC_PUBLIC) != 0) { 297 s = "public"; 298 hasone = true; 299 } 300 if ((af & ACC_PRIVATE) != 0) { 301 if (hasone) s = s + separator; 302 else hasone = true; 303 s = s + "private"; 304 } 305 if ((af & ACC_PROTECTED) != 0) { 306 if (hasone) s = s + separator; 307 else hasone = true; 308 s = s + "protected"; 309 } 310 if ((af & ACC_STATIC) != 0) { 311 if (hasone) s = s + separator; 312 else hasone = true; 313 s = s + "static"; 314 } 315 if ((af & ACC_FINAL) != 0) { 316 if (hasone) s = s + separator; 317 else hasone = true; 318 s = s + "final"; 319 } 320 if ((af & ACC_SUPER) != 0) { 321 if (hasone) s = s + separator; 322 else hasone = true; 323 s = s + "super"; 324 } 325 if ((af & ACC_VOLATILE) != 0) { 326 if (hasone) s = s + separator; 327 else hasone = true; 328 s = s + "volatile"; 329 } 330 if ((af & ACC_TRANSIENT) != 0) { 331 if (hasone) s = s + separator; 332 else hasone = true; 333 s = s + "transient"; 334 } 335 if ((af & ACC_INTERFACE) != 0) { 336 if (hasone) s = s + separator; 337 else hasone = true; 338 s = s + "interface"; 339 } 340 if ((af & ACC_ABSTRACT) != 0) { 341 if (hasone) s = s + separator; 342 else hasone = true; 343 s = s + "abstract"; 344 } 345 if ((af & ACC_STRICT) != 0) { 346 if (hasone) s = s + separator; 347 else hasone = true; 348 s = s + "strict"; 349 } 350 if ((af & ACC_ANNOTATION) != 0) { 351 if (hasone) s = s + separator; 352 else hasone = true; 353 s = s + "annotation"; 354 } 355 if ((af & ACC_ENUM) != 0) { 356 if (hasone) s = s + separator; 357 else hasone = true; 358 s = s + "enum"; 359 } 360 if ((af & ACC_UNKNOWN) != 0) { 361 if (hasone) s = s + separator; 362 else hasone = true; 363 s = s + "unknown"; 364 } 365 return s; 366 } 367 368 373 public boolean readClass(DataInputStream d) { 374 try { 375 magic = d.readInt() & 0xFFFFFFFFL; 377 if (magic != MAGIC) { 378 G.v().out.println("Wrong magic number in " + fn + ": " + magic); 379 return false; 380 } 381 minor_version = d.readUnsignedShort(); 383 major_version = d.readUnsignedShort(); 384 constant_pool_count = d.readUnsignedShort(); 386 388 if (!readConstantPool(d)) 389 return false; 390 391 access_flags = d.readUnsignedShort(); 392 395 396 this_class = d.readUnsignedShort(); 397 super_class = d.readUnsignedShort(); 398 interfaces_count = d.readUnsignedShort(); 399 if (interfaces_count>0) { 400 interfaces = new int[interfaces_count]; 401 int j; 402 for (j=0; j<interfaces_count; j++) 403 interfaces[j] = d.readUnsignedShort(); 404 } 405 407 Timers.v().fieldTimer.start(); 408 409 fields_count = d.readUnsignedShort(); 410 readFields(d); 412 Timers.v().fieldTimer.end(); 413 414 Timers.v().methodTimer.start(); 415 methods_count = d.readUnsignedShort(); 416 readMethods(d); 418 Timers.v().methodTimer.end(); 419 420 Timers.v().attributeTimer.start(); 421 422 attributes_count = d.readUnsignedShort(); 423 if (attributes_count>0) { 425 attributes = new attribute_info[attributes_count]; 426 readAttributes(d,attributes_count,attributes); 427 } 428 Timers.v().attributeTimer.end(); 429 430 } catch(IOException e) { 431 throw new RuntimeException ("IOException with " + fn + ": " + e.getMessage()); 432 } 433 434 437 438 return true; 439 } 440 441 446 protected boolean readConstantPool(DataInputStream d) throws IOException { 447 byte tag; 448 cp_info cp; 449 int i; 450 boolean skipone; 452 constant_pool = new cp_info[constant_pool_count]; 453 skipone = false; 455 456 for (i=1;i<constant_pool_count;i++) { 457 if (skipone) { 458 skipone = false; 459 continue; 460 } 461 tag = (byte)d.readUnsignedByte(); 462 switch(tag) { 463 case cp_info.CONSTANT_Class: 464 cp = new CONSTANT_Class_info(); 465 ((CONSTANT_Class_info)cp).name_index = d.readUnsignedShort(); 466 if (debug) G.v().out.println("Constant pool[" + i + "]: Class"); 467 break; 468 case cp_info.CONSTANT_Fieldref: 469 cp = new CONSTANT_Fieldref_info(); 470 ((CONSTANT_Fieldref_info)cp).class_index = d.readUnsignedShort(); 471 ((CONSTANT_Fieldref_info)cp).name_and_type_index = 472 d.readUnsignedShort(); 473 if (debug) G.v().out.println("Constant pool[" + i + "]: Fieldref"); 474 break; 475 case cp_info.CONSTANT_Methodref: 476 cp = new CONSTANT_Methodref_info(); 477 ((CONSTANT_Methodref_info)cp).class_index = d.readUnsignedShort(); 478 ((CONSTANT_Methodref_info)cp).name_and_type_index = 479 d.readUnsignedShort(); 480 if (debug) G.v().out.println("Constant pool[" + i + "]: Methodref"); 481 break; 482 case cp_info.CONSTANT_InterfaceMethodref: 483 cp = new CONSTANT_InterfaceMethodref_info(); 484 ((CONSTANT_InterfaceMethodref_info)cp).class_index = 485 d.readUnsignedShort(); 486 ((CONSTANT_InterfaceMethodref_info)cp).name_and_type_index = 487 d.readUnsignedShort(); 488 if (debug) 489 G.v().out.println("Constant pool[" + i + "]: InterfaceMethodref"); 490 break; 491 case cp_info.CONSTANT_String: 492 cp = new CONSTANT_String_info(); 493 ((CONSTANT_String_info)cp).string_index = 494 d.readUnsignedShort(); 495 if (debug) G.v().out.println("Constant pool[" + i + "]: String"); 496 break; 497 case cp_info.CONSTANT_Integer: 498 cp = new CONSTANT_Integer_info(); 499 ((CONSTANT_Integer_info)cp).bytes = d.readInt(); 500 if (debug) G.v().out.println("Constant pool[" + i + "]: Integer = " + 501 ((CONSTANT_Integer_info)cp).bytes); 502 break; 503 case cp_info.CONSTANT_Float: 504 cp = new CONSTANT_Float_info(); 505 ((CONSTANT_Float_info)cp).bytes = d.readInt(); 506 if (debug) G.v().out.println("Constant pool[" + i + "]: Float = " + 507 ((CONSTANT_Float_info)cp).convert()); 508 break; 509 case cp_info.CONSTANT_Long: 510 cp = new CONSTANT_Long_info(); 511 ((CONSTANT_Long_info)cp).high = d.readInt() & 0xFFFFFFFFL; 512 ((CONSTANT_Long_info)cp).low = d.readInt() & 0xFFFFFFFFL; 513 514 if (debug) { 515 String temp = cp.toString(constant_pool); 516 G.v().out.println("Constant pool[" + i + "]: Long = " + temp); 517 521 } 522 skipone = true; break; 524 case cp_info.CONSTANT_Double: 525 cp = new CONSTANT_Double_info(); 526 ((CONSTANT_Double_info)cp).high = d.readInt() & 0xFFFFFFFFL; 527 ((CONSTANT_Double_info)cp).low = d.readInt() & 0xFFFFFFFFL; 528 if (debug) G.v().out.println("Constant pool[" + i + "]: Double = " + 529 ((CONSTANT_Double_info)cp).convert()); 530 skipone = true; break; 532 case cp_info.CONSTANT_NameAndType: 533 cp = new CONSTANT_NameAndType_info(); 534 ((CONSTANT_NameAndType_info)cp).name_index = 535 d.readUnsignedShort(); 536 ((CONSTANT_NameAndType_info)cp).descriptor_index = 537 d.readUnsignedShort(); 538 if (debug) G.v().out.println("Constant pool[" + i + "]: Name and Type"); 539 break; 540 case cp_info.CONSTANT_Utf8: 541 CONSTANT_Utf8_info cputf8 = new CONSTANT_Utf8_info(d); 542 cp = (cp_info) CONSTANT_Utf8_collector.v().add(cputf8); 545 if (debug) 546 G.v().out.println("Constant pool[" + i + "]: Utf8 = \"" + 547 cputf8.convert() + "\""); 548 break; 549 default: 550 G.v().out.println("Unknown tag in constant pool: " + 551 tag + " at entry " + i); 552 return false; 553 } 554 cp.tag = tag; 555 constant_pool[i] = cp; 556 } 557 return true; 558 } 559 560 567 protected boolean readAttributes(DataInputStream d,int attributes_count, 568 attribute_info[] ai) throws IOException { 569 attribute_info a=null; 570 int i; 571 int j; 572 long len; 573 String s; 574 575 for (i=0;i<attributes_count;i++) { 576 577 j = d.readUnsignedShort(); len = d.readInt() & 0xFFFFFFFFL; 579 s = ((CONSTANT_Utf8_info)(constant_pool[j])).convert(); 580 if (s.compareTo(attribute_info.SourceFile)==0) 581 { 582 SourceFile_attribute sa = new SourceFile_attribute(); 583 sa.sourcefile_index = d.readUnsignedShort(); 584 a = (attribute_info)sa; 585 } else if(s.compareTo(attribute_info.ConstantValue)==0) 586 { 587 ConstantValue_attribute ca = new ConstantValue_attribute(); 588 ca.constantvalue_index = d.readUnsignedShort(); 589 a = (attribute_info)ca; 590 } else if(s.compareTo(attribute_info.Code)==0) 591 { 592 Code_attribute ca = new Code_attribute(); 593 ca.max_stack = d.readUnsignedShort(); 594 ca.max_locals = d.readUnsignedShort(); 595 ca.code_length = d.readInt() & 0xFFFFFFFFL; 596 ca.code = new byte[(int) ca.code_length]; 597 d.read(ca.code); 598 ca.exception_table_length = d.readUnsignedShort(); 599 ca.exception_table = new exception_table_entry[ca.exception_table_length]; 600 int k; 601 exception_table_entry e; 602 for (k=0; k<ca.exception_table_length; k++) { 603 e = new exception_table_entry(); 604 e.start_pc = d.readUnsignedShort(); 605 e.end_pc = d.readUnsignedShort(); 606 e.handler_pc = d.readUnsignedShort(); 607 e.catch_type = d.readUnsignedShort(); 608 ca.exception_table[k] = e; 609 } 610 ca.attributes_count = d.readUnsignedShort(); 611 ca.attributes = new attribute_info[ca.attributes_count]; 612 readAttributes(d,ca.attributes_count,ca.attributes); 613 a = (attribute_info)ca; 614 615 616 } else if(s.compareTo(attribute_info.Exceptions)==0) 617 { 618 Exception_attribute ea = new Exception_attribute(); 619 ea.number_of_exceptions = d.readUnsignedShort(); 620 if (ea.number_of_exceptions>0) { 621 int k; 622 ea.exception_index_table = new int[ea.number_of_exceptions]; 623 for (k=0; k<ea.number_of_exceptions; k++) 624 ea.exception_index_table[k] = d.readUnsignedShort(); 625 } 626 a = (attribute_info)ea; 627 } else if(s.compareTo(attribute_info.LineNumberTable)==0) 628 { 629 LineNumberTable_attribute la = new LineNumberTable_attribute(); 630 la.line_number_table_length = d.readUnsignedShort(); 631 int k; 632 line_number_table_entry e; 633 la.line_number_table = new 634 line_number_table_entry[la.line_number_table_length]; 635 for (k=0; k<la.line_number_table_length; k++) { 636 e = new line_number_table_entry(); 637 e.start_pc = d.readUnsignedShort(); 638 e.line_number = d.readUnsignedShort(); 639 la.line_number_table[k] = e; 640 } 641 a = (attribute_info)la; 642 } 643 else if(s.compareTo(attribute_info.LocalVariableTable)==0) 644 { 645 LocalVariableTable_attribute la = new LocalVariableTable_attribute(); 646 la.local_variable_table_length = d.readUnsignedShort(); 647 int k; 648 local_variable_table_entry e; 649 la.local_variable_table = 650 new local_variable_table_entry[la.local_variable_table_length]; 651 for (k=0; k<la.local_variable_table_length; k++) { 652 e = new local_variable_table_entry(); 653 e.start_pc = d.readUnsignedShort(); 654 e.length = d.readUnsignedShort(); 655 e.name_index = d.readUnsignedShort(); 656 e.descriptor_index = d.readUnsignedShort(); 657 e.index = d.readUnsignedShort(); 658 la.local_variable_table[k] = e; 659 } 660 a = (attribute_info)la; 661 } 662 else if(s.compareTo(attribute_info.LocalVariableTypeTable)==0) 663 { 664 LocalVariableTypeTable_attribute la = new LocalVariableTypeTable_attribute(); 665 la.local_variable_type_table_length = d.readUnsignedShort(); 666 int k; 667 local_variable_type_table_entry e; 668 la.local_variable_type_table = 669 new local_variable_type_table_entry[la.local_variable_type_table_length]; 670 for (k=0; k<la.local_variable_type_table_length; k++) { 671 e = new local_variable_type_table_entry(); 672 e.start_pc = d.readUnsignedShort(); 673 e.length = d.readUnsignedShort(); 674 e.name_index = d.readUnsignedShort(); 675 e.signature_index = d.readUnsignedShort(); 676 e.index = d.readUnsignedShort(); 677 la.local_variable_type_table[k] = e; 678 } 679 a = (attribute_info)la; 680 } 681 else if (s.compareTo(attribute_info.Synthetic)==0){ 682 Synthetic_attribute ia = new Synthetic_attribute(); 683 a = (attribute_info)ia; 684 } 685 else if (s.compareTo(attribute_info.Signature)==0){ 686 Signature_attribute ia = new Signature_attribute(); 687 ia.signature_index = d.readUnsignedShort(); 688 a = (attribute_info)ia; 689 } 690 else if (s.compareTo(attribute_info.Deprecated)==0){ 691 Deprecated_attribute da = new Deprecated_attribute(); 692 a = (attribute_info)da; 693 } 694 else if (s.compareTo(attribute_info.EnclosingMethod)==0){ 695 EnclosingMethod_attribute ea = new EnclosingMethod_attribute(); 696 ea.class_index = d.readUnsignedShort(); 697 ea.method_index = d.readUnsignedShort(); 698 a = (attribute_info)ea; 699 } 700 else if(s.compareTo(attribute_info.InnerClasses)==0) 701 { 702 InnerClasses_attribute ia = new InnerClasses_attribute(); 703 ia.inner_classes_length = d.readUnsignedShort(); 704 ia.inner_classes = new inner_class_entry[ia.inner_classes_length]; 705 for (int k = 0; k < ia.inner_classes_length; k++) { 706 inner_class_entry e = new inner_class_entry(); 707 e.inner_class_index = d.readUnsignedShort(); 708 e.outer_class_index = d.readUnsignedShort(); 709 e.name_index = d.readUnsignedShort(); 710 e.access_flags = d.readUnsignedShort(); 711 ia.inner_classes[k] = e; 712 } 713 a = (attribute_info)ia; 714 } 715 else if (s.compareTo(attribute_info.RuntimeVisibleAnnotations)==0) 716 { 717 RuntimeVisibleAnnotations_attribute ra = new RuntimeVisibleAnnotations_attribute(); 718 ra.number_of_annotations = d.readUnsignedShort(); 719 ra.annotations = new annotation[ra.number_of_annotations]; 720 for (int k = 0; k < ra.number_of_annotations; k++){ 721 annotation annot = new annotation(); 722 annot.type_index = d.readUnsignedShort(); 723 annot.num_element_value_pairs = d.readUnsignedShort(); 724 annot.element_value_pairs = readElementValues(annot.num_element_value_pairs, d, true, 0); 725 ra.annotations[k] = annot; 726 } 727 728 a = (attribute_info)ra; 729 } 730 else if (s.compareTo(attribute_info.RuntimeInvisibleAnnotations)==0) 731 { 732 RuntimeInvisibleAnnotations_attribute ra = new RuntimeInvisibleAnnotations_attribute(); 733 ra.number_of_annotations = d.readUnsignedShort(); 734 ra.annotations = new annotation[ra.number_of_annotations]; 735 for (int k = 0; k < ra.number_of_annotations; k++){ 736 annotation annot = new annotation(); 737 annot.type_index = d.readUnsignedShort(); 738 annot.num_element_value_pairs = d.readUnsignedShort(); 739 annot.element_value_pairs = readElementValues(annot.num_element_value_pairs, d, true, 0); 740 ra.annotations[k] = annot; 741 } 742 a = (attribute_info)ra; 743 } 744 else if (s.compareTo(attribute_info.RuntimeVisibleParameterAnnotations)==0) 745 { 746 RuntimeVisibleParameterAnnotations_attribute ra = new RuntimeVisibleParameterAnnotations_attribute(); 747 ra.num_parameters = d.readUnsignedByte(); 748 ra.parameter_annotations = new parameter_annotation[ra.num_parameters]; 749 for (int x = 0; x < ra.num_parameters; x++){ 750 parameter_annotation pAnnot = new parameter_annotation(); 751 pAnnot.num_annotations = d.readUnsignedShort(); 752 pAnnot.annotations = new annotation[pAnnot.num_annotations]; 753 for (int k = 0; k < pAnnot.num_annotations; k++){ 754 annotation annot = new annotation(); 755 annot.type_index = d.readUnsignedShort(); 756 annot.num_element_value_pairs = d.readUnsignedShort(); 757 annot.element_value_pairs = readElementValues(annot.num_element_value_pairs, d, true, 0); 758 pAnnot.annotations[k] = annot; 759 } 760 ra.parameter_annotations[x] = pAnnot; 761 } 762 a = (attribute_info)ra; 763 } 764 else if (s.compareTo(attribute_info.RuntimeInvisibleParameterAnnotations)==0) 765 { 766 RuntimeInvisibleParameterAnnotations_attribute ra = new RuntimeInvisibleParameterAnnotations_attribute(); 767 ra.num_parameters = d.readUnsignedByte(); 768 ra.parameter_annotations = new parameter_annotation[ra.num_parameters]; 769 for (int x = 0; x < ra.num_parameters; x++){ 770 parameter_annotation pAnnot = new parameter_annotation(); 771 pAnnot.num_annotations = d.readUnsignedShort(); 772 pAnnot.annotations = new annotation[pAnnot.num_annotations]; 773 for (int k = 0; k < pAnnot.num_annotations; k++){ 774 annotation annot = new annotation(); 775 annot.type_index = d.readUnsignedShort(); 776 annot.num_element_value_pairs = d.readUnsignedShort(); 777 annot.element_value_pairs = readElementValues(annot.num_element_value_pairs, d, true, 0); 778 pAnnot.annotations[k] = annot; 779 } 780 ra.parameter_annotations[x] = pAnnot; 781 } 782 a = (attribute_info)ra; 783 } 784 else if (s.compareTo(attribute_info.AnnotationDefault)==0){ 785 AnnotationDefault_attribute da = new AnnotationDefault_attribute(); 786 element_value [] result = readElementValues(1, d, false, 0); 787 da.default_value = result[0]; 788 a = (attribute_info)da; 789 } 790 else { 791 Generic_attribute ga = new Generic_attribute(); 794 if (len>0) { 795 ga.info = new byte[(int) len]; 796 d.read(ga.info); 797 } 798 a = (attribute_info)ga; 799 } 800 a.attribute_name = j; 801 a.attribute_length = len; 802 ai[i] = a; 803 } 804 return true; 805 } 806 807 private element_value [] readElementValues(int count, DataInputStream d, boolean needName, int name_index) 808 throws IOException { 809 element_value [] list = new element_value[count]; 810 for (int x = 0; x < count; x++){ 811 if (needName){ 812 name_index = d.readUnsignedShort(); 813 } 814 int tag = d.readUnsignedByte(); 815 char kind = (char)tag; 816 if (kind == 'B' || kind == 'C' || kind == 'D' || kind == 'F' || kind == 'I' || kind == 'J' || kind == 'S' || kind == 'Z' || kind == 's'){ 817 constant_element_value elem = new constant_element_value(); 818 elem.name_index = name_index; 819 elem.tag = kind; 820 elem.constant_value_index = d.readUnsignedShort(); 821 list[x] = elem; 822 } 823 else if (kind == 'e'){ 824 enum_constant_element_value elem = new enum_constant_element_value(); 825 elem.name_index = name_index; 826 elem.tag = kind; 827 elem.type_name_index = d.readUnsignedShort(); 828 elem.constant_name_index = d.readUnsignedShort(); 829 list[x] = elem; 830 } 831 else if (kind == 'c'){ 832 class_element_value elem = new class_element_value(); 833 elem.name_index = name_index; 834 elem.tag = kind; 835 elem.class_info_index = d.readUnsignedShort(); 836 list[x] = elem; 837 } 838 else if (kind == '['){ 839 array_element_value elem = new array_element_value(); 840 elem.name_index = name_index; 841 elem.tag = kind; 842 elem.num_values = d.readUnsignedShort(); 843 elem.values = readElementValues(elem.num_values, d, false, name_index); 844 list[x] = elem; 845 } 846 else if (kind == '@'){ 847 annotation_element_value elem = new annotation_element_value(); 848 elem.name_index = name_index; 849 elem.tag = kind; 850 annotation annot = new annotation(); 851 annot.type_index = d.readUnsignedShort(); 852 annot.num_element_value_pairs = d.readUnsignedShort(); 853 annot.element_value_pairs = readElementValues(annot.num_element_value_pairs, d, true, 0); 854 elem.annotation_value = annot; 855 list[x] = elem; 856 } 857 else { 858 throw new RuntimeException ("Unknown element value pair kind: "+kind); 859 } 860 } 861 return list; 862 } 863 864 869 protected boolean readFields(DataInputStream d) throws IOException { 870 field_info fi; 871 int i; 872 873 fields = new field_info[fields_count]; 874 875 for (i=0;i<fields_count;i++) { 876 fi = new field_info(); 877 fi.access_flags = d.readUnsignedShort(); 878 fi.name_index = d.readUnsignedShort(); 879 fi.descriptor_index = d.readUnsignedShort(); 880 fi.attributes_count = d.readUnsignedShort(); 881 if (fi.attributes_count>0) { 882 fi.attributes = new attribute_info[fi.attributes_count]; 883 readAttributes(d,fi.attributes_count,fi.attributes); 884 } 885 888 fields[i] = fi; 889 } 890 891 return true; 892 } 893 894 899 protected boolean readMethods(DataInputStream d) throws IOException { 900 method_info mi; 901 int i; 902 903 methods = new method_info[methods_count]; 904 905 for (i=0;i<methods_count;i++) { 906 mi = new method_info(); 907 mi.access_flags = d.readUnsignedShort(); 908 909 mi.name_index = d.readUnsignedShort(); 910 911 mi.descriptor_index = d.readUnsignedShort(); 912 913 mi.attributes_count = d.readUnsignedShort(); 914 915 CONSTANT_Utf8_info ci; 916 ci = (CONSTANT_Utf8_info)(constant_pool[mi.name_index]); 917 919 if (mi.attributes_count>0) { 920 mi.attributes = new attribute_info[mi.attributes_count]; 921 readAttributes(d,mi.attributes_count,mi.attributes); 922 923 for (int j=0; j<mi.attributes_count; j++) 924 { 925 if (mi.attributes[j] instanceof Code_attribute) 926 { 927 mi.code_attr = (Code_attribute)mi.attributes[j]; 928 break; 929 } 930 } 931 } 932 933 936 937 methods[i] = mi; 938 } 939 940 return true; 941 } 942 943 956 957 962 protected boolean writeConstantPool(DataOutputStream dd) throws IOException { 963 byte tag; 964 cp_info cp; 965 int i; 966 boolean skipone = false; 967 968 for (i=1;i<constant_pool_count;i++) { 969 if (skipone) { 970 skipone = false; 971 continue; 972 } 973 cp = constant_pool[i]; 974 dd.writeByte(cp.tag); 975 switch(cp.tag) { 976 case cp_info.CONSTANT_Class: 977 dd.writeShort(((CONSTANT_Class_info)cp).name_index); 978 break; 979 case cp_info.CONSTANT_Fieldref: 980 dd.writeShort(((CONSTANT_Fieldref_info)cp).class_index); 981 dd.writeShort(((CONSTANT_Fieldref_info)cp).name_and_type_index); 982 break; 983 case cp_info.CONSTANT_Methodref: 984 dd.writeShort(((CONSTANT_Methodref_info)cp).class_index); 985 dd.writeShort(((CONSTANT_Methodref_info)cp).name_and_type_index); 986 break; 987 case cp_info.CONSTANT_InterfaceMethodref: 988 dd.writeShort(((CONSTANT_InterfaceMethodref_info)cp).class_index); 989 dd.writeShort(((CONSTANT_InterfaceMethodref_info)cp).name_and_type_index); 990 break; 991 case cp_info.CONSTANT_String: 992 dd.writeShort(((CONSTANT_String_info)cp).string_index); 993 break; 994 case cp_info.CONSTANT_Integer: 995 dd.writeInt((int) ((CONSTANT_Integer_info)cp).bytes); 996 break; 997 case cp_info.CONSTANT_Float: 998 dd.writeInt((int) ((CONSTANT_Float_info)cp).bytes); 999 break; 1000 case cp_info.CONSTANT_Long: 1001 dd.writeInt((int) ((CONSTANT_Long_info)cp).high); 1002 dd.writeInt((int) ((CONSTANT_Long_info)cp).low); 1003 skipone = true; 1004 break; 1005 case cp_info.CONSTANT_Double: 1006 dd.writeInt((int) ((CONSTANT_Double_info)cp).high); 1007 dd.writeInt((int) ((CONSTANT_Double_info)cp).low); 1008 skipone = true; 1009 break; 1010 case cp_info.CONSTANT_NameAndType: 1011 dd.writeShort(((CONSTANT_NameAndType_info)cp).name_index); 1012 dd.writeShort(((CONSTANT_NameAndType_info)cp).descriptor_index); 1013 break; 1014 case cp_info.CONSTANT_Utf8: 1015 ((CONSTANT_Utf8_info)cp).writeBytes(dd); 1016 break; 1017 default: 1018 G.v().out.println("Unknown tag in constant pool: " + cp.tag); 1019 return false; 1020 } 1021 } 1022 return true; 1023 } 1024 1025 1032 protected boolean writeAttributes(DataOutputStream dd, int attributes_count, 1033 attribute_info[] ai) throws IOException { 1034 attribute_info a=null; 1035 int i,len; 1036 short j; 1037 String s; 1038 1039 for (i=0;i<attributes_count;i++) { 1040 a = ai[i]; 1041 dd.writeShort(a.attribute_name); 1042 dd.writeInt((int) a.attribute_length); 1043 if (a instanceof SourceFile_attribute) { 1044 SourceFile_attribute sa = (SourceFile_attribute)a; 1045 dd.writeShort(sa.sourcefile_index); 1046 } else if(a instanceof ConstantValue_attribute) { 1047 ConstantValue_attribute ca = (ConstantValue_attribute)a; 1048 dd.writeShort(ca.constantvalue_index); 1049 } else if(a instanceof Code_attribute) { 1050 Code_attribute ca = (Code_attribute)a; 1051 dd.writeShort(ca.max_stack); 1052 dd.writeShort(ca.max_locals); 1053 dd.writeInt((int) ca.code_length); 1054 dd.write(ca.code,0, (int) ca.code_length); 1055 dd.writeShort(ca.exception_table_length); 1056 int k; 1057 exception_table_entry e; 1058 for (k=0; k<ca.exception_table_length; k++) { 1059 e = ca.exception_table[k]; 1060 dd.writeShort(e.start_pc); 1061 dd.writeShort(e.end_pc); 1062 dd.writeShort(e.handler_pc); 1063 dd.writeShort(e.catch_type); 1064 } 1065 dd.writeShort(ca.attributes_count); 1066 if (ca.attributes_count>0) 1067 writeAttributes(dd,ca.attributes_count,ca.attributes); 1068 } else if(a instanceof Exception_attribute) { 1069 Exception_attribute ea = (Exception_attribute)a; 1070 dd.writeShort(ea.number_of_exceptions); 1071 if (ea.number_of_exceptions>0) { 1072 int k; 1073 for (k=0; k<ea.number_of_exceptions; k++) 1074 dd.writeShort(ea.exception_index_table[k]); 1075 } 1076 } else if(a instanceof LineNumberTable_attribute) { 1077 LineNumberTable_attribute la = (LineNumberTable_attribute)a; 1078 dd.writeShort(la.line_number_table_length); 1079 int k; 1080 line_number_table_entry e; 1081 for (k=0; k<la.line_number_table_length; k++) { 1082 e = la.line_number_table[k]; 1083 dd.writeShort(e.start_pc); 1084 dd.writeShort(e.line_number); 1085 } 1086 } else if(a instanceof LocalVariableTable_attribute) { 1087 LocalVariableTable_attribute la = (LocalVariableTable_attribute)a; 1088 dd.writeShort(la.local_variable_table_length); 1089 int k; 1090 local_variable_table_entry e; 1091 for (k=0; k<la.local_variable_table_length; k++) { 1092 e = la.local_variable_table[k]; 1093 dd.writeShort(e.start_pc); 1094 dd.writeShort(e.length); 1095 dd.writeShort(e.name_index); 1096 dd.writeShort(e.descriptor_index); 1097 dd.writeShort(e.index); 1098 } 1099 } else { 1100 G.v().out.println("Generic/Unknown Attribute in output"); 1102 Generic_attribute ga = (Generic_attribute)a; 1103 if (ga.attribute_length>0) { 1104 dd.write(ga.info,0,(int) ga.attribute_length); 1105 } 1106 } 1107 } 1108 return true; 1109 } 1110 1111 1116 protected boolean writeFields(DataOutputStream dd) throws IOException { 1117 field_info fi; 1118 int i; 1119 1120 for (i=0;i<fields_count;i++) { 1121 fi = fields[i]; 1122 dd.writeShort(fi.access_flags); 1123 dd.writeShort(fi.name_index); 1124 dd.writeShort(fi.descriptor_index); 1125 dd.writeShort(fi.attributes_count); 1126 if (fi.attributes_count>0) { 1127 writeAttributes(dd,fi.attributes_count,fi.attributes); 1128 } 1129 } 1130 return true; 1131 } 1132 1133 1138 protected boolean writeMethods(DataOutputStream dd) throws IOException { 1139 method_info mi; 1140 int i; 1141 1142 for (i=0;i<methods_count;i++) { 1143 mi = methods[i]; 1144 dd.writeShort(mi.access_flags); 1145 dd.writeShort(mi.name_index); 1146 dd.writeShort(mi.descriptor_index); 1147 dd.writeShort(mi.attributes_count); 1148 if (mi.attributes_count>0) { 1149 writeAttributes(dd,mi.attributes_count,mi.attributes); 1150 } 1151 } 1152 return true; 1153 } 1154 1155 1159 boolean writeClass(DataOutputStream dd) { 1160 try { 1162 dd.writeInt((int) magic); 1164 1165 dd.writeShort(minor_version); 1166 dd.writeShort(major_version); 1167 dd.writeShort(constant_pool_count); 1168 1169 if (!writeConstantPool(dd)) 1170 return false; 1171 1172 dd.writeShort(access_flags); 1173 dd.writeShort(this_class); 1174 dd.writeShort(super_class); 1175 dd.writeShort(interfaces_count); 1176 if (interfaces_count>0) { 1177 int j; 1178 for (j=0; j<interfaces_count; j++) 1179 dd.writeShort(interfaces[j]); 1180 } 1181 1182 dd.writeShort(fields_count); 1183 writeFields(dd); 1184 1185 dd.writeShort(methods_count); 1186 writeMethods(dd); 1187 1188 dd.writeShort(attributes_count); 1189 if (attributes_count>0) { 1190 writeAttributes(dd,attributes_count,attributes); 1191 } 1192 } catch(IOException e) { 1193 G.v().out.println("IOException with " + fn + ": " + e.getMessage()); 1194 return false; 1195 } 1196 return true; 1197 } 1198 1199 1207 public Instruction parseMethod(method_info m) { 1208 int j; 1210 Code_attribute ca; 1211 ByteCode bc; 1212 Instruction inst,head,tail; 1213 exception_table_entry e; 1214 1215 head = null; 1216 tail = null; 1217 bc = new ByteCode(); 1218 1219 ca = m.locate_code_attribute(); 1220 if (ca==null) return null; 1221 1222 j = 0; 1223 while(j<ca.code_length) { 1224 inst = bc.disassemble_bytecode(ca.code,j); 1225 inst.originalIndex = j; 1226 1229 if (inst instanceof Instruction_Unknown) { 1230 G.v().out.println("Unknown instruction in \"" + m.toName(constant_pool) + 1231 "\" at offset " + j); 1232 G.v().out.println(" bytecode = " + (((int)(inst.code))&0xff)); 1233 } 1234 j = inst.nextOffset(j); 1236 1238 if ( head==null ) 1239 head = inst; 1240 else 1241 { 1242 tail.next = inst; 1243 inst.prev = tail; 1244 } 1245 tail = inst; 1246 } 1247 1248 bc.build(head); 1250 1251 for (j=0;j<ca.exception_table_length;j++) { 1253 e = ca.exception_table[j]; 1254 e.start_inst = bc.locateInst(e.start_pc); 1255 if (e.end_pc == ca.code_length) 1256 e.end_inst = null; 1257 else 1258 e.end_inst = bc.locateInst(e.end_pc); 1259 e.handler_inst = bc.locateInst(e.handler_pc); 1260 if (e.handler_inst!=null) 1261 e.handler_inst.labelled = true; 1262 } 1263 1264 m.instructions = head; 1265 1266 for (int k=0; k<ca.attributes.length; k++) 1268 { 1269 if (ca.attributes[k] instanceof LineNumberTable_attribute) 1270 { 1271 LineNumberTable_attribute lntattr = 1272 (LineNumberTable_attribute)ca.attributes[k]; 1273 1274 for (int l=0; l<lntattr.line_number_table.length; l++) 1275 { 1276 lntattr.line_number_table[l].start_inst = 1277 bc.locateInst(lntattr.line_number_table[l].start_pc); 1278 } 1279 } 1280 } 1281 1282 return head; 1283 } 1284 1285 1290 public void parse() { 1291 method_info mi; 1292 int i; 1293 1294 for (i=0;i<methods_count;i++) { 1295 mi = methods[i]; 1296 mi.instructions = parseMethod(mi); 1297 } 1300 } 1301 1302 1308 int relabel(Instruction i) { 1309 int index = 0; 1310 while (i!=null) { 1311 i.label = index; 1312 index = i.nextOffset(index); 1313 i = i.next; 1314 } 1315 return index; 1316 } 1317 1318 1328 byte[] unparseMethod(method_info m) { 1329 int codesize; 1330 byte bc[]; 1331 Instruction i; 1332 1333 m.cfg.reconstructInstructions(); 1335 1336 codesize = relabel(m.instructions); 1338 1339 bc = new byte[codesize]; 1341 if (bc==null) { 1342 G.v().out.println("Warning: can't allocate memory for recompile"); 1343 return null; 1344 } 1345 1346 i = m.instructions; 1348 codesize = 0; 1349 while (i!=null) { 1350 codesize = i.compile(bc,codesize); 1351 i = i.next; 1352 } 1353 if (codesize != bc.length) 1354 G.v().out.println("Warning: code size doesn't match array length!"); 1355 1356 return bc; 1357 } 1358 1359 1364 void unparse() { 1365 int i,j; 1366 Code_attribute ca; 1367 byte bc[]; 1368 method_info mi; 1369 exception_table_entry e; 1370 1371 for (i=0;i<methods_count;i++) { 1372 mi = methods[i]; 1373 ca = mi.locate_code_attribute(); 1375 if (ca==null) continue; 1376 bc = unparseMethod(mi); 1377 if (bc==null) { 1378 G.v().out.println("Recompile of " + mi.toName(constant_pool) + " failed!"); 1379 } else { 1380 ca.code_length = bc.length; 1381 ca.code = bc; 1382 for (j=0;j<ca.exception_table_length;j++) { 1384 e = ca.exception_table[j]; 1385 e.start_pc = (e.start_inst.label); 1386 if (e.end_inst!=null) 1387 e.end_pc = (e.end_inst.label); 1388 else 1389 e.end_pc = (int) (ca.code_length); 1390 e.handler_pc = (e.handler_inst.label); 1391 } 1392 } 1393 } 1394 } 1395 1396 1402 static String parseMethodDesc_return(String s) { 1403 int j; 1404 j = s.lastIndexOf(')'); 1405 if (j>=0) { 1406 return parseDesc(s.substring(j+1),","); 1407 } 1408 return parseDesc(s,","); 1409 } 1410 1411 1417 static String parseMethodDesc_params(String s) { 1418 int i,j; 1419 i = s.indexOf('('); 1420 if (i>=0) { 1421 j = s.indexOf(')',i+1); 1422 if (j>=0) { 1423 return parseDesc(s.substring(i+1,j),","); 1424 } 1425 } 1426 return "<parse error>"; 1427 } 1428 1429 1436 static String parseDesc(String desc,String sep) { 1437 String params = "",param; 1438 char c; 1439 int i,len,arraylevel=0; 1440 boolean didone = false; 1441 1442 len = desc.length(); 1443 for (i=0;i<len;i++) { 1444 c = desc.charAt(i); 1445 if (c==DESC_BYTE.charAt(0)) { 1446 param = "byte"; 1447 } else if (c==DESC_CHAR.charAt(0)) { 1448 param = "char"; 1449 } else if (c==DESC_DOUBLE.charAt(0)) { 1450 param = "double"; 1451 } else if (c==DESC_FLOAT.charAt(0)) { 1452 param = "float"; 1453 } else if (c==DESC_INT.charAt(0)) { 1454 param = "int"; 1455 } else if (c==DESC_LONG.charAt(0)) { 1456 param = "long"; 1457 } else if (c==DESC_SHORT.charAt(0)) { 1458 param = "short"; 1459 } else if (c==DESC_BOOLEAN.charAt(0)) { 1460 param = "boolean"; 1461 } else if (c==DESC_VOID.charAt(0)) { 1462 param = "void"; 1463 } else if (c==DESC_ARRAY.charAt(0)) { 1464 arraylevel++; 1465 continue; 1466 } else if (c==DESC_OBJECT.charAt(0)) { 1467 int j; 1468 j = desc.indexOf(';',i+1); 1469 if (j<0) { 1470 G.v().out.println("Warning: Parse error -- can't find a ; in " + 1471 desc.substring(i+1)); 1472 param = "<error>"; 1473 } else { 1474 if (j-i>10 && desc.substring(i+1,i+11).compareTo("java/lang/")==0) 1475 i = i+10; 1476 param = desc.substring(i+1,j); 1477 param = param.replace('/','.'); 1479 i = j; 1480 } 1481 } else { 1482 param = "???"; 1483 } 1484 if (didone) params = params + sep; 1485 params = params + param; 1486 while (arraylevel>0) { 1487 params = params + "[]"; 1488 arraylevel--; 1489 } 1490 didone = true; 1491 } 1492 return params; 1493 } 1494 1495 1496 1501 method_info findMethod(String s) { 1502 method_info m; 1503 int i; 1504 1505 for (i=0;i<methods_count;i++) { 1506 m = methods[i]; 1507 if (s.equals(m.toName(constant_pool))) { 1508 return m; 1509 } 1510 } 1511 return null; 1512 } 1513 1514 1519 void listMethods() { 1520 int i; 1521 1522 for (i=0;i<methods_count;i++) { 1523 G.v().out.println(methods[i].prototype(constant_pool)); 1524 } 1525 } 1526 1527 1532 void listConstantPool() { 1533 cp_info c; 1534 int i; 1535 1536 for (i=1;i<constant_pool_count;i++) { 1538 c = constant_pool[i]; 1539 G.v().out.println("[" + i + "] " + c.typeName() + 1540 "=" + c.toString(constant_pool)); 1541 if ((constant_pool[i]).tag==cp_info.CONSTANT_Long || 1542 (constant_pool[i]).tag==cp_info.CONSTANT_Double) { 1543 i++; 1545 } 1546 } 1547 } 1548 1549 1556 void listFields() { 1557 field_info fi; 1558 ConstantValue_attribute cva; 1559 CONSTANT_Utf8_info cm; 1560 int i,j; 1561 1562 for (i=0;i<fields_count;i++) { 1563 fi = fields[i]; 1564 G.v().out.print(fi.prototype(constant_pool)); 1565 for (j=0;j<fi.attributes_count;j++) { 1567 cm = (CONSTANT_Utf8_info)(constant_pool[fi.attributes[j].attribute_name]); 1568 if (cm.convert().compareTo(attribute_info.ConstantValue)==0) { 1569 cva = (ConstantValue_attribute)(fi.attributes[j]); 1570 G.v().out.print(" = " + 1572 constant_pool[cva.constantvalue_index]. 1573 toString(constant_pool)); 1574 break; 1575 } 1576 } 1577 G.v().out.println(";"); 1578 } 1579 } 1580 1581 1586 void moveMethod(String m,int pos) { 1587 int i,j; 1588 method_info mthd; 1589 G.v().out.println("Moving " + m + " to position " + pos + 1590 " of " + methods_count); 1591 1592 for (i=0;i<methods_count;i++) { 1593 if (m.compareTo(methods[i].toName(constant_pool))==0) { 1594 mthd = methods[i]; 1595 if (i>pos) { 1596 for (j=i;j>pos && j>0;j--) 1597 methods[j] = methods[j-1]; 1598 methods[pos] = mthd; 1599 } else if (i<pos) { 1600 for (j=i;j<pos && j<methods_count-1;j++) 1601 methods[j] = methods[j+1]; 1602 methods[pos] = mthd; 1603 } 1604 return; 1605 } 1606 } 1607 } 1608 1609 1615 boolean descendsFrom(ClassFile cf) { return descendsFrom(cf.toString()); } 1616 1617 1623 boolean descendsFrom(String cname) { 1624 cp_info cf; 1625 int i; 1626 cf = constant_pool[super_class]; 1627 if (cf.toString(constant_pool).compareTo(cname)==0) return true; 1628 for (i=0;i<interfaces_count;i++) { 1629 cf = constant_pool[interfaces[i]]; 1630 if (cf.toString(constant_pool).compareTo(cname)==0) return true; 1631 } 1632 return false; 1633 } 1634 1635 1638 boolean isSterile() { 1639 if ((access_flags&ACC_PUBLIC)!=0 && (access_flags&ACC_FINAL)==0) return false; 1640 return true; 1641 } 1642 1643 1647 boolean sameClass(String cfn) { 1648 String s = cfn; 1649 int i = s.lastIndexOf(".class"); 1650 if (i>0) { s = s.substring(0,i); } 1653 if (s.compareTo(toString())==0) 1654 return true; 1655 return false; 1656 } 1657 1658 1662 String fieldName(int i) { 1663 return fields[i].toName(constant_pool); 1664 } 1665 1666 1848 1849 1850} 1851 1852 1853 1854 1855 1856 1857 | Popular Tags |