1 package edu.berkeley.cs.megacz;
8 public class Transformer {
9 public static void main(String[] args)
13 System.out.println("Syntax: java ashes.examples.countgotos.Main [soot options]");
17 PackManager.v().getPack("jtp").add(new Transform("jtp.instrumenter", GotoInstrumenter.v()));
19 // Just in case, resolve the PrintStream SootClass.
20 Scene.v().addBasicClass("java.io.PrintStream",SootClass.SIGNATURES);
24 static class GotoInstrumenter extends BodyTransformer {
25 private static GotoInstrumenter instance = new GotoInstrumenter();
26 private GotoInstrumenter() {}
28 public static GotoInstrumenter v() { return instance; }
30 private boolean addedFieldToMainClassAndLoadedPrintStream = false;
31 private SootClass javaIoPrintStream;
33 private Local addTmpRef(Body body) {
34 Local tmpRef = Jimple.v().newLocal("tmpRef", RefType.v("java.io.PrintStream"));
35 body.getLocals().add(tmpRef);
39 private Local addTmpLong(Body body) {
40 Local tmpLong = Jimple.v().newLocal("tmpLong", LongType.v());
41 body.getLocals().add(tmpLong);
45 private void addStmtsToBefore(Chain units, Stmt s, SootField gotoCounter, Local tmpRef, Local tmpLong)
47 // insert "tmpRef = java.lang.System.out;"
48 units.insertBefore(Jimple.v().newAssignStmt(
49 tmpRef, Jimple.v().newStaticFieldRef(
50 Scene.v().getField("<java.lang.System: java.io.PrintStream out>").makeRef())), s);
52 // insert "tmpLong = gotoCounter;"
53 units.insertBefore(Jimple.v().newAssignStmt(tmpLong,
54 Jimple.v().newStaticFieldRef(gotoCounter.makeRef())), s);
56 // insert "tmpRef.println(tmpLong);"
57 SootMethod toCall = javaIoPrintStream.getMethod("void println(long)");
58 units.insertBefore(Jimple.v().newInvokeStmt(
59 Jimple.v().newVirtualInvokeExpr(tmpRef, toCall.makeRef(), tmpLong)), s);
62 protected void internalTransform(Body body, String phaseName, Map options) {
63 SootClass sClass = body.getMethod().getDeclaringClass();
64 SootField gotoCounter = null;
65 boolean addedLocals = false;
66 Local tmpRef = null, tmpLong = null;
67 Chain units = body.getUnits();
69 System.out.println("sClass is " + sClass);
71 // Add code at the end of the main method to print out the
72 // gotoCounter (this only works in simple cases, because you may have multiple returns or System.exit()'s )
75 if (!Scene.v().getMainClass().
76 declaresMethod("void main(java.lang.String[])"))
77 throw new RuntimeException("couldn't find main() in mainClass");
79 if (addedFieldToMainClassAndLoadedPrintStream)
80 gotoCounter = Scene.v().getMainClass().getFieldByName("gotoCount");
83 // Add gotoCounter field
84 gotoCounter = new SootField("gotoCount", LongType.v(),
86 Scene.v().getMainClass().addField(gotoCounter);
88 javaIoPrintStream = Scene.v().getSootClass("java.io.PrintStream");
90 addedFieldToMainClassAndLoadedPrintStream = true;
94 // Add code to increase goto counter each time a goto is encountered
96 boolean isMainMethod = body.getMethod().getSubSignature().equals("void main(java.lang.String[])");
98 Local tmpLocal = Jimple.v().newLocal("tmp", LongType.v());
99 body.getLocals().add(tmpLocal);
101 Iterator stmtIt = units.snapshotIterator();
103 while(stmtIt.hasNext())
105 Stmt s = (Stmt) stmtIt.next();
107 if(s instanceof GotoStmt)
109 AssignStmt toAdd1 = Jimple.v().newAssignStmt(tmpLocal,
110 Jimple.v().newStaticFieldRef(gotoCounter.makeRef()));
111 AssignStmt toAdd2 = Jimple.v().newAssignStmt(tmpLocal,
112 Jimple.v().newAddExpr(tmpLocal, LongConstant.v(1L)));
113 AssignStmt toAdd3 = Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(gotoCounter.makeRef()),
116 // insert "tmpLocal = gotoCounter;"
117 units.insertBefore(toAdd1, s);
119 // insert "tmpLocal = tmpLocal + 1L;"
120 units.insertBefore(toAdd2, s);
122 // insert "gotoCounter = tmpLocal;"
123 units.insertBefore(toAdd3, s);
125 else if (s instanceof InvokeStmt)
127 InvokeExpr iexpr = (InvokeExpr) ((InvokeStmt)s).getInvokeExpr();
128 if (iexpr instanceof StaticInvokeExpr)
130 SootMethod target = ((StaticInvokeExpr)iexpr).getMethod();
132 if (target.getSignature().equals("<java.lang.System: void exit(int)>"))
136 tmpRef = addTmpRef(body); tmpLong = addTmpLong(body);
139 addStmtsToBefore(units, s, gotoCounter, tmpRef, tmpLong);
143 else if (isMainMethod && (s instanceof ReturnStmt || s instanceof ReturnVoidStmt))
147 tmpRef = addTmpRef(body); tmpLong = addTmpLong(body);
150 addStmtsToBefore(units, s, gotoCounter, tmpRef, tmpLong);