KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ashes > examples > countgotos > Main


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 1997-1999 Raja Vallee-Rai
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 /* Reference Version: $SootVersion: 1.beta.6.dev.51 $ */
27
28 package ashes.examples.countgotos;
29
30 import soot.*;
31 import soot.jimple.*;
32 import soot.util.*;
33 import java.io.*;
34 import java.util.*;
35
36 /**
37    Example to instrument a classfile to produce goto counts.
38  */

39 public class Main
40 {
41     public static void main(String JavaDoc[] args)
42     {
43         if(args.length == 0)
44         {
45             System.out.println("Syntax: java ashes.examples.countgotos.Main [soot options]");
46             System.exit(0);
47         }
48         
49         PackManager.v().getPack("jtp").add(new Transform("jtp.instrumenter", GotoInstrumenter.v()));
50
51     // Just in case, resolve the PrintStream SootClass.
52
Scene.v().addBasicClass("java.io.PrintStream",SootClass.SIGNATURES);
53         soot.Main.main(args);
54     }
55 }
56
57 /**
58     InstrumentClass example.
59     
60     Instruments the given class to print out the number of Jimple goto
61     statements executed.
62
63     To enable this class, enable the given PackAdjuster by compiling it
64     separately, into the soot package.
65  */

66
67 class GotoInstrumenter extends BodyTransformer
68 {
69     private static GotoInstrumenter instance = new GotoInstrumenter();
70     private GotoInstrumenter() {}
71
72     public static GotoInstrumenter v() { return instance; }
73
74     private boolean addedFieldToMainClassAndLoadedPrintStream = false;
75     private SootClass javaIoPrintStream;
76
77     private Local addTmpRef(Body body)
78     {
79         Local tmpRef = Jimple.v().newLocal("tmpRef", RefType.v("java.io.PrintStream"));
80         body.getLocals().add(tmpRef);
81         return tmpRef;
82     }
83      
84     private Local addTmpLong(Body body)
85     {
86         Local tmpLong = Jimple.v().newLocal("tmpLong", LongType.v());
87         body.getLocals().add(tmpLong);
88         return tmpLong;
89     }
90
91     private void addStmtsToBefore(Chain units, Stmt s, SootField gotoCounter, Local tmpRef, Local tmpLong)
92     {
93         // insert "tmpRef = java.lang.System.out;"
94
units.insertBefore(Jimple.v().newAssignStmt(
95                       tmpRef, Jimple.v().newStaticFieldRef(
96                       Scene.v().getField("<java.lang.System: java.io.PrintStream out>").makeRef())), s);
97
98         // insert "tmpLong = gotoCounter;"
99
units.insertBefore(Jimple.v().newAssignStmt(tmpLong,
100                       Jimple.v().newStaticFieldRef(gotoCounter.makeRef())), s);
101             
102         // insert "tmpRef.println(tmpLong);"
103
SootMethod toCall = javaIoPrintStream.getMethod("void println(long)");
104         units.insertBefore(Jimple.v().newInvokeStmt(
105                       Jimple.v().newVirtualInvokeExpr(tmpRef, toCall.makeRef(), tmpLong)), s);
106     }
107
108     protected void internalTransform(Body body, String JavaDoc phaseName, Map options)
109     {
110         SootClass sClass = body.getMethod().getDeclaringClass();
111         SootField gotoCounter = null;
112         boolean addedLocals = false;
113         Local tmpRef = null, tmpLong = null;
114         Chain units = body.getUnits();
115         
116         // Add code at the end of the main method to print out the
117
// gotoCounter (this only works in simple cases, because you may have multiple returns or System.exit()'s )
118
synchronized(this)
119         {
120             if (!Scene.v().getMainClass().
121                     declaresMethod("void main(java.lang.String[])"))
122                 throw new RuntimeException JavaDoc("couldn't find main() in mainClass");
123
124             if (addedFieldToMainClassAndLoadedPrintStream)
125                 gotoCounter = Scene.v().getMainClass().getFieldByName("gotoCount");
126             else
127             {
128                 // Add gotoCounter field
129
gotoCounter = new SootField("gotoCount", LongType.v(),
130                                                 Modifier.STATIC);
131                 Scene.v().getMainClass().addField(gotoCounter);
132
133                 javaIoPrintStream = Scene.v().getSootClass("java.io.PrintStream");
134
135                 addedFieldToMainClassAndLoadedPrintStream = true;
136             }
137         }
138             
139         // Add code to increase goto counter each time a goto is encountered
140
{
141             boolean isMainMethod = body.getMethod().getSubSignature().equals("void main(java.lang.String[])");
142
143             Local tmpLocal = Jimple.v().newLocal("tmp", LongType.v());
144             body.getLocals().add(tmpLocal);
145                 
146             Iterator stmtIt = units.snapshotIterator();
147             
148             while(stmtIt.hasNext())
149             {
150                 Stmt s = (Stmt) stmtIt.next();
151
152                 if(s instanceof GotoStmt)
153                 {
154                     AssignStmt toAdd1 = Jimple.v().newAssignStmt(tmpLocal,
155                                  Jimple.v().newStaticFieldRef(gotoCounter.makeRef()));
156                     AssignStmt toAdd2 = Jimple.v().newAssignStmt(tmpLocal,
157                                  Jimple.v().newAddExpr(tmpLocal, LongConstant.v(1L)));
158                     AssignStmt toAdd3 = Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(gotoCounter.makeRef()),
159                                                                  tmpLocal);
160
161                     // insert "tmpLocal = gotoCounter;"
162
units.insertBefore(toAdd1, s);
163                         
164                     // insert "tmpLocal = tmpLocal + 1L;"
165
units.insertBefore(toAdd2, s);
166
167                     // insert "gotoCounter = tmpLocal;"
168
units.insertBefore(toAdd3, s);
169                 }
170                 else if (s instanceof InvokeStmt)
171                 {
172                     InvokeExpr iexpr = (InvokeExpr) ((InvokeStmt)s).getInvokeExpr();
173                     if (iexpr instanceof StaticInvokeExpr)
174                     {
175                         SootMethod target = ((StaticInvokeExpr)iexpr).getMethod();
176                         
177                         if (target.getSignature().equals("<java.lang.System: void exit(int)>"))
178                         {
179                             if (!addedLocals)
180                             {
181                                 tmpRef = addTmpRef(body); tmpLong = addTmpLong(body);
182                                 addedLocals = true;
183                             }
184                             addStmtsToBefore(units, s, gotoCounter, tmpRef, tmpLong);
185                         }
186                     }
187                 }
188                 else if (isMainMethod && (s instanceof ReturnStmt || s instanceof ReturnVoidStmt))
189                 {
190                     if (!addedLocals)
191                     {
192                         tmpRef = addTmpRef(body); tmpLong = addTmpLong(body);
193                         addedLocals = true;
194                     }
195                     addStmtsToBefore(units, s, gotoCounter, tmpRef, tmpLong);
196                 }
197             }
198         }
199     }
200 }
201
Popular Tags