00001 package ca.mcgill.sable.soot.coffi;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 import java.io.*;
00125 import java.util.Enumeration;
00126 import java.util.Vector;
00127 import ca.mcgill.sable.util.ClassLocator;
00128 import ca.mcgill.sable.soot.jimple.Main;
00129
00130
00131
00132
00133
00134
00135
00136 public class ClassFile {
00137
00138
00139 static final long MAGIC = 0xCAFEBABEL;
00140
00141
00142 static final short ACC_PUBLIC = 0x0001;
00143
00144 static final short ACC_PRIVATE = 0x0002;
00145
00146 static final short ACC_PROTECTED = 0x0004;
00147
00148 static final short ACC_STATIC = 0x0008;
00149
00150 static final short ACC_FINAL = 0x0010;
00151
00152 static final short ACC_SUPER = 0x0020;
00153
00154 static final short ACC_VOLATILE = 0x0040;
00155
00156 static final short ACC_TRANSIENT = 0x0080;
00157
00158 static final short ACC_INTERFACE = 0x0200;
00159
00160 static final short ACC_ABSTRACT = 0x0400;
00161
00162 static final short ACC_UNKNOWN = 0x7800;
00163
00164
00165 static final String DESC_BYTE = "B";
00166
00167 static final String DESC_CHAR = "C";
00168
00169 static final String DESC_DOUBLE = "D";
00170
00171 static final String DESC_FLOAT= "F";
00172
00173 static final String DESC_INT = "I";
00174
00175 static final String DESC_LONG = "J";
00176
00177 static final String DESC_OBJECT = "L";
00178
00179 static final String DESC_SHORT = "S";
00180
00181 static final String DESC_BOOLEAN = "Z";
00182
00183 static final String DESC_VOID = "V";
00184
00185 static final String DESC_ARRAY = "[";
00186
00187
00188 boolean debug;
00189
00190
00191 String fn;
00192
00193
00194
00195
00196
00197
00198
00199 long magic;
00200
00201 int minor_version;
00202
00203 int major_version;
00204
00205 int constant_pool_count;
00206
00207
00208
00209 public cp_info constant_pool[];
00210
00211
00212 int access_flags;
00213
00214
00215
00216 public int this_class;
00217
00218
00219
00220 int super_class;
00221
00222 int interfaces_count;
00223
00224
00225
00226
00227
00228 int interfaces[];
00229
00230 int fields_count;
00231
00232
00233
00234 field_info fields[];
00235
00236 int methods_count;
00237
00238
00239
00240 method_info methods[];
00241
00242 int attributes_count;
00243
00244
00245
00246 attribute_info attributes[];
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 ClassFile(String nfn) { fn = nfn; }
00436
00437
00438
00439
00440
00441
00442
00443
00444 static String access_string(int af,String separator) {
00445 boolean hasone = false;
00446 String s = "";
00447 if ((af & ACC_PUBLIC) != 0) {
00448 s = "public";
00449 hasone = true;
00450 }
00451 if ((af & ACC_PRIVATE) != 0) {
00452 if (hasone) s = s + separator;
00453 else hasone = true;
00454 s = s + "private";
00455 }
00456 if ((af & ACC_PROTECTED) != 0) {
00457 if (hasone) s = s + separator;
00458 else hasone = true;
00459 s = s + "protected";
00460 }
00461 if ((af & ACC_STATIC) != 0) {
00462 if (hasone) s = s + separator;
00463 else hasone = true;
00464 s = s + "static";
00465 }
00466 if ((af & ACC_FINAL) != 0) {
00467 if (hasone) s = s + separator;
00468 else hasone = true;
00469 s = s + "final";
00470 }
00471 if ((af & ACC_SUPER) != 0) {
00472 if (hasone) s = s + separator;
00473 else hasone = true;
00474 s = s + "super";
00475 }
00476 if ((af & ACC_VOLATILE) != 0) {
00477 if (hasone) s = s + separator;
00478 else hasone = true;
00479 s = s + "volatile";
00480 }
00481 if ((af & ACC_TRANSIENT) != 0) {
00482 if (hasone) s = s + separator;
00483 else hasone = true;
00484 s = s + "transient";
00485 }
00486 if ((af & ACC_INTERFACE) != 0) {
00487 if (hasone) s = s + separator;
00488 else hasone = true;
00489 s = s + "interface";
00490 }
00491 if ((af & ACC_ABSTRACT) != 0) {
00492 if (hasone) s = s + separator;
00493 else hasone = true;
00494 s = s + "abstract";
00495 }
00496 if ((af & ACC_UNKNOWN) != 0) {
00497 if (hasone) s = s + separator;
00498 else hasone = true;
00499 s = s + "unknown";
00500 }
00501 return s;
00502 }
00503
00504
00505
00506
00507
00508
00509 boolean descendsFrom(ClassFile cf) { return descendsFrom(cf.toString()); }
00510
00511
00512
00513
00514
00515
00516 boolean descendsFrom(String cname) {
00517 cp_info cf;
00518 int i;
00519 cf = constant_pool[super_class];
00520 if (cf.toString(constant_pool).compareTo(cname)==0) return true;
00521 for (i=0;i<interfaces_count;i++) {
00522 cf = constant_pool[interfaces[i]];
00523 if (cf.toString(constant_pool).compareTo(cname)==0) return true;
00524 }
00525 return false;
00526 }
00527
00528
00529
00530
00531 String fieldName(int i) {
00532 return fields[i].toName(constant_pool);
00533 }
00534
00535
00536
00537
00538
00539 method_info findMethod(String s) {
00540 method_info m;
00541 int i;
00542
00543 for (i=0;i<methods_count;i++) {
00544 m = methods[i];
00545 if (s.equals(m.toName(constant_pool))) {
00546 return m;
00547 }
00548 }
00549 return null;
00550 }
00551
00552
00553
00554 boolean isSterile() {
00555 if ((access_flags&ACC_PUBLIC)!=0 && (access_flags&ACC_FINAL)==0) return false;
00556 return true;
00557 }
00558
00559
00560
00561
00562
00563 void listConstantPool() {
00564 cp_info c;
00565 int i;
00566
00567
00568 for (i=1;i<constant_pool_count;i++) {
00569 c = constant_pool[i];
00570 System.out.println("[" + i + "] " + c.typeName() +
00571 "=" + c.toString(constant_pool));
00572 if ((constant_pool[i]).tag==cp_info.CONSTANT_Long ||
00573 (constant_pool[i]).tag==cp_info.CONSTANT_Double) {
00574
00575 i++;
00576 }
00577 }
00578 }
00579
00580
00581
00582
00583
00584
00585
00586 void listFields() {
00587 field_info fi;
00588 ConstantValue_attribute cva;
00589 CONSTANT_Utf8_info cm;
00590 int i,j;
00591
00592 for (i=0;i<fields_count;i++) {
00593 fi = fields[i];
00594 System.out.print(fi.prototype(constant_pool));
00595
00596 for (j=0;j<fi.attributes_count;j++) {
00597 cm = (CONSTANT_Utf8_info)(constant_pool[fi.attributes[j].attribute_name]);
00598 if (cm.convert().compareTo(attribute_info.ConstantValue)==0) {
00599 cva = (ConstantValue_attribute)(fi.attributes[j]);
00600
00601 System.out.print(" = " +
00602 constant_pool[cva.constantvalue_index].
00603 toString(constant_pool));
00604 break;
00605 }
00606 }
00607 System.out.println(";");
00608 }
00609 }
00610
00611
00612
00613
00614
00615 void listMethods() {
00616 int i;
00617
00618 for (i=0;i<methods_count;i++) {
00619 System.out.println(methods[i].prototype(constant_pool));
00620 }
00621 }
00622
00623
00624
00625
00626
00627 boolean loadClassFile() {
00628 InputStream f;
00629 DataInputStream d;
00630 boolean b;
00631
00632 try
00633 { if(Main.jimpleClassPath != null)
00634 { f = ClassLocator.getInputStreamOf(Main.jimpleClassPath, fn);
00635 }
00636 else
00637 { f = ClassLocator.getInputStreamOf(fn);
00638 }
00639
00640 }
00641 catch(ClassNotFoundException e)
00642 { throw new RuntimeException("Could not locate class " + fn);
00643 }
00644
00645 d = new DataInputStream(f);
00646 b = readClass(d);
00647
00648 try {
00649 d.close();
00650 f.close();
00651 } catch(IOException e) {
00652 System.out.println("IOException with " + fn + ": " + e.getMessage());
00653 return false;
00654 }
00655
00656 if (!b) return false;
00657 parse();
00658
00659 return true;
00660 }
00661
00662
00663
00664
00665
00666 void moveMethod(String m,int pos) {
00667 int i,j;
00668 method_info mthd;
00669 System.out.println("Moving " + m + " to position " + pos +
00670 " of " + methods_count);
00671
00672 for (i=0;i<methods_count;i++) {
00673 if (m.compareTo(methods[i].toName(constant_pool))==0) {
00674 mthd = methods[i];
00675 if (i>pos) {
00676 for (j=i;j>pos && j>0;j--)
00677 methods[j] = methods[j-1];
00678 methods[pos] = mthd;
00679 } else if (i<pos) {
00680 for (j=i;j<pos && j<methods_count-1;j++)
00681 methods[j] = methods[j+1];
00682 methods[pos] = mthd;
00683 }
00684 return;
00685 }
00686 }
00687 }
00688
00689
00690
00691
00692
00693 void parse() {
00694 method_info mi;
00695 int i;
00696
00697 for (i=0;i<methods_count;i++) {
00698 mi = methods[i];
00699 mi.instructions = parseMethod(mi);
00700
00701
00702 }
00703 }
00704
00705
00706
00707
00708
00709
00710
00711 static String parseDesc(String desc,String sep) {
00712 String params = "",param;
00713 char c;
00714 int i,len,arraylevel=0;
00715 boolean didone = false;
00716
00717 len = desc.length();
00718 for (i=0;i<len;i++) {
00719 c = desc.charAt(i);
00720 if (c==DESC_BYTE.charAt(0)) {
00721 param = "byte";
00722 } else if (c==DESC_CHAR.charAt(0)) {
00723 param = "char";
00724 } else if (c==DESC_DOUBLE.charAt(0)) {
00725 param = "double";
00726 } else if (c==DESC_FLOAT.charAt(0)) {
00727 param = "float";
00728 } else if (c==DESC_INT.charAt(0)) {
00729 param = "int";
00730 } else if (c==DESC_LONG.charAt(0)) {
00731 param = "long";
00732 } else if (c==DESC_SHORT.charAt(0)) {
00733 param = "short";
00734 } else if (c==DESC_BOOLEAN.charAt(0)) {
00735 param = "boolean";
00736 } else if (c==DESC_VOID.charAt(0)) {
00737 param = "void";
00738 } else if (c==DESC_ARRAY.charAt(0)) {
00739 arraylevel++;
00740 continue;
00741 } else if (c==DESC_OBJECT.charAt(0)) {
00742 int j;
00743 j = desc.indexOf(';',i+1);
00744 if (j<0) {
00745 System.out.println("Warning: Parse error -- can't find a ; in " +
00746 desc.substring(i+1));
00747 param = "<error>";
00748 } else {
00749 if (j-i>10 && desc.substring(i+1,i+11).compareTo("java/lang/")==0)
00750 i = i+10;
00751 param = desc.substring(i+1,j);
00752
00753 param = param.replace('/','.');
00754 i = j;
00755 }
00756 } else {
00757 param = "???";
00758 }
00759 if (didone) params = params + sep;
00760 params = params + param;
00761 while (arraylevel>0) {
00762 params = params + "[]";
00763 arraylevel--;
00764 }
00765 didone = true;
00766 }
00767 return params;
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777 Instruction parseMethod(method_info m) {
00778
00779 int j;
00780 Code_attribute ca;
00781 ByteCode bc;
00782 Instruction inst,head,tail;
00783 exception_table_entry e;
00784
00785 head = null;
00786 tail = null;
00787 bc = new ByteCode();
00788
00789 ca = m.locate_code_attribute();
00790 if (ca==null) return null;
00791
00792 j = 0;
00793 while(j<ca.code_length) {
00794 inst = bc.disassemble_bytecode(ca.code,j);
00795 inst.originalIndex = j;
00796
00797
00798
00799 if (inst instanceof Instruction_Unknown) {
00800 System.out.println("Unknown instruction in \"" + m.toName(constant_pool) +
00801 "\" at offset " + j);
00802 System.out.println(" bytecode = " + (((int)(inst.code))&0xff));
00803 }
00804
00805 j = inst.nextOffset(j);
00806
00807
00808 if (head==null) head = inst;
00809 else tail.next = inst;
00810 tail = inst;
00811 }
00812
00813
00814 bc.build(head);
00815
00816
00817 for (j=0;j<ca.exception_table_length;j++) {
00818 e = ca.exception_table[j];
00819 e.start_inst = bc.locateInst(e.start_pc);
00820 if (e.end_pc == ca.code_length)
00821 e.end_inst = null;
00822 else
00823 e.end_inst = bc.locateInst(e.end_pc);
00824 e.handler_inst = bc.locateInst(e.handler_pc);
00825 if (e.handler_inst!=null)
00826 e.handler_inst.labelled = true;
00827 }
00828
00829 return head;
00830 }
00831
00832
00833
00834
00835
00836
00837 static String parseMethodDesc_params(String s) {
00838 int i,j;
00839 i = s.indexOf('(');
00840 if (i>=0) {
00841 j = s.indexOf(')',i+1);
00842 if (j>=0) {
00843 return parseDesc(s.substring(i+1,j),",");
00844 }
00845 }
00846 return "<parse error>";
00847 }
00848
00849
00850
00851
00852
00853
00854 static String parseMethodDesc_return(String s) {
00855 int j;
00856 j = s.lastIndexOf(')');
00857 if (j>=0) {
00858 return parseDesc(s.substring(j+1),",");
00859 }
00860 return parseDesc(s,",");
00861 }
00862
00863
00864
00865
00866
00867
00868
00869 protected boolean readAttributes(DataInputStream d,int attributes_count,
00870 attribute_info[] ai) throws IOException {
00871 attribute_info a=null;
00872 int i;
00873 int j;
00874 long len;
00875 String s;
00876
00877 for (i=0;i<attributes_count;i++) {
00878 j = d.readUnsignedShort();
00879 len = d.readInt() & 0xFFFFFFFFL;
00880 s = ((CONSTANT_Utf8_info)(constant_pool[j])).convert();
00881
00882 if (s.compareTo(attribute_info.SourceFile)==0) {
00883 SourceFile_attribute sa = new SourceFile_attribute();
00884 sa.sourcefile_index = d.readUnsignedShort();
00885 a = (attribute_info)sa;
00886 } else if(s.compareTo(attribute_info.ConstantValue)==0) {
00887 ConstantValue_attribute ca = new ConstantValue_attribute();
00888 ca.constantvalue_index = d.readUnsignedShort();
00889 a = (attribute_info)ca;
00890 } else if(s.compareTo(attribute_info.Code)==0) {
00891 Code_attribute ca = new Code_attribute();
00892 ca.max_stack = d.readUnsignedShort();
00893 ca.max_locals = d.readUnsignedShort();
00894 ca.code_length = d.readInt() & 0xFFFFFFFFL;
00895 ca.code = new byte[(int) ca.code_length];
00896 d.read(ca.code);
00897 ca.exception_table_length = d.readUnsignedShort();
00898 ca.exception_table = new exception_table_entry[ca.exception_table_length];
00899 int k;
00900 exception_table_entry e;
00901 for (k=0; k<ca.exception_table_length; k++) {
00902 e = new exception_table_entry();
00903 e.start_pc = d.readUnsignedShort();
00904 e.end_pc = d.readUnsignedShort();
00905 e.handler_pc = d.readUnsignedShort();
00906 e.catch_type = d.readUnsignedShort();
00907 ca.exception_table[k] = e;
00908 }
00909 ca.attributes_count = d.readUnsignedShort();
00910 ca.attributes = new attribute_info[ca.attributes_count];
00911 readAttributes(d,ca.attributes_count,ca.attributes);
00912 a = (attribute_info)ca;
00913 } else if(s.compareTo(attribute_info.Exceptions)==0) {
00914 Exception_attribute ea = new Exception_attribute();
00915 ea.number_of_exceptions = d.readUnsignedShort();
00916 if (ea.number_of_exceptions>0) {
00917 int k;
00918 ea.exception_index_table = new int[ea.number_of_exceptions];
00919 for (k=0; k<ea.number_of_exceptions; k++)
00920 ea.exception_index_table[k] = d.readUnsignedShort();
00921 }
00922 a = (attribute_info)ea;
00923 } else if(s.compareTo(attribute_info.LineNumberTable)==0) {
00924 LineNumberTable_attribute la = new LineNumberTable_attribute();
00925 la.line_number_table_length = d.readUnsignedShort();
00926 int k;
00927 line_number_table_entry e;
00928 la.line_number_table = new
00929 line_number_table_entry[la.line_number_table_length];
00930 for (k=0; k<la.line_number_table_length; k++) {
00931 e = new line_number_table_entry();
00932 e.start_pc = d.readUnsignedShort();
00933 e.line_number = d.readUnsignedShort();
00934 la.line_number_table[k] = e;
00935 }
00936 a = (attribute_info)la;
00937 } else if(s.compareTo(attribute_info.LocalVariableTable)==0) {
00938 LocalVariableTable_attribute la = new LocalVariableTable_attribute();
00939 la.local_variable_table_length = d.readUnsignedShort();
00940 int k;
00941 local_variable_table_entry e;
00942 la.local_variable_table =
00943 new local_variable_table_entry[la.local_variable_table_length];
00944 for (k=0; k<la.local_variable_table_length; k++) {
00945 e = new local_variable_table_entry();
00946 e.start_pc = d.readUnsignedShort();
00947 e.length = d.readUnsignedShort();
00948 e.name_index = d.readUnsignedShort();
00949 e.descriptor_index = d.readUnsignedShort();
00950 e.index = d.readUnsignedShort();
00951 la.local_variable_table[k] = e;
00952 }
00953 a = (attribute_info)la;
00954 } else {
00955
00956
00957 Generic_attribute ga = new Generic_attribute();
00958 if (len>0) {
00959 ga.info = new byte[(int) len];
00960 d.read(ga.info);
00961 }
00962 a = (attribute_info)ga;
00963 }
00964 a.attribute_name = j;
00965 a.attribute_length = len;
00966 ai[i] = a;
00967 }
00968 return true;
00969 }
00970
00971
00972
00973
00974
00975 public boolean readClass(DataInputStream d) {
00976 try {
00977
00978 magic = d.readInt() & 0xFFFFFFFFL;
00979 if (magic != MAGIC) {
00980 System.out.println("Wrong magic number in " + fn + ": " + magic);
00981 return false;
00982 }
00983
00984 minor_version = d.readUnsignedShort();
00985 major_version = d.readUnsignedShort();
00986
00987 constant_pool_count = d.readUnsignedShort();
00988
00989
00990 if (!readConstantPool(d))
00991 return false;
00992
00993 access_flags = d.readUnsignedShort();
00994
00995
00996
00997
00998 this_class = d.readUnsignedShort();
00999 super_class = d.readUnsignedShort();
01000 interfaces_count = d.readUnsignedShort();
01001 if (interfaces_count>0) {
01002 interfaces = new int[interfaces_count];
01003 int j;
01004 for (j=0; j<interfaces_count; j++)
01005 interfaces[j] = d.readUnsignedShort();
01006 }
01007
01008
01009 fields_count = d.readUnsignedShort();
01010
01011 readFields(d);
01012
01013 methods_count = d.readUnsignedShort();
01014
01015 readMethods(d);
01016
01017 attributes_count = d.readUnsignedShort();
01018
01019 if (attributes_count>0) {
01020 attributes = new attribute_info[attributes_count];
01021 readAttributes(d,attributes_count,attributes);
01022 }
01023 } catch(IOException e) {
01024 throw new RuntimeException("IOException with " + fn + ": " + e.getMessage());
01025 }
01026
01027
01028
01029
01030
01031 return true;
01032 }
01033
01034
01035
01036
01037
01038 protected boolean readConstantPool(DataInputStream d) throws IOException {
01039 byte tag;
01040 cp_info cp;
01041 int i;
01042 boolean skipone;
01043
01044 constant_pool = new cp_info[constant_pool_count];
01045
01046 skipone = false;
01047
01048 for (i=1;i<constant_pool_count;i++) {
01049 if (skipone) {
01050 skipone = false;
01051 continue;
01052 }
01053 tag = (byte)d.readUnsignedByte();
01054 switch(tag) {
01055 case cp_info.CONSTANT_Class:
01056 cp = new CONSTANT_Class_info();
01057 ((CONSTANT_Class_info)cp).name_index = d.readUnsignedShort();
01058 if (debug) System.out.println("Constant pool[" + i + "]: Class");
01059 break;
01060 case cp_info.CONSTANT_Fieldref:
01061 cp = new CONSTANT_Fieldref_info();
01062 ((CONSTANT_Fieldref_info)cp).class_index = d.readUnsignedShort();
01063 ((CONSTANT_Fieldref_info)cp).name_and_type_index =
01064 d.readUnsignedShort();
01065 if (debug) System.out.println("Constant pool[" + i + "]: Fieldref");
01066 break;
01067 case cp_info.CONSTANT_Methodref:
01068 cp = new CONSTANT_Methodref_info();
01069 ((CONSTANT_Methodref_info)cp).class_index = d.readUnsignedShort();
01070 ((CONSTANT_Methodref_info)cp).name_and_type_index =
01071 d.readUnsignedShort();
01072 if (debug) System.out.println("Constant pool[" + i + "]: Methodref");
01073 break;
01074 case cp_info.CONSTANT_InterfaceMethodref:
01075 cp = new CONSTANT_InterfaceMethodref_info();
01076 ((CONSTANT_InterfaceMethodref_info)cp).class_index =
01077 d.readUnsignedShort();
01078 ((CONSTANT_InterfaceMethodref_info)cp).name_and_type_index =
01079 d.readUnsignedShort();
01080 if (debug)
01081 System.out.println("Constant pool[" + i + "]: InterfaceMethodref");
01082 break;
01083 case cp_info.CONSTANT_String:
01084 cp = new CONSTANT_String_info();
01085 ((CONSTANT_String_info)cp).string_index =
01086 d.readUnsignedShort();
01087 if (debug) System.out.println("Constant pool[" + i + "]: String");
01088 break;
01089 case cp_info.CONSTANT_Integer:
01090 cp = new CONSTANT_Integer_info();
01091 ((CONSTANT_Integer_info)cp).bytes = d.readInt();
01092 if (debug) System.out.println("Constant pool[" + i + "]: Integer = " +
01093 ((CONSTANT_Integer_info)cp).bytes);
01094 break;
01095 case cp_info.CONSTANT_Float:
01096 cp = new CONSTANT_Float_info();
01097 ((CONSTANT_Float_info)cp).bytes = d.readInt();
01098 if (debug) System.out.println("Constant pool[" + i + "]: Float = " +
01099 ((CONSTANT_Float_info)cp).convert());
01100 break;
01101 case cp_info.CONSTANT_Long:
01102 cp = new CONSTANT_Long_info();
01103 ((CONSTANT_Long_info)cp).high = d.readInt() & 0xFFFFFFFFL;
01104 ((CONSTANT_Long_info)cp).low = d.readInt() & 0xFFFFFFFFL;
01105
01106 if (debug) {
01107 String temp = cp.toString(constant_pool);
01108 System.out.println("Constant pool[" + i + "]: Long = " + temp);
01109
01110
01111
01112
01113 }
01114 skipone = true;
01115 break;
01116 case cp_info.CONSTANT_Double:
01117 cp = new CONSTANT_Double_info();
01118 ((CONSTANT_Double_info)cp).high = d.readInt() & 0xFFFFFFFFL;
01119 ((CONSTANT_Double_info)cp).low = d.readInt() & 0xFFFFFFFFL;
01120 if (debug) System.out.println("Constant pool[" + i + "]: Double = " +
01121 ((CONSTANT_Double_info)cp).convert());
01122 skipone = true;
01123 break;
01124 case cp_info.CONSTANT_NameAndType:
01125 cp = new CONSTANT_NameAndType_info();
01126 ((CONSTANT_NameAndType_info)cp).name_index =
01127 d.readUnsignedShort();
01128 ((CONSTANT_NameAndType_info)cp).descriptor_index =
01129 d.readUnsignedShort();
01130 if (debug) System.out.println("Constant pool[" + i + "]: Name and Type");
01131 break;
01132 case cp_info.CONSTANT_Utf8:
01133 int len;
01134 CONSTANT_Utf8_info cputf8 = new CONSTANT_Utf8_info();
01135 len = d.readUnsignedShort();
01136 cputf8.bytes = new byte[len+2];
01137 cputf8.bytes[0] = (byte)(len>>8);
01138 cputf8.bytes[1] = (byte)(len & 0xff);
01139 if (len>0) {
01140 int j;
01141 for (j=0; j<len;j++)
01142 cputf8.bytes[j+2] = (byte)d.readUnsignedByte();
01143 }
01144 cp = (cp_info)cputf8;
01145 if (debug)
01146 System.out.println("Constant pool[" + i + "]: Utf8 = \"" +
01147 cputf8.convert() + "\"");
01148 break;
01149 default:
01150 System.out.println("Unknown tag in constant pool: " +
01151 tag + " at entry " + i);
01152 return false;
01153 }
01154 cp.tag = tag;
01155 constant_pool[i] = cp;
01156 }
01157 return true;
01158 }
01159
01160
01161
01162
01163
01164 protected boolean readFields(DataInputStream d) throws IOException {
01165 field_info fi;
01166 int i;
01167
01168 fields = new field_info[fields_count];
01169
01170 for (i=0;i<fields_count;i++) {
01171 fi = new field_info();
01172 fi.access_flags = d.readUnsignedShort();
01173 fi.name_index = d.readUnsignedShort();
01174 fi.descriptor_index = d.readUnsignedShort();
01175 fi.attributes_count = d.readUnsignedShort();
01176 if (fi.attributes_count>0) {
01177 fi.attributes = new attribute_info[fi.attributes_count];
01178 readAttributes(d,fi.attributes_count,fi.attributes);
01179 }
01180
01181
01182
01183 fields[i] = fi;
01184 }
01185
01186 return true;
01187 }
01188
01189
01190
01191
01192
01193 protected boolean readMethods(DataInputStream d) throws IOException {
01194 method_info mi;
01195 int i;
01196
01197 methods = new method_info[methods_count];
01198
01199 for (i=0;i<methods_count;i++) {
01200 mi = new method_info();
01201 mi.access_flags = d.readUnsignedShort();
01202 mi.name_index = d.readUnsignedShort();
01203 mi.descriptor_index = d.readUnsignedShort();
01204 mi.attributes_count = d.readUnsignedShort();
01205
01206
01207
01208
01209
01210
01211 if (mi.attributes_count>0) {
01212 mi.attributes = new attribute_info[mi.attributes_count];
01213 readAttributes(d,mi.attributes_count,mi.attributes);
01214 }
01215
01216
01217
01218
01219
01220 methods[i] = mi;
01221 }
01222
01223 return true;
01224 }
01225
01226
01227
01228
01229
01230
01231 int relabel(Instruction i) {
01232 int index = 0;
01233 while (i!=null) {
01234 i.label = index;
01235 index = i.nextOffset(index);
01236 i = i.next;
01237 }
01238 return index;
01239 }
01240
01241
01242
01243
01244 boolean sameClass(String cfn) {
01245 String s = cfn;
01246 int i = s.lastIndexOf(".class");
01247 if (i>0) {
01248 s = s.substring(0,i);
01249 }
01250 if (s.compareTo(toString())==0)
01251 return true;
01252 return false;
01253 }
01254
01255
01256
01257
01258
01259 boolean saveClassFile() {
01260 FileOutputStream f;
01261 DataOutputStream d;
01262 boolean b;
01263 try {
01264 f = new FileOutputStream(fn);
01265 } catch(FileNotFoundException e) {
01266 if (fn.indexOf(".class")>=0) {
01267 System.out.println("Can't find " + fn);
01268 return false;
01269 }
01270 fn = fn + ".class";
01271 try {
01272 f = new FileOutputStream(fn);
01273 } catch(FileNotFoundException ee) {
01274 System.out.println("Can't find " + fn);
01275 return false;
01276 } catch(IOException ee) {
01277 System.out.println("IOException with " + fn + ": " + ee.getMessage());
01278 return false;
01279 }
01280 } catch(IOException e) {
01281 System.out.println("IOException with " + fn + ": " + e.getMessage());
01282 return false;
01283 }
01284 d = new DataOutputStream(f);
01285 if (d==null) {
01286 try {
01287 f.close();
01288 } catch(IOException e) { }
01289 return false;
01290 }
01291 b = writeClass(d);
01292 try {
01293 d.close();
01294 f.close();
01295 } catch(IOException e) {
01296 System.out.println("IOException with " + fn + ": " + e.getMessage());
01297 return false;
01298 }
01299 return b;
01300 }
01301
01302 public String toString() {
01303 return (constant_pool[this_class].toString(constant_pool));
01304 }
01305
01306
01307
01308
01309
01310 void unparse() {
01311 int i,j;
01312 Code_attribute ca;
01313 byte bc[];
01314 method_info mi;
01315 exception_table_entry e;
01316
01317 for (i=0;i<methods_count;i++) {
01318 mi = methods[i];
01319
01320 ca = mi.locate_code_attribute();
01321 if (ca==null) continue;
01322 bc = unparseMethod(mi);
01323 if (bc==null) {
01324 System.out.println("Recompile of " + mi.toName(constant_pool) + " failed!");
01325 } else {
01326 ca.code_length = bc.length;
01327 ca.code = bc;
01328
01329 for (j=0;j<ca.exception_table_length;j++) {
01330 e = ca.exception_table[j];
01331 e.start_pc = (e.start_inst.label);
01332 if (e.end_inst!=null)
01333 e.end_pc = (e.end_inst.label);
01334 else
01335 e.end_pc = (int) (ca.code_length);
01336 e.handler_pc = (e.handler_inst.label);
01337 }
01338 }
01339 }
01340 }
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351 byte[] unparseMethod(method_info m) {
01352 int codesize;
01353 byte bc[];
01354 Instruction i;
01355
01356
01357 m.cfg.reconstructInstructions();
01358
01359
01360 codesize = relabel(m.instructions);
01361
01362
01363 bc = new byte[codesize];
01364 if (bc==null) {
01365 System.out.println("Warning: can't allocate memory for recompile");
01366 return null;
01367 }
01368
01369
01370 i = m.instructions;
01371 codesize = 0;
01372 while (i!=null) {
01373 codesize = i.compile(bc,codesize);
01374 i = i.next;
01375 }
01376 if (codesize != bc.length)
01377 System.out.println("Warning: code size doesn't match array length!");
01378
01379 return bc;
01380 }
01381
01382
01383
01384
01385
01386
01387
01388 protected boolean writeAttributes(DataOutputStream dd, int attributes_count,
01389 attribute_info[] ai) throws IOException {
01390 attribute_info a=null;
01391 int i,len;
01392 short j;
01393 String s;
01394
01395 for (i=0;i<attributes_count;i++) {
01396 a = ai[i];
01397 dd.writeShort(a.attribute_name);
01398 dd.writeInt((int) a.attribute_length);
01399 if (a instanceof SourceFile_attribute) {
01400 SourceFile_attribute sa = (SourceFile_attribute)a;
01401 dd.writeShort(sa.sourcefile_index);
01402 } else if(a instanceof ConstantValue_attribute) {
01403 ConstantValue_attribute ca = (ConstantValue_attribute)a;
01404 dd.writeShort(ca.constantvalue_index);
01405 } else if(a instanceof Code_attribute) {
01406 Code_attribute ca = (Code_attribute)a;
01407 dd.writeShort(ca.max_stack);
01408 dd.writeShort(ca.max_locals);
01409 dd.writeInt((int) ca.code_length);
01410 dd.write(ca.code,0, (int) ca.code_length);
01411 dd.writeShort(ca.exception_table_length);
01412 int k;
01413 exception_table_entry e;
01414 for (k=0; k<ca.exception_table_length; k++) {
01415 e = ca.exception_table[k];
01416 dd.writeShort(e.start_pc);
01417 dd.writeShort(e.end_pc);
01418 dd.writeShort(e.handler_pc);
01419 dd.writeShort(e.catch_type);
01420 }
01421 dd.writeShort(ca.attributes_count);
01422 if (ca.attributes_count>0)
01423 writeAttributes(dd,ca.attributes_count,ca.attributes);
01424 } else if(a instanceof Exception_attribute) {
01425 Exception_attribute ea = (Exception_attribute)a;
01426 dd.writeShort(ea.number_of_exceptions);
01427 if (ea.number_of_exceptions>0) {
01428 int k;
01429 for (k=0; k<ea.number_of_exceptions; k++)
01430 dd.writeShort(ea.exception_index_table[k]);
01431 }
01432 } else if(a instanceof LineNumberTable_attribute) {
01433 LineNumberTable_attribute la = (LineNumberTable_attribute)a;
01434 dd.writeShort(la.line_number_table_length);
01435 int k;
01436 line_number_table_entry e;
01437 for (k=0; k<la.line_number_table_length; k++) {
01438 e = la.line_number_table[k];
01439 dd.writeShort(e.start_pc);
01440 dd.writeShort(e.line_number);
01441 }
01442 } else if(a instanceof LocalVariableTable_attribute) {
01443 LocalVariableTable_attribute la = (LocalVariableTable_attribute)a;
01444 dd.writeShort(la.local_variable_table_length);
01445 int k;
01446 local_variable_table_entry e;
01447 for (k=0; k<la.local_variable_table_length; k++) {
01448 e = la.local_variable_table[k];
01449 dd.writeShort(e.start_pc);
01450 dd.writeShort(e.length);
01451 dd.writeShort(e.name_index);
01452 dd.writeShort(e.descriptor_index);
01453 dd.writeShort(e.index);
01454 }
01455 } else {
01456
01457 System.out.println("Generic/Unknown Attribute in output");
01458 Generic_attribute ga = (Generic_attribute)a;
01459 if (ga.attribute_length>0) {
01460 dd.write(ga.info,0,(int) ga.attribute_length);
01461 }
01462 }
01463 }
01464 return true;
01465 }
01466
01467
01468
01469
01470 boolean writeClass(DataOutputStream dd) {
01471
01472 try {
01473
01474 dd.writeInt((int) magic);
01475
01476 dd.writeShort(minor_version);
01477 dd.writeShort(major_version);
01478 dd.writeShort(constant_pool_count);
01479
01480 if (!writeConstantPool(dd))
01481 return false;
01482
01483 dd.writeShort(access_flags);
01484 dd.writeShort(this_class);
01485 dd.writeShort(super_class);
01486 dd.writeShort(interfaces_count);
01487 if (interfaces_count>0) {
01488 int j;
01489 for (j=0; j<interfaces_count; j++)
01490 dd.writeShort(interfaces[j]);
01491 }
01492
01493 dd.writeShort(fields_count);
01494 writeFields(dd);
01495
01496 dd.writeShort(methods_count);
01497 writeMethods(dd);
01498
01499 dd.writeShort(attributes_count);
01500 if (attributes_count>0) {
01501 writeAttributes(dd,attributes_count,attributes);
01502 }
01503 } catch(IOException e) {
01504 System.out.println("IOException with " + fn + ": " + e.getMessage());
01505 return false;
01506 }
01507 return true;
01508 }
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528 protected boolean writeConstantPool(DataOutputStream dd) throws IOException {
01529 byte tag;
01530 cp_info cp;
01531 int i;
01532 boolean skipone = false;
01533
01534 for (i=1;i<constant_pool_count;i++) {
01535 if (skipone) {
01536 skipone = false;
01537 continue;
01538 }
01539 cp = constant_pool[i];
01540 dd.writeByte(cp.tag);
01541 switch(cp.tag) {
01542 case cp_info.CONSTANT_Class:
01543 dd.writeShort(((CONSTANT_Class_info)cp).name_index);
01544 break;
01545 case cp_info.CONSTANT_Fieldref:
01546 dd.writeShort(((CONSTANT_Fieldref_info)cp).class_index);
01547 dd.writeShort(((CONSTANT_Fieldref_info)cp).name_and_type_index);
01548 break;
01549 case cp_info.CONSTANT_Methodref:
01550 dd.writeShort(((CONSTANT_Methodref_info)cp).class_index);
01551 dd.writeShort(((CONSTANT_Methodref_info)cp).name_and_type_index);
01552 break;
01553 case cp_info.CONSTANT_InterfaceMethodref:
01554 dd.writeShort(((CONSTANT_InterfaceMethodref_info)cp).class_index);
01555 dd.writeShort(((CONSTANT_InterfaceMethodref_info)cp).name_and_type_index);
01556 break;
01557 case cp_info.CONSTANT_String:
01558 dd.writeShort(((CONSTANT_String_info)cp).string_index);
01559 break;
01560 case cp_info.CONSTANT_Integer:
01561 dd.writeInt((int) ((CONSTANT_Integer_info)cp).bytes);
01562 break;
01563 case cp_info.CONSTANT_Float:
01564 dd.writeInt((int) ((CONSTANT_Float_info)cp).bytes);
01565 break;
01566 case cp_info.CONSTANT_Long:
01567 dd.writeInt((int) ((CONSTANT_Long_info)cp).high);
01568 dd.writeInt((int) ((CONSTANT_Long_info)cp).low);
01569 skipone = true;
01570 break;
01571 case cp_info.CONSTANT_Double:
01572 dd.writeInt((int) ((CONSTANT_Double_info)cp).high);
01573 dd.writeInt((int) ((CONSTANT_Double_info)cp).low);
01574 skipone = true;
01575 break;
01576 case cp_info.CONSTANT_NameAndType:
01577 dd.writeShort(((CONSTANT_NameAndType_info)cp).name_index);
01578 dd.writeShort(((CONSTANT_NameAndType_info)cp).descriptor_index);
01579 break;
01580 case cp_info.CONSTANT_Utf8:
01581 int len;
01582 len = ((CONSTANT_Utf8_info)cp).bytes.length;
01583 dd.writeShort(len-2);
01584 dd.write(((CONSTANT_Utf8_info)cp).bytes,2,len-2);
01585 break;
01586 default:
01587 System.out.println("Unknown tag in constant pool: " + cp.tag);
01588 return false;
01589 }
01590 }
01591 return true;
01592 }
01593
01594
01595
01596
01597
01598 protected boolean writeFields(DataOutputStream dd) throws IOException {
01599 field_info fi;
01600 int i;
01601
01602 for (i=0;i<fields_count;i++) {
01603 fi = fields[i];
01604 dd.writeShort(fi.access_flags);
01605 dd.writeShort(fi.name_index);
01606 dd.writeShort(fi.descriptor_index);
01607 dd.writeShort(fi.attributes_count);
01608 if (fi.attributes_count>0) {
01609 writeAttributes(dd,fi.attributes_count,fi.attributes);
01610 }
01611 }
01612 return true;
01613 }
01614
01615
01616
01617
01618
01619 protected boolean writeMethods(DataOutputStream dd) throws IOException {
01620 method_info mi;
01621 int i;
01622
01623 for (i=0;i<methods_count;i++) {
01624 mi = methods[i];
01625 dd.writeShort(mi.access_flags);
01626 dd.writeShort(mi.name_index);
01627 dd.writeShort(mi.descriptor_index);
01628 dd.writeShort(mi.attributes_count);
01629 if (mi.attributes_count>0) {
01630 writeAttributes(dd,mi.attributes_count,mi.attributes);
01631 }
01632 }
01633 return true;
01634 }
01635 }