package soot.jimple.toolkits.thread.mhp.findobject; import soot.Scene; import soot.SootMethod; import soot.toolkits.graph.CompleteUnitGraph; import soot.toolkits.graph.UnitGraph; import soot.toolkits.scalar.FlowSet; import soot.util.*; import java.util.*; import soot.jimple.toolkits.callgraph.CallGraph; import soot.jimple.toolkits.thread.mhp.pegcallgraph.PegCallGraph; /* import soot.tagkit.*; import soot.toolkits.scalar.*; */ // *** USE AT YOUR OWN RISK *** // May Happen in Parallel (MHP) analysis by Lin Li. // This code should be treated as beta-quality code. // It was written in 2003, but not incorporated into Soot until 2006. // As such, it may contain incorrect assumptions about the usage // of certain Soot classes. // Some portions of this MHP analysis have been quality-checked, and are // now used by the Transactions toolkit. // // -Richard L. Halpert, 2006-11-30 public class MultiCalledMethods{ Set<SootMethod> multiCalledMethods = new HashSet<SootMethod>(); MultiCalledMethods(PegCallGraph pcg, Set<SootMethod> mcm){ multiCalledMethods = mcm; byMCalledS0(pcg); finder1(pcg); finder2(pcg); propagate(pcg); } private void byMCalledS0(PegCallGraph pcg) { Iterator it = pcg.iterator(); while (it.hasNext()){ SootMethod sm = (SootMethod)it.next(); UnitGraph graph = new CompleteUnitGraph(sm.getActiveBody()); CallGraph callGraph = Scene.v().getCallGraph(); MultiRunStatementsFinder finder = new MultiRunStatementsFinder(graph, sm, multiCalledMethods, callGraph); FlowSet fs = finder.getMultiRunStatements(); } } private void propagate(PegCallGraph pcg){ Set<SootMethod> visited = new HashSet(); List<SootMethod> reachable = new ArrayList<SootMethod>(); reachable.addAll(multiCalledMethods); while(reachable.size()>=1) { SootMethod popped = reachable.remove(0); if(visited.contains(popped)) continue; if (!multiCalledMethods.contains(popped)) multiCalledMethods.add(popped); visited.add(popped); Iterator succIt = pcg.getSuccsOf(popped).iterator(); while (succIt.hasNext()){ Object succ = succIt.next(); reachable.add((SootMethod)succ); } } } //Use breadth first search to find methods are called more than once in call graph private void finder1(PegCallGraph pcg){ Set clinitMethods = pcg.getClinitMethods(); Iterator it = pcg.iterator(); while (it.hasNext()){ Object head = it.next(); //breadth first scan Set<Object> gray = new HashSet<Object>(); LinkedList<Object> queue = new LinkedList<Object>(); queue.add(head); while (queue.size()>0){ Object root = queue.getFirst(); Iterator succsIt = pcg.getSuccsOf(root).iterator(); while (succsIt.hasNext()){ Object succ = succsIt.next(); if (!gray.contains(succ)){ gray.add(succ); queue.addLast(succ); } else if(clinitMethods.contains(succ)) continue; else{ multiCalledMethods.add((SootMethod) succ); } } queue.remove(root); } } } //Find multi called methods relavant to recusive method invocation private void finder2(PegCallGraph pcg){ pcg.trim(); Set<SootMethod> first = new HashSet<SootMethod>(); Set<SootMethod> second = new HashSet<SootMethod>(); // Visit each node Iterator it = pcg.iterator(); while (it.hasNext()){ SootMethod s = (SootMethod) it.next(); if (!second.contains(s)){ visitNode(s, pcg, first, second); } } } private void visitNode(SootMethod node, PegCallGraph pcg, Set<SootMethod> first, Set<SootMethod> second){ if (first.contains(node)){ second.add(node); if (!multiCalledMethods.contains(node)){ multiCalledMethods.add(node); } } else first.add(node); Iterator it = pcg.getTrimSuccsOf(node).iterator(); while (it.hasNext()){ SootMethod succ = (SootMethod) it.next(); if (!second.contains(succ)){ visitNode(succ, pcg, first, second); } } } public Set<SootMethod> getMultiCalledMethods(){ return multiCalledMethods; } }