KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > AbstractJasminClass


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

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

26
27
28
29
30
31 package soot;
32 import soot.options.*;
33 import soot.tagkit.*;
34 import soot.*;
35 import soot.jimple.*;
36 import soot.toolkits.graph.*;
37 import soot.util.*;
38 import java.util.*;
39 import java.io.*;
40 import soot.baf.*;
41
42 public abstract class AbstractJasminClass
43 {
44     protected Map unitToLabel;
45     protected Map localToSlot;
46     protected Map subroutineToReturnAddressSlot;
47
48     protected List code;
49
50     protected boolean isEmittingMethodCode;
51     protected int labelCount;
52
53     protected boolean isNextGotoAJsr;
54     protected int returnAddressSlot;
55     protected int currentStackHeight = 0;
56     protected int maxStackHeight = 0;
57
58     protected Map localToGroup;
59     protected Map groupToColorCount;
60     protected Map localToColor;
61
62
63     protected Map blockToStackHeight = new HashMap(); // maps a block to the stack height upon entering it
64
protected Map blockToLogicalStackHeight = new HashMap(); // maps a block to the logical stack height upon entering it
65

66
67     public static String JavaDoc slashify(String JavaDoc s)
68     {
69         return s.replace('.', '/');
70     }
71
72     public static int sizeOfType(Type t)
73     {
74         if(t instanceof DoubleWordType || t instanceof LongType || t instanceof DoubleType)
75             return 2;
76         else if(t instanceof VoidType)
77             return 0;
78         else
79             return 1;
80     }
81
82     public static int argCountOf(SootMethodRef m)
83     {
84         int argCount = 0;
85         Iterator typeIt = m.parameterTypes().iterator();
86
87         while(typeIt.hasNext())
88         {
89             Type t = (Type) typeIt.next();
90
91             argCount += sizeOfType(t);
92         }
93
94         return argCount;
95     }
96
97     public static String JavaDoc jasminDescriptorOf(Type type)
98     {
99         TypeSwitch sw;
100
101         type.apply(sw = new TypeSwitch()
102         {
103             public void caseBooleanType(BooleanType t)
104             {
105                 setResult("Z");
106             }
107
108             public void caseByteType(ByteType t)
109             {
110                 setResult("B");
111             }
112
113             public void caseCharType(CharType t)
114             {
115                 setResult("C");
116             }
117
118             public void caseDoubleType(DoubleType t)
119             {
120                 setResult("D");
121             }
122
123             public void caseFloatType(FloatType t)
124             {
125                 setResult("F");
126             }
127
128             public void caseIntType(IntType t)
129             {
130                 setResult("I");
131             }
132
133             public void caseLongType(LongType t)
134             {
135                 setResult("J");
136             }
137
138             public void caseShortType(ShortType t)
139             {
140                 setResult("S");
141             }
142
143             public void defaultCase(Type t)
144             {
145                 throw new RuntimeException JavaDoc("Invalid type: " + t);
146             }
147
148             public void caseArrayType(ArrayType t)
149             {
150                 StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
151
152                 for(int i = 0; i < t.numDimensions; i++)
153                     buffer.append("[");
154
155                 setResult(buffer.toString() + jasminDescriptorOf(t.baseType));
156             }
157
158             public void caseRefType(RefType t)
159             {
160                 setResult("L" + t.getClassName().replace('.', '/') + ";");
161             }
162
163             public void caseVoidType(VoidType t)
164             {
165                 setResult("V");
166             }
167         });
168
169         return (String JavaDoc) sw.getResult();
170
171     }
172
173     public static String JavaDoc jasminDescriptorOf(SootMethodRef m)
174     {
175         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
176
177         buffer.append("(");
178
179         // Add methods parameters
180
{
181             Iterator typeIt = m.parameterTypes().iterator();
182
183             while(typeIt.hasNext())
184             {
185                 Type t = (Type) typeIt.next();
186
187                 buffer.append(jasminDescriptorOf(t));
188             }
189         }
190
191         buffer.append(")");
192
193         buffer.append(jasminDescriptorOf(m.returnType()));
194
195         return buffer.toString();
196     }
197
198     protected void emit(String JavaDoc s)
199     {
200         okayEmit(s);
201     }
202     
203     protected void okayEmit(String JavaDoc s)
204     {
205         if(isEmittingMethodCode && !s.endsWith(":"))
206             code.add(" " + s);
207         else
208             code.add(s);
209     }
210     
211     private String JavaDoc getVisibilityAnnotationAttr(VisibilityAnnotationTag tag){
212         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
213         if (tag.getVisibility() == AnnotationConstants.RUNTIME_VISIBLE){
214             sb.append(".runtime_visible_annotation\n");
215         }
216         else {
217             sb.append(".runtime_invisible_annotation\n");
218         }
219         if (tag.hasAnnotations()){
220             Iterator it = tag.getAnnotations().iterator();
221             while (it.hasNext()){
222                 AnnotationTag annot = (AnnotationTag)it.next();
223                 sb.append(".annotation ");
224                 sb.append(soot.util.StringTools.getQuotedStringOf(annot.getType())+"\n");
225                 for (int i = 0; i < annot.getNumElems(); i++){
226                     sb.append(getElemAttr(annot.getElemAt(i)));
227                 }
228                 sb.append(".end .annotation\n");
229             }
230         }
231         sb.append(".end .annotation_attr\n");
232         return sb.toString();
233     }
234    
235     
236     private String JavaDoc getVisibilityParameterAnnotationAttr(VisibilityParameterAnnotationTag tag){
237         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
238         sb.append(".param ");
239         if (tag.getKind() == AnnotationConstants.RUNTIME_VISIBLE){
240             sb.append(".runtime_visible_annotation\n");
241         }
242         else {
243             sb.append(".runtime_invisible_annotation\n");
244         }
245         ArrayList vis_list = tag.getVisibilityAnnotations();
246         if (vis_list != null){
247             Iterator it = vis_list.iterator();
248             while (it.hasNext()){
249                 sb.append(getVisibilityAnnotationAttr((VisibilityAnnotationTag)it.next()));
250             }
251         }
252         sb.append(".end .param\n");
253         return sb.toString();
254     }
255    
256     private String JavaDoc getElemAttr(AnnotationElem elem){
257         StringBuffer JavaDoc result = new StringBuffer JavaDoc(".elem ");
258         switch (elem.getKind()){
259             case 'Z': {
260                         result.append(".bool_kind ");
261                         result.append("\""+elem.getName()+"\" ");
262                         result.append(((AnnotationIntElem)elem).getValue());
263                         result.append("\n");
264                         break;
265                       }
266             case 'S': {
267                         result.append(".short_kind ");
268                         result.append("\""+elem.getName()+"\" ");
269                         result.append(((AnnotationIntElem)elem).getValue());
270                         result.append("\n");
271                         break;
272                       }
273             case 'B': {
274                         result.append(".byte_kind ");
275                         result.append("\""+elem.getName()+"\" ");
276                         result.append(((AnnotationIntElem)elem).getValue());
277                         result.append("\n");
278                         break;
279                       }
280             case 'C': {
281                         result.append(".char_kind ");
282                         result.append("\""+elem.getName()+"\" ");
283                         result.append(((AnnotationIntElem)elem).getValue());
284                         result.append("\n");
285                         break;
286                       }
287             case 'I': {
288                         result.append(".int_kind ");
289                         result.append("\""+elem.getName()+"\" ");
290                         result.append(((AnnotationIntElem)elem).getValue());
291                         result.append("\n");
292                         break;
293                       }
294             case 'J': {
295                         result.append(".long_kind ");
296                         result.append("\""+elem.getName()+"\" ");
297                         result.append(((AnnotationLongElem)elem).getValue());
298                         result.append("\n");
299                         break;
300                       }
301             case 'F': {
302                         result.append(".float_kind ");
303                         result.append("\""+elem.getName()+"\" ");
304                         result.append(Float.floatToRawIntBits(((AnnotationFloatElem)elem).getValue()));
305                         result.append("\n");
306                         break;
307                       }
308             case 'D': {
309                         result.append(".doub_kind ");
310                         result.append("\""+elem.getName()+"\" ");
311                         result.append(Double.doubleToRawLongBits(((AnnotationDoubleElem)elem).getValue()));
312                         result.append("\n");
313                         break;
314                       }
315             case 's': {
316                         result.append(".str_kind ");
317                         result.append("\""+elem.getName()+"\" ");
318                         result.append(soot.util.StringTools.getQuotedStringOf(((AnnotationStringElem)elem).getValue()));
319                         result.append("\n");
320                         break;
321                       }
322             case 'e': {
323                         result.append(".enum_kind ");
324                         result.append("\""+elem.getName()+"\" ");
325                         result.append(soot.util.StringTools.getQuotedStringOf(((AnnotationEnumElem)elem).getTypeName()));
326                         result.append(" ");
327                         result.append(soot.util.StringTools.getQuotedStringOf(((AnnotationEnumElem)elem).getConstantName()));
328                         result.append("\n");
329                         break;
330                       }
331             case 'c': {
332                         result.append(".cls_kind ");
333                         result.append("\""+elem.getName()+"\" ");
334                         result.append(soot.util.StringTools.getQuotedStringOf(((AnnotationClassElem)elem).getDesc()));
335                         result.append("\n");
336                         break;
337                       }
338             case '[': {
339                         result.append(".arr_kind ");
340                         result.append("\""+elem.getName()+"\" ");
341                         AnnotationArrayElem arrayElem = (AnnotationArrayElem)elem;
342                         result.append("\n");
343                         for (int i = 0; i < arrayElem.getNumValues(); i++){
344                             //result.append("\n");
345
result.append(getElemAttr(arrayElem.getValueAt(i)));
346                         }
347                         result.append(".end .arr_elem\n");
348                         break;
349                       }
350             case '@': {
351                         result.append(".ann_kind ");
352                         result.append("\""+elem.getName()+"\"\n");
353                         AnnotationTag annot = ((AnnotationAnnotationElem)elem).getValue();
354                         result.append(".annotation ");
355                         result.append(soot.util.StringTools.getQuotedStringOf(annot.getType())+"\n");
356                         for (int i = 0; i < annot.getNumElems(); i++){
357                             result.append(getElemAttr(annot.getElemAt(i)));
358                         }
359                         result.append(".end .annotation\n");
360                         result.append(".end .annot_elem\n");
361                         break;
362                       }
363             default : {
364                 throw new RuntimeException JavaDoc("Unknown Elem Attr Kind: "+elem.getKind());
365             }
366         }
367         return result.toString();
368     }
369     
370     public AbstractJasminClass(SootClass sootClass)
371     {
372         if(Options.v().time())
373             Timers.v().buildJasminTimer.start();
374         
375         if(Options.v().verbose())
376             G.v().out.println("[" + sootClass.getName() + "] Constructing baf.JasminClass...");
377
378         code = new LinkedList();
379
380         // Emit the header
381
{
382             int modifiers = sootClass.getModifiers();
383
384             
385             if ((sootClass.getTag("SourceFileTag") != null) && (!Options.v().no_output_source_file_attribute())){
386                 String JavaDoc srcName = ((SourceFileTag)sootClass.getTag("SourceFileTag")).getSourceFile();
387                 emit(".source "+soot.util.StringTools.getEscapedStringOf(srcName));
388             }
389             if(Modifier.isInterface(modifiers))
390             {
391                 modifiers -= Modifier.INTERFACE;
392
393                 emit(".interface " + Modifier.toString(modifiers) + " " + slashify(sootClass.getName()));
394             }
395             else
396                 emit(".class " + Modifier.toString(modifiers) + " " + slashify(sootClass.getName()));
397
398             if(sootClass.hasSuperclass())
399                 emit(".super " + slashify(sootClass.getSuperclass().getName()));
400             else
401                 emit(".no_super");
402
403             emit("");
404         }
405
406         // Emit the interfaces
407
{
408             Iterator interfaceIt = sootClass.getInterfaces().iterator();
409
410             while(interfaceIt.hasNext())
411             {
412                 SootClass inter = (SootClass) interfaceIt.next();
413
414                 emit(".implements " + slashify(inter.getName()));
415             }
416
417             /* why do this????
418             if(sootClass.getInterfaceCount() != 0)
419                 emit("");*/

420         }
421
422
423
424
425
426     
427     // emit class attributes.
428
Iterator it = sootClass.getTags().iterator();
429     while(it.hasNext()) {
430         Tag tag = (Tag) it.next();
431         if(tag instanceof Attribute)
432         emit(".class_attribute " + tag.getName() + " \"" + new String JavaDoc(Base64.encode(((Attribute)tag).getValue()))+"\"");
433         /*else {
434             emit("");
435         }*/

436     }
437
438
439     // emit synthetic attributes
440
if (sootClass.hasTag("SyntheticTag")){
441         emit(".synthetic\n");
442     }
443     // emit deprecated attributes
444
if (sootClass.hasTag("DeprecatedTag")){
445         emit(".deprecated\n");
446     }
447     // emit inner class attributes
448
if (sootClass.hasTag("InnerClassAttribute")){
449         if (!Options.v().no_output_inner_classes_attribute()){
450             emit(".inner_class_attr ");
451             Iterator innersIt = ((InnerClassAttribute)sootClass.getTag("InnerClassAttribute")).getSpecs().iterator();
452             while (innersIt.hasNext()){
453                 InnerClassTag ict = (InnerClassTag)innersIt.next();
454                 //System.out.println("inner class tag: "+ict);
455
emit(".inner_class_spec_attr "+
456                     "\""+ict.getInnerClass()+"\" "+
457                 
458                     "\""+ict.getOuterClass()+"\" "+
459                 
460                     "\""+ict.getShortName()+"\" "+
461                     Modifier.toString(ict.getAccessFlags())+" "+
462
463                 ".end .inner_class_spec_attr");
464             }
465             emit(".end .inner_class_attr\n");
466         }
467     }
468     if (sootClass.hasTag("EnclosingMethodTag")){
469         String JavaDoc encMeth = ".enclosing_method_attr ";
470         EnclosingMethodTag eMethTag = (EnclosingMethodTag)sootClass.getTag("EnclosingMethodTag");
471         encMeth += "\""+eMethTag.getEnclosingClass()+"\" ";
472         encMeth += "\""+eMethTag.getEnclosingMethod()+"\" ";
473         encMeth += "\""+eMethTag.getEnclosingMethodSig()+"\"\n";
474         emit(encMeth);
475     }
476     if (sootClass.hasTag("SignatureTag")){
477         String JavaDoc sigAttr = ".signature_attr ";
478         SignatureTag sigTag = (SignatureTag)sootClass.getTag("SignatureTag");
479         sigAttr += "\""+sigTag.getSignature()+"\"\n";
480         emit(sigAttr);
481     }
482     
483     Iterator vit = sootClass.getTags().iterator();
484     while (vit.hasNext()){
485         Tag t = (Tag)vit.next();
486         if (t.getName().equals("VisibilityAnnotationTag")){
487             emit(getVisibilityAnnotationAttr((VisibilityAnnotationTag)t));
488         }
489     }
490
491         // Emit the fields
492
{
493             Iterator fieldIt = sootClass.getFields().iterator();
494
495             while(fieldIt.hasNext())
496             {
497                 SootField field = (SootField) fieldIt.next();
498
499                 String JavaDoc fieldString = ".field " + Modifier.toString(field.getModifiers()) + " " + "\"" + field.getName() + "\"" + " " + jasminDescriptorOf(field.getType());
500     
501                 if (field.hasTag("StringConstantValueTag")){
502                     fieldString += " = ";
503                     fieldString += soot.util.StringTools.getQuotedStringOf(((StringConstantValueTag)field.getTag("StringConstantValueTag")).getStringValue());
504                 }
505                 else if (field.hasTag("IntegerConstantValueTag")){
506                     fieldString += " = ";
507                     fieldString += ((IntegerConstantValueTag)field.getTag("IntegerConstantValueTag")).getIntValue();
508                 }
509                 else if (field.hasTag("LongConstantValueTag")){
510                     fieldString += " = ";
511                     fieldString += ((LongConstantValueTag)field.getTag("LongConstantValueTag")).getLongValue();
512                 }
513                 else if (field.hasTag("FloatConstantValueTag")){
514                     fieldString += " = ";
515                     float val = ((FloatConstantValueTag)field.getTag("FloatConstantValueTag")).getFloatValue();
516                     fieldString += Float.floatToRawIntBits(val);
517                 }
518                 else if (field.hasTag("DoubleConstantValueTag")){
519                     fieldString += " = ";
520                     double val = ((DoubleConstantValueTag)field.getTag("DoubleConstantValueTag")).getDoubleValue();
521                     fieldString += Double.doubleToRawLongBits(val);
522                 }
523                 if (field.hasTag("SyntheticTag")){
524                     fieldString +=" .synthetic";
525                 }
526
527                 fieldString +="\n";
528                 if (field.hasTag("DeprecatedTag")){
529                     fieldString +=".deprecated\n";
530                 }
531                 if (field.hasTag("SignatureTag")){
532                     fieldString += ".signature_attr ";
533                     SignatureTag sigTag = (SignatureTag)field.getTag("SignatureTag");
534                     fieldString += "\""+sigTag.getSignature()+"\"\n";
535                 }
536                 Iterator vfit = field.getTags().iterator();
537                 while (vfit.hasNext()){
538                     Tag t = (Tag)vfit.next();
539                     if (t.getName().equals("VisibilityAnnotationTag")){
540                         fieldString += getVisibilityAnnotationAttr((VisibilityAnnotationTag)t);
541                     }
542                 }
543
544                 emit(fieldString);
545
546         Iterator attributeIt = field.getTags().iterator();
547         while(attributeIt.hasNext()) {
548             Tag tag = (Tag) attributeIt.next();
549             if(tag instanceof Attribute)
550             emit(".field_attribute " + tag.getName() + " \"" + new String JavaDoc(Base64.encode(((Attribute)tag).getValue())) +"\"");
551         }
552
553             }
554
555             if(sootClass.getFieldCount() != 0)
556                 emit("");
557         }
558
559         // Emit the methods
560
{
561             Iterator methodIt = sootClass.methodIterator();
562
563             while(methodIt.hasNext())
564             {
565                 emitMethod((SootMethod) methodIt.next());
566                 emit("");
567             }
568         }
569         
570         if(Options.v().time())
571             Timers.v().buildJasminTimer.end();
572     }
573
574     protected void assignColorsToLocals(Body body)
575     {
576         if(Options.v().verbose())
577             G.v().out.println("[" + body.getMethod().getName() +
578                 "] Assigning colors to locals...");
579         
580         if(Options.v().time())
581             Timers.v().packTimer.start();
582
583         localToGroup = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
584         groupToColorCount = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
585         localToColor = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
586         
587         // Assign each local to a group, and set that group's color count to 0.
588
{
589             Iterator localIt = body.getLocals().iterator();
590
591             while(localIt.hasNext())
592             {
593                 Local l = (Local) localIt.next();
594                 Object JavaDoc g;
595                 
596                 if(sizeOfType(l.getType()) == 1)
597                     g = IntType.v();
598                 else
599                     g = LongType.v();
600                 
601                 localToGroup.put(l, g);
602                 
603                 if(!groupToColorCount.containsKey(g))
604                 {
605                     groupToColorCount.put(g, new Integer JavaDoc(0));
606                 }
607             }
608         }
609
610         // Assign colors to the parameter locals.
611
{
612             Iterator codeIt = body.getUnits().iterator();
613
614             while(codeIt.hasNext())
615             {
616                 Stmt s = (Stmt) codeIt.next();
617
618                 if(s instanceof IdentityStmt &&
619                     ((IdentityStmt) s).getLeftOp() instanceof Local)
620                 {
621                     Local l = (Local) ((IdentityStmt) s).getLeftOp();
622                     
623                     Object JavaDoc group = localToGroup.get(l);
624                     int count = ((Integer JavaDoc) groupToColorCount.get(group)).intValue();
625                     
626                     localToColor.put(l, new Integer JavaDoc(count));
627                     
628                     count++;
629                     
630                     groupToColorCount.put(group, new Integer JavaDoc(count));
631                 }
632             }
633         }
634         
635     }
636
637     protected void emitMethod(SootMethod method)
638     {
639        if (method.isPhantom())
640            return;
641
642        // Emit prologue
643
emit(".method " + Modifier.toString(method.getModifiers()) + " " +
644                  method.getName() + jasminDescriptorOf(method.makeRef()));
645
646             Iterator throwsIt = method.getExceptions().iterator();
647             while (throwsIt.hasNext()){
648                 SootClass exceptClass = (SootClass)throwsIt.next();
649                 emit(".throws "+exceptClass.getName());
650             }
651             if (method.hasTag("SyntheticTag")){
652                 emit(".synthetic");
653             }
654             if (method.hasTag("DeprecatedTag")){
655                 emit(".deprecated");
656             }
657             if (method.hasTag("SignatureTag")){
658                 String JavaDoc sigAttr = ".signature_attr ";
659                 SignatureTag sigTag = (SignatureTag)method.getTag("SignatureTag");
660                 sigAttr += "\""+sigTag.getSignature()+"\"";
661                 emit(sigAttr);
662             }
663             if (method.hasTag("AnnotationDefaultTag")){
664                 String JavaDoc annotDefAttr = ".annotation_default ";
665                 AnnotationDefaultTag annotDefTag = (AnnotationDefaultTag)method.getTag("AnnotationDefaultTag");
666                 annotDefAttr += getElemAttr(annotDefTag.getDefaultVal());
667                 annotDefAttr += ".end .annotation_default";
668                 emit(annotDefAttr);
669             }
670             Iterator vit = method.getTags().iterator();
671             while (vit.hasNext()){
672                 Tag t = (Tag)vit.next();
673                 if (t.getName().equals("VisibilityAnnotationTag")){
674                     emit(getVisibilityAnnotationAttr((VisibilityAnnotationTag)t));
675                 }
676                 if (t.getName().equals("VisibilityParameterAnnotationTag")){
677                     emit(getVisibilityParameterAnnotationAttr((VisibilityParameterAnnotationTag)t));
678                 }
679             }
680
681        if(method.isConcrete())
682        {
683             if(!method.hasActiveBody())
684                 throw new RuntimeException JavaDoc("method: " + method.getName() + " has no active body!");
685             else
686                 emitMethodBody(method);
687        }
688        
689        // Emit epilogue
690
emit(".end method");
691
692         Iterator it = method.getTags().iterator();
693         while(it.hasNext()) {
694         Tag tag = (Tag) it.next();
695         if(tag instanceof Attribute)
696             emit(".method_attribute " + tag.getName() + " \"" + new String JavaDoc(Base64.encode(tag.getValue())) +"\"");
697         }
698     }
699     
700     protected abstract void emitMethodBody(SootMethod method);
701
702     public void print(PrintWriter out)
703     {
704         Iterator it = code.iterator();
705
706         while(it.hasNext())
707             out.println(it.next());
708     }
709
710 }
711
712
Popular Tags