/** * @ast method * @aspect Expressions * @declaredat * /Users/eric/Documents/workspaces/clara-soot/JastAddExtensions/JimpleBackend/Expressions.jrag:84 */ public soot.Value eval(Body b) { TypeDecl dest = getDest().type(); TypeDecl source = getSource().type(); if (dest.isString()) { Value lvalue = getDest().eval(b); Value v = asImmediate(b, lvalue); // new StringBuffer(left) Local local = b.newTemp(b.newNewExpr(lookupType("java.lang", "StringBuffer").sootRef(), this)); b.setLine(this); b.add( b.newInvokeStmt( b.newSpecialInvokeExpr( local, Scene.v() .getMethod("<java.lang.StringBuffer: void <init>(java.lang.String)>") .makeRef(), v, this), this)); // append right Local rightResult = b.newTemp( b.newVirtualInvokeExpr( local, lookupType("java.lang", "StringBuffer") .methodWithArgs("append", new TypeDecl[] {source.stringPromotion()}) .sootRef(), asImmediate(b, getSource().eval(b)), this)); // toString Local result = b.newTemp( b.newVirtualInvokeExpr( rightResult, Scene.v() .getMethod("<java.lang.StringBuffer: java.lang.String toString()>") .makeRef(), this)); Value v2 = lvalue instanceof Local ? lvalue : (Value) lvalue.clone(); getDest().emitStore(b, v2, result, this); return result; } else { return super.eval(b); } }
public static void main(String args[]) { // Set classPath String exemplePath = "/Users/gamyot/Documents/workspace/Soot_Exemples/src/"; String objectPath = "/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar"; String tracePath = "/Users/gamyot/Documents/workspace/SootInstrumenter/src/"; Scene.v().setSootClassPath(".:" + objectPath + ":" + exemplePath + ":" + tracePath); Scene.v().loadClassAndSupport("java.lang.Object"); Scene.v().loadClassAndSupport("java.lang.System"); // Set up the class we’re working with SootClass c = Scene.v().loadClassAndSupport("MyExemples.ExempleBasic"); c.setApplicationClass(); // Get methods Iterator<SootMethod> methodIterator = c.methodIterator(); while (methodIterator.hasNext()) methodList.add(methodIterator.next()); // Iterate through the method list for (SootMethod m : methodList) { Body body = m.retrieveActiveBody(); PatchingChain<Unit> unitList = body.getUnits(); // get the all the "if statements" Units List<Unit> ifStmtList = searchIfStmts(body); // for each "if statement" unit, instrument and add the instrumentation code right after for (Unit ifStmtUnit : ifStmtList) { // Chain<Unit> instrumentedChain = generateInstrumentationUnits(ifStmtUnit, body); // unitList.insertAfter(instrumentedChain, ifStmtUnit); Chain<Unit> testChain = generateInstrumentationUnits(ifStmtUnit, body); unitList.insertAfter(testChain, ifStmtUnit); } // Output all the units for this method on terminal String methodName = m.getName(); System.out.println( "____Method: \"" + methodName + "\"__________________________________________________"); LoadAndGenerate.printAllUnits(body); } try { LoadAndGenerate.outputClassToBinary(c); } catch (IOException e) { e.printStackTrace(); } }
private static List<Unit> searchIfStmts(Body b) { List<Unit> searchResult = new ArrayList<Unit>(); PatchingChain<Unit> statements = b.getUnits(); Iterator<Unit> unitIt = statements.iterator(); // iterate through the Units of the body while (unitIt.hasNext()) { Unit tempUnit = unitIt.next(); // if the unit is a "if statement" if (tempUnit instanceof soot.jimple.internal.JIfStmt) searchResult.add(tempUnit); } return searchResult; }
/** * Create a method conveniently. The method is added to the class "TestClass". Parameters can be * given as an (positional) array of local variables (the "identity statements", required by Soot * to map parameters to local variables, are inserted automatically) */ public SootMethod makeMethod( int modifier, String name, List<Local> params, soot.Type retType, List<Unit> bodyStmts) { SootMethod m = new SootMethod( name, params.stream().map(Local::getType).collect(toList()), retType, modifier); this.testClass.addMethod(m); Body body = Jimple.v().newBody(m); m.setActiveBody(body); // set the statements for the body.. first the identity statements, then the bodyStmts if (!m.isStatic()) { body.getLocals().add(localThis); body.getUnits() .add(Jimple.v().newIdentityStmt(localThis, Jimple.v().newThisRef(testClass.getType()))); } IntStream.range(0, params.size()) .forEach( pos -> { Local l = params.get(pos); ParameterRef pr = Jimple.v().newParameterRef(l.getType(), pos); body.getUnits().add(Jimple.v().newIdentityStmt(l, pr)); }); body.getUnits().addAll(bodyStmts); // set the locals for the body Set<Local> locals = Stream.concat( params.stream(), body.getUseAndDefBoxes() .stream() .filter(b -> b.getValue() instanceof Local) .map(b -> (Local) b.getValue())) .collect(toSet()); locals.removeAll(body.getLocals()); body.getLocals().addAll(locals); return m; }
public void internalTransform(String phaseName, Map opts) { Iterator it = Scene.v().getApplicationClasses().iterator(); while (it.hasNext()) { SootClass sc = (SootClass) it.next(); // make map of first line to each method HashMap<Integer, SootMethod> lineToMeth = new HashMap<Integer, SootMethod>(); Iterator methIt = sc.getMethods().iterator(); while (methIt.hasNext()) { SootMethod meth = (SootMethod) methIt.next(); if (!meth.isConcrete()) continue; Body body = meth.retrieveActiveBody(); Stmt s = (Stmt) body.getUnits().getFirst(); while (s instanceof IdentityStmt) { s = (Stmt) body.getUnits().getSuccOf(s); } if (s.hasTag("LineNumberTag")) { LineNumberTag tag = (LineNumberTag) s.getTag("LineNumberTag"); lineToMeth.put(new Integer(tag.getLineNumber()), meth); } } Iterator methIt2 = sc.getMethods().iterator(); while (methIt2.hasNext()) { SootMethod meth = (SootMethod) methIt2.next(); if (!meth.isConcrete()) continue; Body body = meth.retrieveActiveBody(); Stmt s = (Stmt) body.getUnits().getFirst(); while (s instanceof IdentityStmt) { s = (Stmt) body.getUnits().getSuccOf(s); } if (s.hasTag("LineNumberTag")) { LineNumberTag tag = (LineNumberTag) s.getTag("LineNumberTag"); int line_num = tag.getLineNumber() - 1; // already taken if (lineToMeth.containsKey(new Integer(line_num))) { meth.addTag(new LineNumberTag(line_num + 1)); } // still available - so use it for this meth else { meth.addTag(new LineNumberTag(line_num)); } } } } }
/* * Generates the sequence of instructions needed to instrument ifStmtUnit * * @param ifStmtUnit: the unit to be instrumented * @return A Chain of Units that represent the instrumentation of ifStmtUnit */ private static Chain<Unit> generateInstrumentationUnits(Unit ifStmtUnit, Body b) { AbstractBinopExpr expression = (AbstractBinopExpr) ((JIfStmt) ifStmtUnit).getCondition(); // implementation of AbstractBinopExpr Value operand1 = expression.getOp1(); Value operand2 = expression.getOp2(); JimpleLocal op1Local = (JimpleLocal) operand1; // Local localOperand = Jimple.v().newLocal("op1", operand1.getType()); // b.getLocals().add(localOperand); // We need to use these operand as Locals or constants /** * JimpleLocal test; if(operand1 instanceof soot.jimple.internal.JimpleLocal) test = * (JimpleLocal)operand1; else test = null; */ String op = expression.getClass().toString(); Chain<Unit> resultUnits = new HashChain<Unit>(); Local tmpRef; // Add locals directely on the top of the body, java.io.printStream tmpRef tmpRef = Jimple.v().newLocal("tmpRef", RefType.v("java.io.PrintStream")); b.getLocals().addFirst(tmpRef); // add "tmpRef = java.lang.System.out" resultUnits.add( Jimple.v() .newAssignStmt( tmpRef, Jimple.v() .newStaticFieldRef( Scene.v() .getField("<java.lang.System: java.io.PrintStream out>") .makeRef()))); { SootMethod toCall = Scene.v().getMethod("<java.io.PrintStream: void println(java.lang.String)>"); resultUnits.add( Jimple.v() .newInvokeStmt( Jimple.v() .newVirtualInvokeExpr( tmpRef, toCall.makeRef(), StringConstant.v("Operande 1: ")))); resultUnits.add( Jimple.v() .newInvokeStmt( Jimple.v() .newVirtualInvokeExpr( tmpRef, toCall.makeRef(), StringConstant.v(operand1.getClass().toString())))); resultUnits.add( Jimple.v() .newInvokeStmt( Jimple.v() .newVirtualInvokeExpr( tmpRef, toCall.makeRef(), StringConstant.v("Operande 2:")))); resultUnits.add( Jimple.v() .newInvokeStmt( Jimple.v() .newVirtualInvokeExpr( tmpRef, toCall.makeRef(), StringConstant.v(operand2.getClass().toString())))); resultUnits.add( Jimple.v() .newInvokeStmt( Jimple.v() .newVirtualInvokeExpr( tmpRef, toCall.makeRef(), StringConstant.v("Operateur: ")))); resultUnits.add( Jimple.v() .newInvokeStmt( Jimple.v().newVirtualInvokeExpr(tmpRef, toCall.makeRef(), StringConstant.v(op)))); } return resultUnits; }
/** * Constructs a graph for the units found in the provided Body instance. Each node in the graph * corresponds to a unit. The edges are derived from the control flow. * * @param body The underlying body we want to make a graph for. * @param addExceptionEdges If true then the control flow edges associated with exceptions are * added. * @param dontAddEdgeFromStmtBeforeAreaOfProtectionToCatchBlock This was added for Dava. If true, * edges are not added from statement before area of protection to catch. If false, edges ARE * added. For Dava, it should be true. For flow analyses, it should be false. * @param Hierarchy Using class hierarchy analysis to find the run method of started thread * @param PointsToAnalysis Using point to analysis (SPARK package) to improve the precision of * results */ public PegGraph( CallGraph callGraph, Hierarchy hierarchy, PAG pag, Set methodsNeedingInlining, Set allocNodes, List<List> inlineSites, Map<SootMethod, String> synchObj, Set multiRunAllocNodes, Map<AllocNode, String> allocNodeToObj, Body unitBody, String threadName, SootMethod sm, boolean addExceEdge, boolean dontAddEdgeFromStmtBeforeAreaOfProtectionToCatchBlock) { this.allocNodeToObj = allocNodeToObj; this.multiRunAllocNodes = multiRunAllocNodes; this.synchObj = synchObj; this.inlineSites = inlineSites; this.allocNodes = allocNodes; this.methodsNeedingInlining = methodsNeedingInlining; logFile = new File("log.txt"); try { fileWriter = new FileWriter(logFile); } catch (IOException io) { System.err.println("Errors occur during create FileWriter !"); // throw io; } body = unitBody; synch = new HashSet<List>(); exceHandlers = new HashSet<Unit>(); needInlining = true; monitorObjs = new HashSet<Object>(); startToBeginNodes = new HashMap(); unitChain = body.getUnits(); int size = unitChain.size(); // initial unitToSuccs, unitToPreds, unitToPegMap, and startToThread unitToSuccs = new HashMap(size * 2 + 1, 0.7f); unitToPreds = new HashMap(size * 2 + 1, 0.7f); // unitToPegMap is the map of a chain to its corresponding (cfg node --> peg node ) map. unitToPegMap = new HashMap(size * 2 + 1, 0.7f); startToThread = new HashMap(size * 2 + 1, 0.7f); startToAllocNodes = new HashMap(size * 2 + 1, 0.7f); waitingNodes = new HashMap<String, FlowSet>(size * 2 + 1, 0.7f); joinStmtToThread = new HashMap<JPegStmt, Chain>(); threadNo = new HashMap(); threadNameToStart = new HashMap(); this.allocNodeToObj = new HashMap<AllocNode, String>(size * 2 + 1, 0.7f); allocNodeToThread = new HashMap<AllocNode, PegChain>(size * 2 + 1, 0.7f); notifyAll = new HashMap<String, Set<JPegStmt>>(size * 2 + 1, 0.7f); methodsNeedingInlining = new HashSet(); allNodes = new ArraySparseSet(); canNotBeCompacted = new HashSet(); threadAllocSites = new HashSet(); specialJoin = new HashSet<JPegStmt>(); // if(Main.isVerbose) // System.out.println(" Constructing PegGraph..."); // if(Main.isProfilingOptimization) // Main.graphTimer.start(); // make a peg for debug /* mainPegChain = new HashChain(); specialTreatment1(); */ // end make a peg UnitGraph mainUnitGraph = new CompleteUnitGraph(body); // mainPegChain = new HashChain(); mainPegChain = new PegChain( callGraph, hierarchy, pag, threadAllocSites, methodsNeedingInlining, allocNodes, inlineSites, synchObj, multiRunAllocNodes, allocNodeToObj, body, sm, threadName, true, this); // testPegChain(); // System.out.println("finish building chain"); // testStartToThread(); // buildSuccessor(mainUnitGraph, mainPegChain,addExceptionEdges); // buildSuccessorForExtendingMethod(mainPegChain); // testSet(exceHandlers, "exceHandlers"); buildSuccessor(mainPegChain); // System.out.println("finish building successors"); // unmodifiableSuccs(mainPegChain); // testUnitToSucc ); buildPredecessor(mainPegChain); // System.out.println("finish building predcessors"); // unmodifiablePreds(mainPegChain); // testSynch(); addMonitorStmt(); addTag(); // System.out.println(this.toString()); buildHeadsAndTails(); // testIterator(); // testWaitingNodes(); // System.out.println("finish building heads and tails"); // testSet(canNotBeCompacted, "canNotBeCompacted"); // computeEdgeAndThreadNo(); // testExtendingPoints(); // testUnitToSucc(); // testPegChain(); /* if (print) { PegToDotFile printer1 = new PegToDotFile(this, false, sm.getName()); } */ try { fileWriter.flush(); fileWriter.close(); } catch (IOException io) { System.err.println("Errors occur during close file " + logFile.getName()); // throw io; } // System.out.println("==threadAllocaSits==\n"+threadAllocSites.toString()); }
/** * @ast method * @aspect Expressions * @declaredat * /Users/eric/Documents/workspaces/clara-soot/JastAddExtensions/JimpleBackend/Expressions.jrag:183 */ public soot.Value createAssignOp(Body b, soot.Value fst, soot.Value snd) { return b.newXorExpr(asImmediate(b, fst), asImmediate(b, snd), this); }
/** * @ast method * @aspect Statements * @declaredat * /Users/eric/Documents/workspaces/clara-soot/JastAddExtensions/JimpleBackend/Statements.jrag:312 */ public void jimplify2(Body b) { b.setLine(this); b.add(b.newThrowStmt(asImmediate(b, getExpr().eval(b)), this)); }