KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > coffi > Util


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 1997 Clark Verbrugge
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */

19
20 /*
21  * Modified by the Sable Research Group and others 1997-1999.
22  * See the 'credits' file distributed with Soot for the complete list of
23  * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
24  */

25
26
27
28
29
30
31
32 package soot.coffi;
33 import soot.options.*;
34 import soot.jimple.*;
35 import soot.util.*;
36 import java.util.*;
37 import java.io.*;
38 import soot.baf.*;
39 import soot.tagkit.*;
40 import soot.*;
41
42
43 public class Util
44 {
45     public Util( Singletons.Global g ) {}
46     public static Util v() { return G.v().soot_coffi_Util(); }
47
48
49     Map classNameToAbbreviation;
50     Set markedClasses;
51     LinkedList classesToResolve;
52
53     int activeOriginalIndex = -1;
54     cp_info[] activeConstantPool = null;
55     LocalVariableTable_attribute activeVariableTable;
56     LocalVariableTypeTable_attribute activeVariableTypeTable;
57     boolean useFaithfulNaming = false;
58     boolean isLocalStore = false; // global variable used
59
boolean isWideLocalStore = false;
60     public void setFaithfulNaming(boolean v)
61     {
62         useFaithfulNaming = v;
63     }
64
65     public void resolveFromClassFile(SootClass aClass, InputStream is, List references)
66     {
67         SootClass bclass = aClass;
68         String JavaDoc className = bclass.getName();
69         ClassFile coffiClass = new ClassFile(className);
70         
71         // Load up class file, and retrieve bclass from class manager.
72
{
73             boolean success = coffiClass.loadClassFile(is);
74
75             if(!success)
76                 {
77                     if(!Scene.v().allowsPhantomRefs())
78                         throw new RuntimeException JavaDoc("Could not load classfile: " + bclass.getName());
79                     else {
80                         G.v().out.println("Warning: " + className + " is a phantom class!");
81                         bclass.setPhantom(true);
82                         return;
83                     }
84                     
85                 }
86             
87             CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[coffiClass.this_class];
88     
89             String JavaDoc name = ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
90             name = name.replace('/', '.');
91                         
92             if( !name.equals( bclass.getName() ) ) {
93                 throw new RuntimeException JavaDoc(
94                         "Error: class "+name+" read in from a classfile in which "+bclass.getName()+" was expected." );
95             }
96         }
97       
98         // Set modifier
99
bclass.setModifiers(coffiClass.access_flags & (~0x0020));
100         // don't want the ACC_SUPER flag, it is always supposed to be set anyways
101

102         // Set superclass
103
{
104             if(coffiClass.super_class != 0)
105                 {
106                     // This object is not java.lang.Object, so must have a super class
107

108                     CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[coffiClass.super_class];
109     
110                     String JavaDoc superName = ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
111                     superName = superName.replace('/', '.');
112     
113                     references.add(superName);
114                     bclass.setSuperclass(SootResolver.v().makeClassRef(superName));
115                 }
116         }
117     
118         // Add interfaces to the bclass
119
{
120             for(int i = 0; i < coffiClass.interfaces_count; i++)
121                 {
122                     CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[coffiClass.interfaces[i]];
123     
124                     String JavaDoc interfaceName =
125                         ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
126     
127                     interfaceName = interfaceName.replace('/', '.');
128     
129                     references.add(interfaceName);
130                     SootClass interfaceClass = SootResolver.v().makeClassRef(interfaceName);
131                     bclass.addInterface(interfaceClass);
132                 }
133         }
134     
135         // Add every field to the bclass
136
for(int i = 0; i < coffiClass.fields_count; i++){
137             
138             field_info fieldInfo = coffiClass.fields[i];
139
140             String JavaDoc fieldName = ((CONSTANT_Utf8_info)
141                                 (coffiClass.constant_pool[fieldInfo.name_index])).convert();
142
143             String JavaDoc fieldDescriptor = ((CONSTANT_Utf8_info)
144                                       (coffiClass.constant_pool[fieldInfo.descriptor_index])).convert();
145
146             int modifiers = fieldInfo.access_flags;
147             Type fieldType = jimpleTypeOfFieldDescriptor(fieldDescriptor);
148                 
149             SootField field = new SootField(fieldName, fieldType, modifiers);
150             bclass.addField(field);
151                 
152             references.add(fieldType);
153
154             // add initialization constant, if any
155
for(int j = 0; j < fieldInfo.attributes_count; j++) {
156                 // add constant value attributes
157
if (fieldInfo.attributes[j] instanceof ConstantValue_attribute){
158                     
159                     ConstantValue_attribute attr = (ConstantValue_attribute) fieldInfo.attributes[j];
160                     cp_info cval = coffiClass.constant_pool[attr.constantvalue_index];
161                     ConstantValueTag tag;
162                     switch (cval.tag) {
163                     case cp_info.CONSTANT_Integer:
164                     tag = new IntegerConstantValueTag((int)((CONSTANT_Integer_info)cval).bytes);
165                     break;
166                     case cp_info.CONSTANT_Float:
167                     //tag = new FloatConstantValueTag((int)((CONSTANT_Float_info)cval).bytes);
168
tag = new FloatConstantValueTag(((CONSTANT_Float_info)cval).convert());
169                     break;
170                     case cp_info.CONSTANT_Long:
171                       {
172                     CONSTANT_Long_info lcval = (CONSTANT_Long_info)cval;
173                     tag = new LongConstantValueTag((lcval.high << 32) + lcval.low);
174                     break;
175                       }
176                     case cp_info.CONSTANT_Double:
177                       {
178                     CONSTANT_Double_info dcval = (CONSTANT_Double_info)cval;
179                     //tag = new DoubleConstantValueTag((dcval.high << 32) + dcval.low);
180
tag = new DoubleConstantValueTag(dcval.convert());
181                     break;
182                       }
183                     case cp_info.CONSTANT_String:
184                       {
185                     CONSTANT_String_info scval = (CONSTANT_String_info)cval;
186                     CONSTANT_Utf8_info ucval = (CONSTANT_Utf8_info)coffiClass.constant_pool[scval.string_index];
187                     tag = new StringConstantValueTag(ucval.convert());
188                     break;
189                       }
190                     default:
191                     throw new RuntimeException JavaDoc("unexpected ConstantValue: " + cval);
192                     }
193                     field.addTag(tag);
194                 }
195                 // add synthetic tag
196
else if (fieldInfo.attributes[j] instanceof Synthetic_attribute){
197                     field.addTag(new SyntheticTag());
198                 }
199                 // add deprecated tag
200
else if (fieldInfo.attributes[j] instanceof Deprecated_attribute){
201                     field.addTag(new DeprecatedTag());
202                 }
203                 // add signature tag
204
else if (fieldInfo.attributes[j] instanceof Signature_attribute){
205                     String JavaDoc generic_sig = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[((Signature_attribute)fieldInfo.attributes[j]).signature_index])).convert();
206                     field.addTag(new SignatureTag(generic_sig));
207                 }
208                 else if (fieldInfo.attributes[j] instanceof RuntimeVisibleAnnotations_attribute || fieldInfo.attributes[j] instanceof RuntimeInvisibleAnnotations_attribute)
209                 {
210                     addAnnotationVisibilityAttribute(field, fieldInfo.attributes[j], coffiClass, references);
211                 }
212             }
213         }
214     
215         // Add every method to the bclass
216
for(int i = 0; i < coffiClass.methods_count; i++){
217             
218             method_info methodInfo = coffiClass.methods[i];
219         
220         
221             if( (coffiClass.constant_pool[methodInfo.name_index]) == null) {
222                 G.v().out.println("method index: " + methodInfo.toName(coffiClass.constant_pool));
223                 throw new RuntimeException JavaDoc("method has no name");
224             }
225
226             String JavaDoc methodName = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[methodInfo.name_index])).convert();
227             String JavaDoc methodDescriptor = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[methodInfo.descriptor_index])).convert();
228     
229             List parameterTypes;
230             Type returnType;
231     
232             // Generate parameterTypes & returnType
233
{
234                 Type[] types = jimpleTypesOfFieldOrMethodDescriptor(methodDescriptor);
235     
236                 parameterTypes = new ArrayList();
237                 for(int j = 0; j < types.length - 1; j++){
238                     references.add(types[j]);
239                     parameterTypes.add(types[j]);
240                 }
241                         
242                 returnType = types[types.length - 1];
243                 references.add(returnType);
244             }
245     
246             int modifiers = methodInfo.access_flags;
247
248             SootMethod method;
249
250             method = new SootMethod(methodName,
251                                     parameterTypes, returnType, modifiers);
252             bclass.addMethod(method);
253
254             methodInfo.jmethod = method;
255
256             // add exceptions to method
257
{
258                 for(int j = 0; j < methodInfo.attributes_count; j++){
259                     if(methodInfo.attributes[j] instanceof Exception_attribute){
260                         Exception_attribute exceptions = (Exception_attribute) methodInfo.attributes[j];
261
262                         for(int k = 0; k < exceptions.number_of_exceptions; k++)
263 {
264                             CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.
265                             constant_pool[exceptions.exception_index_table[k]];
266
267                             String JavaDoc exceptionName = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[c.name_index])).convert();
268
269                             exceptionName = exceptionName.replace('/', '.');
270
271                             references.add(exceptionName);
272                             method.addExceptionIfAbsent(SootResolver.v().makeClassRef(exceptionName));
273                         }
274                     }
275                     else if (methodInfo.attributes[j] instanceof Synthetic_attribute) {
276                         method.addTag(new SyntheticTag());
277                     }
278                     else if (methodInfo.attributes[j] instanceof Deprecated_attribute) {
279                         method.addTag(new DeprecatedTag());
280                     }
281                     else if (methodInfo.attributes[j] instanceof Signature_attribute){
282                         String JavaDoc generic_sig = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[((Signature_attribute)methodInfo.attributes[j]).signature_index])).convert();
283                         method.addTag(new SignatureTag(generic_sig));
284                     }
285                     else if (methodInfo.attributes[j] instanceof RuntimeVisibleAnnotations_attribute || methodInfo.attributes[j] instanceof RuntimeInvisibleAnnotations_attribute)
286                     {
287                         addAnnotationVisibilityAttribute(method, methodInfo.attributes[j], coffiClass, references);
288                     }
289                     else if (methodInfo.attributes[j] instanceof RuntimeVisibleParameterAnnotations_attribute || methodInfo.attributes[j] instanceof RuntimeInvisibleParameterAnnotations_attribute)
290                     {
291                         addAnnotationVisibilityParameterAttribute(method, methodInfo.attributes[j], coffiClass, references);
292                     }
293                     else if (methodInfo.attributes[j] instanceof AnnotationDefault_attribute)
294                     {
295                         AnnotationDefault_attribute attr = (AnnotationDefault_attribute)methodInfo.attributes[j];
296                         element_value [] input = new element_value[1];
297                         input[0] = attr.default_value;
298                         ArrayList list = createElementTags(1, coffiClass, input);
299                         method.addTag(new AnnotationDefaultTag((AnnotationElem)list.get(0)));
300                     }
301                 }
302             }
303                     
304                 // Go through the constant pool, forcing all mentioned classes to be resolved.
305
{
306                     for(int k = 0; k < coffiClass.constant_pool_count; k++) {
307                         if(coffiClass.constant_pool[k] instanceof CONSTANT_Class_info)
308                             {
309                                 CONSTANT_Class_info c = (CONSTANT_Class_info) coffiClass.constant_pool[k];
310
311                                 String JavaDoc desc = ((CONSTANT_Utf8_info) (coffiClass.constant_pool[c.name_index])).convert();
312                                 String JavaDoc name = desc.replace('/', '.');
313
314                                 if(name.startsWith("["))
315                                     references.add(jimpleTypeOfFieldDescriptor(desc));
316                                 else
317                                     references.add(name);
318                             }
319                         if(coffiClass.constant_pool[k] instanceof CONSTANT_Fieldref_info
320                         || coffiClass.constant_pool[k] instanceof CONSTANT_Methodref_info
321                         || coffiClass.constant_pool[k] instanceof CONSTANT_InterfaceMethodref_info) {
322                             Type[] types = jimpleTypesOfFieldOrMethodDescriptor(
323                                 cp_info.getTypeDescr(coffiClass.constant_pool,k));
324                             for( int ii = 0; ii < types.length; ii++ ) {
325                                 references.add(types[ii]);
326                             }
327                         }
328
329                     }
330                 }
331             }
332
333         // Set coffi source of method
334
for(int i = 0; i < coffiClass.methods_count; i++)
335             {
336                 method_info methodInfo = coffiClass.methods[i];
337                 // methodInfo.jmethod.setSource(coffiClass, methodInfo);
338
methodInfo.jmethod.setSource(new CoffiMethodSource(coffiClass, methodInfo));
339             }
340         
341     // Set "SourceFile" attribute tag
342
for(int i = 0; i < coffiClass.attributes_count; i++){
343         
344         if(coffiClass.attributes[i] instanceof SourceFile_attribute){
345             
346             SourceFile_attribute attr = (SourceFile_attribute)coffiClass.attributes[i];
347             String JavaDoc sourceFile = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[attr.sourcefile_index])).convert();
348
349             if( sourceFile.indexOf(' ') >= 0 ) {
350                 G.v().out.println( "Warning: Class "+className+" has invalid SourceFile attribute (will be ignored)." );
351             } else {
352                 bclass.addTag(new SourceFileTag( sourceFile ) );
353             }
354     
355         }
356         // Set "InnerClass" attribute tag
357
else if(coffiClass.attributes[i] instanceof InnerClasses_attribute){
358            
359             InnerClasses_attribute attr = (InnerClasses_attribute)coffiClass.attributes[i];
360             for (int j = 0; j < attr.inner_classes_length; j++)
361                 {
362                     inner_class_entry e = attr.inner_classes[j];
363                 String JavaDoc inner = null;
364                 String JavaDoc outer = null;
365                 String JavaDoc name = null;
366                 int class_index;
367
368                 if (e.inner_class_index != 0)
369                     inner = ((CONSTANT_Utf8_info)coffiClass.constant_pool[((CONSTANT_Class_info)coffiClass.constant_pool[e.inner_class_index]).name_index]).convert();
370                 if (e.outer_class_index != 0)
371                     outer = ((CONSTANT_Utf8_info)coffiClass.constant_pool[((CONSTANT_Class_info)coffiClass.constant_pool[e.outer_class_index]).name_index]).convert();
372                 if (e.name_index != 0)
373                     name = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[e.name_index])).convert();
374                 bclass.addTag(new InnerClassTag(inner, outer, name, e.access_flags));
375             }
376         }
377         // set synthetic tags
378
else if(coffiClass.attributes[i] instanceof Synthetic_attribute){
379             
380             Synthetic_attribute attr = (Synthetic_attribute)coffiClass.attributes[i];
381             bclass.addTag(new SyntheticTag());
382         }
383         // set deprectaed tags
384
else if(coffiClass.attributes[i] instanceof Deprecated_attribute){
385             
386             Deprecated_attribute attr = (Deprecated_attribute)coffiClass.attributes[i];
387             bclass.addTag(new DeprecatedTag());
388         }
389         else if (coffiClass.attributes[i] instanceof Signature_attribute){
390             String JavaDoc generic_sig = ((CONSTANT_Utf8_info)(coffiClass.constant_pool[((Signature_attribute)coffiClass.attributes[i]).signature_index])).convert();
391             bclass.addTag(new SignatureTag(generic_sig));
392         }
393         else if (coffiClass.attributes[i] instanceof EnclosingMethod_attribute){
394             EnclosingMethod_attribute attr = (EnclosingMethod_attribute)coffiClass.attributes[i];
395             String JavaDoc class_name = ((CONSTANT_Utf8_info)coffiClass.constant_pool[((CONSTANT_Class_info)coffiClass.constant_pool[ attr.class_index ]).name_index]).convert();
396             CONSTANT_NameAndType_info info = (CONSTANT_NameAndType_info)coffiClass.constant_pool[attr.method_index];
397
398             String JavaDoc method_name = "";
399             String JavaDoc method_sig = "";
400             
401             if (info != null){
402                 method_name = ((CONSTANT_Utf8_info)coffiClass.constant_pool[info.name_index]).convert();
403                 method_sig = ((CONSTANT_Utf8_info)coffiClass.constant_pool[info.descriptor_index]).convert();
404             }
405             bclass.addTag(new EnclosingMethodTag(class_name, method_name, method_sig));
406         }
407         else if (coffiClass.attributes[i] instanceof RuntimeVisibleAnnotations_attribute || coffiClass.attributes[i] instanceof RuntimeInvisibleAnnotations_attribute)
408         {
409             addAnnotationVisibilityAttribute(bclass, coffiClass.attributes[i], coffiClass, references);
410         }
411    
412     }
413     }
414
415
416
417     Type jimpleReturnTypeOfMethodDescriptor(String JavaDoc descriptor)
418     {
419         Type[] types = jimpleTypesOfFieldOrMethodDescriptor(descriptor);
420
421         return types[types.length - 1];
422     }
423
424     private ArrayList conversionTypes = new ArrayList();
425     
426     /*
427     private Map cache = new HashMap();
428     public Type[] jimpleTypesOfFieldOrMethodDescriptor(String descriptor)
429     {
430         Type[] ret = (Type[]) cache.get(descriptor);
431         if( ret != null ) return ret;
432         conversionTypes.clear();
433
434         while(descriptor.length() != 0)
435         {
436             boolean isArray = false;
437             int numDimensions = 0;
438             Type baseType;
439
440             // Skip parenthesis
441                 if(descriptor.startsWith("(") || descriptor.startsWith(")"))
442                 {
443                     descriptor = descriptor.substring(1);
444                     continue;
445                 }
446
447             // Handle array case
448                 while(descriptor.startsWith("["))
449                 {
450                     isArray = true;
451                     numDimensions++;
452                     descriptor = descriptor.substring(1);
453                 }
454
455             // Determine base type
456                 if(descriptor.startsWith("B"))
457                 {
458                     baseType = ByteType.v();
459                     descriptor = descriptor.substring(1);
460                 }
461                 else if(descriptor.startsWith("C"))
462                 {
463                     baseType = CharType.v();
464                     descriptor = descriptor.substring(1);
465                 }
466                 else if(descriptor.startsWith("D"))
467                 {
468                     baseType = DoubleType.v();
469                     descriptor = descriptor.substring(1);
470                 }
471                 else if(descriptor.startsWith("F"))
472                 {
473                     baseType = FloatType.v();
474                     descriptor = descriptor.substring(1);
475                 }
476                 else if(descriptor.startsWith("I"))
477                 {
478                     baseType = IntType.v();
479                     descriptor = descriptor.substring(1);
480                 }
481                 else if(descriptor.startsWith("J"))
482                 {
483                     baseType = LongType.v();
484                     descriptor = descriptor.substring(1);
485                 }
486                 else if(descriptor.startsWith("L"))
487                 {
488                     int index = descriptor.indexOf(';');
489
490                     if(index == -1)
491                         throw new RuntimeException("Class reference has no ending ;");
492
493                     String className = descriptor.substring(1, index);
494
495                     baseType = RefType.v(className.replace('/', '.'));
496
497                     descriptor = descriptor.substring(index + 1);
498                 }
499                 else if(descriptor.startsWith("S"))
500                 {
501                     baseType = ShortType.v();
502                     descriptor = descriptor.substring(1);
503                 }
504                 else if(descriptor.startsWith("Z"))
505                 {
506                     baseType = BooleanType.v();
507                     descriptor = descriptor.substring(1);
508                 }
509                 else if(descriptor.startsWith("V"))
510                 {
511                     baseType = VoidType.v();
512                     descriptor = descriptor.substring(1);
513                 }
514                 else
515                     throw new RuntimeException("Unknown field type!");
516
517             Type t;
518
519             // Determine type
520                 if(isArray)
521                     t = ArrayType.v(baseType, numDimensions);
522                 else
523                     t = baseType;
524
525             conversionTypes.add(t);
526         }
527
528         ret = (Type[]) conversionTypes.toArray(new Type[0]);
529         cache.put(descriptor, ret);
530         return ret;
531     }
532 */

533
534
535     private Map cache = new HashMap();
536     public Type[] jimpleTypesOfFieldOrMethodDescriptor(String JavaDoc descriptor)
537     {
538         Type[] ret = (Type[]) cache.get(descriptor);
539         if( ret != null ) return ret;
540         char[] d = descriptor.toCharArray();
541         int p = 0;
542         conversionTypes.clear();
543
544 outer:
545         while(p<d.length)
546         {
547             boolean isArray = false;
548             int numDimensions = 0;
549             Type baseType = null;
550
551 swtch:
552             while(p<d.length) {
553                 switch( d[p] ) {
554                 // Skip parenthesis
555
case '(': case ')':
556                         p++;
557                         continue outer;
558
559                     case '[':
560                         isArray = true;
561                         numDimensions++;
562                         p++;
563                         continue swtch;
564                     case 'B':
565                         baseType = ByteType.v();
566                         p++;
567                         break swtch;
568                     case 'C':
569                         baseType = CharType.v();
570                         p++;
571                         break swtch;
572                     case 'D':
573                         baseType = DoubleType.v();
574                         p++;
575                         break swtch;
576                     case 'F':
577                         baseType = FloatType.v();
578                         p++;
579                         break swtch;
580                     case 'I':
581                         baseType = IntType.v();
582                         p++;
583                         break swtch;
584                     case 'J':
585                         baseType = LongType.v();
586                         p++;
587                         break swtch;
588                     case 'L':
589                         int index = p+1;
590                         while(index < d.length && d[index] != ';') {
591                             if(d[index] == '/') d[index] = '.';
592                             index++;
593                         }
594                         if( index >= d.length )
595                             throw new RuntimeException JavaDoc("Class reference has no ending ;");
596                         String JavaDoc className = new String JavaDoc(d, p+1, index - p - 1);
597                         baseType = RefType.v(className);
598                         p = index+1;
599                         break swtch;
600                     case 'S':
601                         baseType = ShortType.v();
602                         p++;
603                         break swtch;
604                     case 'Z':
605                         baseType = BooleanType.v();
606                         p++;
607                         break swtch;
608                     case 'V':
609                         baseType = VoidType.v();
610                         p++;
611                         break swtch;
612                     default:
613                         throw new RuntimeException JavaDoc("Unknown field type!");
614                 }
615             }
616             if( baseType == null ) continue;
617
618             // Determine type
619
Type t;
620             if(isArray)
621                 t = ArrayType.v(baseType, numDimensions);
622             else
623                 t = baseType;
624
625             conversionTypes.add(t);
626         }
627
628         ret = (Type[]) conversionTypes.toArray(new Type[0]);
629         cache.put(descriptor, ret);
630         return ret;
631     }
632
633     public Type jimpleTypeOfFieldDescriptor(String JavaDoc descriptor)
634     {
635         boolean isArray = false;
636         int numDimensions = 0;
637         Type baseType;
638
639         // Handle array case
640
while(descriptor.startsWith("["))
641             {
642                 isArray = true;
643                 numDimensions++;
644                 descriptor = descriptor.substring(1);
645             }
646
647         // Determine base type
648
if(descriptor.equals("B"))
649                 baseType = ByteType.v();
650             else if(descriptor.equals("C"))
651                 baseType = CharType.v();
652             else if(descriptor.equals("D"))
653                 baseType = DoubleType.v();
654             else if(descriptor.equals("F"))
655                 baseType = FloatType.v();
656             else if(descriptor.equals("I"))
657                 baseType = IntType.v();
658             else if(descriptor.equals("J"))
659                 baseType = LongType.v();
660             else if(descriptor.equals("V"))
661                 baseType = VoidType.v();
662             else if(descriptor.startsWith("L"))
663             {
664                 if(!descriptor.endsWith(";"))
665                     throw new RuntimeException JavaDoc("Class reference does not end with ;");
666
667                 String JavaDoc className = descriptor.substring(1, descriptor.length() - 1);
668
669                 baseType = RefType.v(className.replace('/', '.'));
670             }
671             else if(descriptor.equals("S"))
672                 baseType = ShortType.v();
673             else if(descriptor.equals("Z"))
674                 baseType = BooleanType.v();
675             else
676                 throw new RuntimeException JavaDoc("Unknown field type: " + descriptor);
677
678         // Return type
679
if(isArray)
680                 return ArrayType.v(baseType, numDimensions);
681             else
682                 return baseType;
683     }
684
685     int nextEasyNameIndex;
686
687     void resetEasyNames()
688     {
689         nextEasyNameIndex = 0;
690     }
691
692     String JavaDoc getNextEasyName()
693     {
694         final String JavaDoc[] easyNames =
695             {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
696              "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
697
698         int justifiedIndex = nextEasyNameIndex++;
699
700         if(justifiedIndex >= easyNames.length)
701             return "local" + (justifiedIndex - easyNames.length);
702         else
703             return easyNames[justifiedIndex];
704     }
705
706     void setClassNameToAbbreviation(Map map)
707     {
708         classNameToAbbreviation = map;
709     }
710
711     Local getLocalForStackOp(JimpleBody listBody, TypeStack typeStack,
712         int index)
713     {
714         if(typeStack.get(index).equals(Double2ndHalfType.v()) ||
715             typeStack.get(index).equals(Long2ndHalfType.v()))
716         {
717             index--;
718         }
719
720         return getLocalCreatingIfNecessary(listBody, "$stack" + index, UnknownType.v());
721     }
722
723     String JavaDoc getAbbreviationOfClassName(String JavaDoc className)
724     {
725         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(new Character JavaDoc(className.charAt(0)).toString());
726         int periodIndex = 0;
727
728         for(;;)
729         {
730             periodIndex = className.indexOf('.', periodIndex + 1);
731
732             if(periodIndex == -1)
733                 break;
734
735             buffer.append(Character.toLowerCase(className.charAt(periodIndex + 1)));
736         }
737
738         return buffer.toString();
739     }
740
741     String JavaDoc getNormalizedClassName(String JavaDoc className)
742     {
743         className = className.replace('/', '.');
744
745         if(className.endsWith(";"))
746             className = className.substring(0, className.length() - 1);
747
748         // Handle array case
749
{
750             int numDimensions = 0;
751
752             while(className.startsWith("["))
753             {
754                 numDimensions++;
755                 className = className.substring(1, className.length());
756                 className = className + "[]";
757             }
758
759             if(numDimensions != 0)
760             {
761                 if(!className.startsWith("L"))
762                     throw new RuntimeException JavaDoc("For some reason an array reference does not start with L");
763
764                 className = className.substring(1, className.length());
765             }
766         }
767
768
769         return className;
770     }
771
772     public Local getLocal(Body b, String JavaDoc name)
773         throws soot.jimple.NoSuchLocalException
774     {
775         Iterator localIt = b.getLocals().iterator();
776
777         while(localIt.hasNext())
778         {
779             Local local = (Local) localIt.next();
780
781             if(local.getName().equals(name))
782                 return local;
783         }
784
785         throw new soot.jimple.NoSuchLocalException();
786     }
787
788
789     public boolean declaresLocal(Body b, String JavaDoc localName)
790     {
791         Iterator localIt = b.getLocals().iterator();
792
793         while(localIt.hasNext())
794         {
795             Local local = (Local) localIt.next();
796
797             if(local.getName().equals(localName))
798                 return true;
799         }
800
801         return false;
802     }
803
804      Local
805         getLocalCreatingIfNecessary(JimpleBody listBody, String JavaDoc name, Type type)
806     {
807         if(declaresLocal(listBody, name))
808         {
809             return getLocal(listBody, name);
810         }
811         else {
812             Local l = Jimple.v().newLocal(name, type);
813             listBody.getLocals().add(l);
814
815             return l;
816         }
817     }
818
819     Local getLocalForIndex(JimpleBody listBody, int index)
820     {
821         String JavaDoc name = null;
822         String JavaDoc debug_type = null;
823         boolean assignedName = false;
824         boolean assignedType = false;
825         
826         if(useFaithfulNaming && activeVariableTable != null)
827         {
828             if(activeOriginalIndex != -1)
829             {
830
831           // Feng asks: why this is necessary? it does wrong thing
832
// for searching local variable names.
833
// It is going to be verified with plam.
834
if(isLocalStore)
835                     activeOriginalIndex++;
836                 if(isWideLocalStore)
837                     activeOriginalIndex++;
838
839                 name = activeVariableTable.getLocalVariableName(activeConstantPool, index, activeOriginalIndex);
840                 if (activeVariableTypeTable != null){
841                debug_type = activeVariableTypeTable.getLocalVariableType(activeConstantPool, index, activeOriginalIndex);
842                if (debug_type != null){
843                     assignedType = true;
844                }
845                 }
846                 if(name != null)
847                     assignedName = true;
848             }
849         }
850         
851         if(!assignedName)
852             name = "l" + index;
853
854         if(declaresLocal(listBody, name))
855             return getLocal(listBody, name);
856         else {
857             Local l = Jimple.v().newLocal(name,
858                 UnknownType.v());
859
860             listBody.getLocals().add(l);
861             /*if (debug_type != null){
862                 l.addTag(new DebugTypeTag(debug_type));
863             } */

864
865             return l;
866         }
867     }
868
869     /*
870     void setLocalType(Local local, List locals,
871         int localIndex, Type type)
872     {
873         if(local.getType().equals(UnknownType.v()) ||
874             local.getType().equals(type))
875         {
876             local.setType(type);
877
878             if(local.getType().equals(DoubleType.v()) ||
879                 local.getType().equals(LongType.v()))
880             {
881                 // This means the next local becomes voided, since these types occupy two
882                 // words.
883
884                 Local secondHalf = (Local) locals.get(localIndex + 1);
885
886                 secondHalf.setType(VoidType.v());
887             }
888
889             return;
890         }
891
892         if(type.equals(IntType.v()))
893         {
894             if(local.getType().equals(BooleanType.v()) ||
895                local.getType().equals(CharType.v()) ||
896                local.getType().equals(ShortType.v()) ||
897                local.getType().equals(ByteType.v()))
898             {
899                 // Even though it's not the same, it's ok, because booleans, chars, shorts, and
900                 // bytes are all sort of treated like integers by the JVM.
901                 return;
902             }
903
904         }
905
906         throw new RuntimeException("required and actual types do not match: " + type.toString() +
907                 " with " + local.getType().toString());
908     } */

909
910     /** Verifies the prospective name for validity as a Jimple name.
911      * In particular, first-char is alpha | _ | $, subsequent-chars
912      * are alphanum | _ | $.
913      *
914      * We could use isJavaIdentifier, except that Jimple's grammar
915      * doesn't support all of those, just ASCII.
916      *
917      * I'd put this in soot.Local, but that's an interface.
918      *
919      * @author Patrick Lam
920      */

921     boolean isValidJimpleName(String JavaDoc prospectiveName) {
922         if(prospectiveName == null) return false;
923     for (int i = 0; i < prospectiveName.length(); i++) {
924         char c = prospectiveName.charAt(i);
925         if (i == 0 && c >= '0' && c <= '9')
926         return false;
927
928         if (!((c >= '0' && c <= '9') ||
929           (c >= 'a' && c <= 'z') ||
930           (c >= 'A' && c <= 'Z') ||
931           (c == '_' || c == '$')))
932         return false;
933     }
934     return true;
935     }
936
937     private void addAnnotationVisibilityAttribute(Host host, attribute_info attribute, ClassFile coffiClass, List references){
938         VisibilityAnnotationTag tag;
939         if (attribute instanceof RuntimeVisibleAnnotations_attribute){
940             tag = new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_VISIBLE);
941             RuntimeVisibleAnnotations_attribute attr = (RuntimeVisibleAnnotations_attribute)attribute;
942             addAnnotations(attr.number_of_annotations, attr.annotations, coffiClass, tag, references);
943         }
944         else {
945             tag = new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_INVISIBLE);
946             RuntimeInvisibleAnnotations_attribute attr = (RuntimeInvisibleAnnotations_attribute)attribute;
947             addAnnotations(attr.number_of_annotations, attr.annotations, coffiClass, tag, references);
948         }
949         host.addTag(tag);
950     }
951     
952     private void addAnnotationVisibilityParameterAttribute(Host host, attribute_info attribute, ClassFile coffiClass, List references){
953         VisibilityParameterAnnotationTag tag;
954         if (attribute instanceof RuntimeVisibleParameterAnnotations_attribute){
955             RuntimeVisibleParameterAnnotations_attribute attr = (RuntimeVisibleParameterAnnotations_attribute)attribute;
956             tag = new VisibilityParameterAnnotationTag(attr.num_parameters, AnnotationConstants.RUNTIME_VISIBLE);
957             for (int i = 0; i < attr.num_parameters; i++){
958                 parameter_annotation pAnnot = attr.parameter_annotations[i];
959                 VisibilityAnnotationTag vTag = new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_VISIBLE);
960                 addAnnotations(pAnnot.num_annotations, pAnnot.annotations, coffiClass, vTag, references);
961                 tag.addVisibilityAnnotation(vTag);
962             }
963         }
964         else {
965             RuntimeInvisibleParameterAnnotations_attribute attr = (RuntimeInvisibleParameterAnnotations_attribute)attribute;
966             tag = new VisibilityParameterAnnotationTag(attr.num_parameters, AnnotationConstants.RUNTIME_INVISIBLE);
967             for (int i = 0; i < attr.num_parameters; i++){
968                 parameter_annotation pAnnot = attr.parameter_annotations[i];
969                 VisibilityAnnotationTag vTag = new VisibilityAnnotationTag(AnnotationConstants.RUNTIME_INVISIBLE);
970                 addAnnotations(pAnnot.num_annotations, pAnnot.annotations, coffiClass, vTag, references);
971                 tag.addVisibilityAnnotation(vTag);
972             }
973         }
974         host.addTag(tag);
975     }
976
977     private void addAnnotations(int numAnnots, annotation [] annotations, ClassFile coffiClass, VisibilityAnnotationTag tag, List references){
978         for (int i = 0; i < numAnnots; i++){
979             annotation annot = annotations[i];
980             String JavaDoc annotType = ((CONSTANT_Utf8_info)coffiClass.constant_pool[annot.type_index]).convert();
981             String JavaDoc ref = annotType.substring(1, annotType.length()-1);
982             ref = ref.replace('/', '.');
983             references.add(ref);
984             int numElems = annot.num_element_value_pairs;
985             AnnotationTag annotTag = new AnnotationTag(annotType, numElems);
986             annotTag.setElems(createElementTags(numElems, coffiClass, annot.element_value_pairs));
987             tag.addAnnotation(annotTag);
988         }
989     }
990     
991     private ArrayList createElementTags(int count, ClassFile coffiClass, element_value [] elems){
992         ArrayList list = new ArrayList();
993         for (int j = 0; j < count; j++){
994             element_value ev = (element_value)elems[j];
995             char kind = ev.tag;
996             String JavaDoc elemName = "default";
997             if (ev.name_index != 0){
998                 elemName = ((CONSTANT_Utf8_info)coffiClass.constant_pool[ev.name_index]).convert();
999             }
1000            if (kind == 'B' || kind == 'C' || kind == 'I' || kind == 'S' || kind == 'Z' || kind == 'D' || kind == 'F' || kind == 'J' || kind == 's'){
1001                constant_element_value cev = (constant_element_value)ev;
1002                if (kind == 'B' || kind == 'C' || kind == 'I' || kind == 'S' || kind == 'Z'){
1003                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
1004                    int constant_val = (int)((CONSTANT_Integer_info)cval).bytes;
1005                    AnnotationIntElem elem = new AnnotationIntElem(constant_val, kind, elemName);
1006                    list.add(elem);
1007                }
1008                else if (kind == 'D'){
1009                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
1010                    double constant_val = ((CONSTANT_Double_info)cval).convert();
1011                    AnnotationDoubleElem elem = new AnnotationDoubleElem(constant_val, kind, elemName);
1012                    list.add(elem);
1013                
1014                }
1015                else if (kind == 'F'){
1016                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
1017                    float constant_val = ((CONSTANT_Float_info)cval).convert();
1018                    AnnotationFloatElem elem = new AnnotationFloatElem(constant_val, kind, elemName);
1019                    list.add(elem);
1020                
1021                }
1022                else if (kind == 'J'){
1023                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
1024                    CONSTANT_Long_info lcval = (CONSTANT_Long_info)cval;
1025                    long constant_val = (lcval.high << 32) + lcval.low;
1026                    AnnotationLongElem elem = new AnnotationLongElem(constant_val, kind, elemName);
1027                    list.add(elem);
1028                
1029                }
1030                else if (kind == 's'){
1031                    cp_info cval = coffiClass.constant_pool[cev.constant_value_index];
1032                    String JavaDoc constant_val = ((CONSTANT_Utf8_info)cval).convert();
1033                    AnnotationStringElem elem = new AnnotationStringElem(constant_val, kind, elemName);
1034                    list.add(elem);
1035                }
1036            }
1037            else if (kind == 'e'){
1038                enum_constant_element_value ecev = (enum_constant_element_value)ev;
1039                cp_info type_val = coffiClass.constant_pool[ecev.type_name_index];
1040                String JavaDoc type_name = ((CONSTANT_Utf8_info)type_val).convert();
1041                cp_info name_val = coffiClass.constant_pool[ecev.constant_name_index];
1042                String JavaDoc constant_name = ((CONSTANT_Utf8_info)name_val).convert();
1043                AnnotationEnumElem elem = new AnnotationEnumElem(type_name, constant_name, kind, elemName);
1044                list.add(elem);
1045            }
1046            else if (kind == 'c'){
1047                class_element_value cev = (class_element_value)ev;
1048                cp_info cval = coffiClass.constant_pool[cev.class_info_index];
1049                CONSTANT_Utf8_info sval = (CONSTANT_Utf8_info)cval;
1050                String JavaDoc desc = sval.convert();
1051                
1052                AnnotationClassElem elem = new AnnotationClassElem(desc, kind, elemName);
1053                list.add(elem);
1054            }
1055            else if (kind == '['){
1056                array_element_value aev = (array_element_value)ev;
1057                int num_vals = aev.num_values;
1058
1059                ArrayList elemVals = createElementTags(num_vals, coffiClass, aev.values);
1060                AnnotationArrayElem elem = new AnnotationArrayElem(elemVals, kind, elemName);
1061                list.add(elem);
1062            }
1063            else if (kind == '@'){
1064                annotation_element_value aev = (annotation_element_value)ev;
1065                annotation annot = aev.annotation_value;
1066                String JavaDoc annotType = ((CONSTANT_Utf8_info)coffiClass.constant_pool[annot.type_index]).convert();
1067                int numElems = annot.num_element_value_pairs;
1068                AnnotationTag annotTag = new AnnotationTag(annotType, numElems);
1069                annotTag.setElems(createElementTags(numElems, coffiClass, annot.element_value_pairs));
1070                
1071                AnnotationAnnotationElem elem = new AnnotationAnnotationElem(annotTag, kind, elemName);
1072                list.add(elem);
1073            }
1074        }
1075   
1076        return list;
1077    }
1078}
1079
Popular Tags