public void staticBlockInlining(SootClass sootClass) { this.sootClass = sootClass; // retrieve the clinit method if any for sootClass if (!sootClass.declaresMethod("void <clinit>()")) { System.out.println("no clinit"); return; } SootMethod clinit = sootClass.getMethod("void <clinit>()"); // System.out.println(clinit); // retireve the active body if (!clinit.hasActiveBody()) throw new RuntimeException("method " + clinit.getName() + " has no active body!"); Body clinitBody = clinit.getActiveBody(); Chain units = ((DavaBody) clinitBody).getUnits(); if (units.size() != 1) { throw new RuntimeException("DavaBody AST doesn't have single root."); } ASTNode AST = (ASTNode) units.getFirst(); if (!(AST instanceof ASTMethodNode)) throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode"); AST.apply(new MethodCallFinder(this)); }
private void printStatementsInBody(Body body, java.io.PrintWriter out) { if (Options.v().verbose()) System.out.println("Printing " + body.getMethod().getName()); Chain<Unit> units = ((DavaBody) body).getUnits(); if (units.size() != 1) { throw new RuntimeException("DavaBody AST doesn't have single root."); } UnitPrinter up = new DavaUnitPrinter((DavaBody) body); ((ASTNode) units.getFirst()).toString(up); out.print(up.toString()); }
protected void internalTransform(Body body, String phaseName, Map options) { if (Options.v().verbose()) G.v().out.println("[" + body.getMethod().getName() + "] Tightening trap boundaries..."); Chain trapChain = body.getTraps(); Chain unitChain = body.getUnits(); if (trapChain.size() > 0) { ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body); for (Iterator trapIt = trapChain.iterator(); trapIt.hasNext(); ) { Trap trap = (Trap) trapIt.next(); Unit firstTrappedUnit = trap.getBeginUnit(); Unit firstTrappedThrower = null; Unit firstUntrappedUnit = trap.getEndUnit(); Unit lastTrappedUnit = (Unit) unitChain.getPredOf(firstUntrappedUnit); Unit lastTrappedThrower = null; for (Unit u = firstTrappedUnit; u != null && u != firstUntrappedUnit; u = (Unit) unitChain.getSuccOf(u)) { if (mightThrowTo(graph, u, trap)) { firstTrappedThrower = u; break; } } if (firstTrappedThrower != null) { for (Unit u = lastTrappedUnit; u != null; u = (Unit) unitChain.getPredOf(u)) { if (mightThrowTo(graph, u, trap)) { lastTrappedThrower = u; break; } } } if (firstTrappedThrower != null && firstTrappedUnit != firstTrappedThrower) { trap.setBeginUnit(firstTrappedThrower); } if (lastTrappedThrower == null) { lastTrappedThrower = firstTrappedUnit; } if (lastTrappedUnit != lastTrappedThrower) { trap.setEndUnit((Unit) unitChain.getSuccOf(lastTrappedThrower)); } } } }
public ASTMethodNode inline(SootMethod maybeInline) { // check if this method should be inlined if (sootClass != null) { // 1, method should belong to the same class as the clinit method if (sootClass.declaresMethod(maybeInline.getSubSignature())) { // System.out.println("The method invoked is from the same class"); // 2, method should be static if (Modifier.isStatic(maybeInline.getModifiers())) { // decided to inline // send the ASTMethod node of the TO BE INLINED METHOD // retireve the active body if (!maybeInline.hasActiveBody()) throw new RuntimeException("method " + maybeInline.getName() + " has no active body!"); Body bod = maybeInline.getActiveBody(); Chain units = ((DavaBody) bod).getUnits(); if (units.size() != 1) { throw new RuntimeException("DavaBody AST doesn't have single root."); } ASTNode ASTtemp = (ASTNode) units.getFirst(); if (!(ASTtemp instanceof ASTMethodNode)) throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode"); // restricting to methods which do not have any variables declared ASTMethodNode toReturn = (ASTMethodNode) ASTtemp; ASTStatementSequenceNode declarations = toReturn.getDeclarations(); if (declarations.getStatements().size() == 0) { // inline only if there are no declarations in the method inlined System.out.println("No declarations in the method. we can inline this method"); return toReturn; } } } } return null; // meaning dont inline }
public int size() { return unitChain.size(); }
/** Constructs a hierarchy from the current scene. */ public Hierarchy() { this.sc = Scene.v(); state = sc.getState(); // Well, this used to be describable by 'Duh'. // Construct the subclasses hierarchy and the subinterfaces hierarchy. { Chain allClasses = sc.getClasses(); classToSubclasses = new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f); interfaceToSubinterfaces = new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f); classToDirSubclasses = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f); interfaceToDirSubinterfaces = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f); interfaceToDirImplementers = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f); Iterator classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.isInterface()) { interfaceToDirSubinterfaces.put(c, new ArrayList()); interfaceToDirImplementers.put(c, new ArrayList()); } else classToDirSubclasses.put(c, new ArrayList()); } classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.hasSuperclass()) { if (c.isInterface()) { Iterator subIt = c.getInterfaces().iterator(); while (subIt.hasNext()) { SootClass i = (SootClass) subIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; List<SootClass> l = interfaceToDirSubinterfaces.get(i); l.add(c); } } else { List<SootClass> l = classToDirSubclasses.get(c.getSuperclass()); l.add(c); Iterator subIt = c.getInterfaces().iterator(); while (subIt.hasNext()) { SootClass i = (SootClass) subIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; l = interfaceToDirImplementers.get(i); l.add(c); } } } } // Fill the directImplementers lists with subclasses. { classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.isInterface()) { List<SootClass> imp = interfaceToDirImplementers.get(c); Set<SootClass> s = new ArraySet(); Iterator<SootClass> impIt = imp.iterator(); while (impIt.hasNext()) { SootClass c0 = impIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; s.addAll(getSubclassesOfIncluding(c0)); } imp.clear(); imp.addAll(s); } } } classesIt = allClasses.iterator(); while (classesIt.hasNext()) { SootClass c = (SootClass) classesIt.next(); if (c.resolvingLevel() < SootClass.HIERARCHY) continue; if (c.isInterface()) { interfaceToDirSubinterfaces.put( c, Collections.unmodifiableList(interfaceToDirSubinterfaces.get(c))); interfaceToDirImplementers.put( c, Collections.unmodifiableList(interfaceToDirImplementers.get(c))); } else classToDirSubclasses.put(c, Collections.unmodifiableList(classToDirSubclasses.get(c))); } } }
void doWeave( SootMethod method, LocalGeneratorEx lg, AdviceApplication adviceappl, Residue residue, WeavingContext wc) { AdviceInliner.v().addShadowMethod(method); ShadowPoints shadowpoints = adviceappl.shadowmatch.sp; AbstractAdviceDecl advicedecl = adviceappl.advice; Body b = method.getActiveBody(); Chain units = b.getUnits().getNonPatchingChain(); // end of shadow Stmt endshadow = shadowpoints.getEnd(); NopStmt nop2 = Jimple.v().newNopStmt(); GotoStmt goto1 = Jimple.v().newGotoStmt(nop2); if (advicedecl instanceof CflowSetup) { Tagger.tagStmt(goto1, InstructionKindTag.CFLOW_EXIT); } else if (advicedecl instanceof PerCflowSetup) { Tagger.tagStmt(goto1, InstructionKindTag.PERCFLOW_EXIT); } else if (advicedecl instanceof DeclareSoft) { Tagger.tagStmt(goto1, InstructionKindTag.EXCEPTION_SOFTENER); } else if (advicedecl instanceof DeclareMessage) { Tagger.tagStmt(goto1, InstructionKindTag.DECLARE_MESSAGE); } else { Tagger.tagStmt(goto1, InstructionKindTag.AFTER_THROWING_HANDLER); } Tagger.tagStmt(goto1, new InstructionSourceTag(advicedecl.sourceId)); Tagger.tagStmt(goto1, new InstructionShadowTag(adviceappl.shadowmatch.shadowId)); units.insertBefore(nop2, endshadow); units.insertBefore(goto1, nop2); // have ... // goto1: goto nop2; // nop2: nop; // endshadow: nop; RefType catchType = getCatchType(); Local exception = lg.generateLocal(catchType, "exception"); bindException(wc, advicedecl, exception); CaughtExceptionRef exceptRef = Jimple.v().newCaughtExceptionRef(); IdentityStmt idStmt = Jimple.v().newIdentityStmt(exception, exceptRef); units.insertAfter(idStmt, goto1); ThrowStmt throwStmt = Jimple.v().newThrowStmt(exception); throwStmt.addTag(new ThrowCreatedByCompilerTag()); if (advicedecl instanceof CflowSetup) { Tagger.tagStmt(throwStmt, InstructionKindTag.CFLOW_EXIT); } else if (advicedecl instanceof PerCflowSetup) { Tagger.tagStmt(throwStmt, InstructionKindTag.PERCFLOW_EXIT); } else if (advicedecl instanceof DeclareSoft) { Tagger.tagStmt(throwStmt, InstructionKindTag.EXCEPTION_SOFTENER); } else if (advicedecl instanceof DeclareMessage) { Tagger.tagStmt(throwStmt, InstructionKindTag.DECLARE_MESSAGE); } else { Tagger.tagStmt(throwStmt, InstructionKindTag.AFTER_THROWING_HANDLER); } Tagger.tagStmt(throwStmt, new InstructionSourceTag(advicedecl.sourceId)); Tagger.tagStmt(throwStmt, new InstructionShadowTag(adviceappl.shadowmatch.shadowId)); // store shadow/source tag for this residue in weaving context if (advicedecl instanceof CflowSetup) { wc.setKindTag(InstructionKindTag.CFLOW_TEST); } if (advicedecl instanceof PerCflowSetup) { wc.setKindTag(InstructionKindTag.CFLOW_TEST); } wc.setShadowTag(new InstructionShadowTag(adviceappl.shadowmatch.shadowId)); wc.setSourceTag(new InstructionSourceTag(adviceappl.advice.sourceId)); Stmt endresidue = residue.codeGen(method, lg, units, idStmt, throwStmt, true, wc); // have ... // java.lang.Exception exception; // // goto1: goto nop2; // idStmt: exception := @caughtexception // nop2: nop; // endshadow: nop; units.insertAfter(throwStmt, endresidue); Chain invokestmts = advicedecl.makeAdviceExecutionStmts(adviceappl, lg, wc); for (Iterator stmtlist = invokestmts.iterator(); stmtlist.hasNext(); ) { Stmt nextstmt = (Stmt) stmtlist.next(); units.insertBefore(nextstmt, throwStmt); } if (method.getName().equals("<clinit>")) // have to handle case of ExceptionInInitialzerError { // if (exception instanceof java.lang.ExceptionInIntializerError) // throw (exception); debug("Adding extra check in clinit"); Local isInitError = lg.generateLocal(soot.BooleanType.v(), "isInitError"); Stmt assignbool = Jimple.v() .newAssignStmt( isInitError, Jimple.v() .newInstanceOfExpr( exception, RefType.v("java.lang.ExceptionInInitializerError"))); Stmt ifstmt = Jimple.v().newIfStmt(Jimple.v().newNeExpr(isInitError, IntConstant.v(0)), throwStmt); // ThrowStmt throwInitError = Jimple.v().newThrowStmt(exception); // units.insertAfter(throwInitError, idStmt); units.insertAfter(ifstmt, idStmt); units.insertAfter(assignbool, idStmt); } Stmt beginshadow = shadowpoints.getBegin(); Stmt begincode = (Stmt) units.getSuccOf(beginshadow); // have ... // java.lang.Exception exception; // <AspectType> theAspect; // // beginshadow: nop // begincode: <some statement> // .... <stuff in between> // goto1: goto nop2; // idStmt: exception := @caughtexception; // assignStmt: theAspect = new AspectOf(); // .... invoke statements .... // throwStmt: throw exception; // nop2: nop; // endshadow: nop; Chain traps = b.getTraps(); Trap t = traps.size() > 0 ? (Trap) traps.getFirst() : null; // assume no exception ranges overlap with this one; make sure // we go after any that would be enclosed within this one. while (t != null && (units.follows(t.getBeginUnit(), begincode) || (t.getBeginUnit() == begincode && units.follows(idStmt, t.getEndUnit())))) t = (Trap) traps.getSuccOf(t); Trap newt = Jimple.v().newTrap(catchType.getSootClass(), begincode, idStmt, idStmt); if (t == null) traps.addLast(newt); else traps.insertBefore(newt, t); // added // catch java.lang.Throwable // from begincode upto idStmt handlewith idStmt } // method doWeave
/** * 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()); }