/** Expensive! */ private void dumpCallGraphReachablesCSV() { try { FileWriter fw = new FileWriter(Project.v().getOutputDir() + File.separator + "reachables-count.csv"); fw.write("Method,Reachables"); for (MethodOrMethodContext momc : getReachableMethodContexts()) { if ("<clinit>".equals(momc.method().getName())) continue; Set<MethodOrMethodContext> c = new HashSet<MethodOrMethodContext>(); c.add(momc); Filter filter = new Filter(noStaticInits); // filter on static initializers, hopefully they won't show in the stats, // or any calls that they make... ReachableMethods rm = new ReachableMethods(callGraph, c.iterator(), filter); rm.update(); QueueReader<MethodOrMethodContext> edges = rm.listener(); int reachables = 0; while (edges.hasNext()) { MethodOrMethodContext reachable = edges.next(); if ("<clinit>".equals(reachable.method().getName())) continue; reachables++; } fw.write(momc + "|" + reachables + "\n"); } fw.close(); } catch (IOException e) { } }
public void getAllInvolvedMethods() { ReachableMethods rm = CallGraphHelper.getReachableMethod(Scene.v().getCallGraph(), syncsEnclosingMethods); for (Iterator<?> it = rm.listener(); it.hasNext(); ) { SootMethod m = (SootMethod) it.next(); allInvolvedMethod.add(m); } }
public ReachableMethods getReachableMethods() { if (reachableMethods == null) { reachableMethods = new ReachableMethods( getCallGraph(), new ArrayList<MethodOrMethodContext>(getEntryPoints())); } reachableMethods.update(); return reachableMethods; }
private void processReachables() { reachableMethods.update(); while (reachablesReader.hasNext()) { MethodOrMethodContext m = (MethodOrMethodContext) reachablesReader.next(); MethodPAG mpag = MethodPAG.v(pag, m.method()); mpag.build(); mpag.addToPAG(m.context()); } }
public OnFlyCallGraph(PAG pag) { this.pag = pag; CGOptions options = new CGOptions(PhaseOptions.v().getPhaseOptions("cg")); if (options.all_reachable()) { List entryPoints = new ArrayList(); entryPoints.addAll(EntryPoints.v().all()); entryPoints.addAll(EntryPoints.v().methodsOfApplicationClasses()); Scene.v().setEntryPoints(entryPoints); } callGraph = new CallGraph(); Scene.v().setCallGraph(callGraph); ContextManager cm = CallGraphBuilder.makeContextManager(callGraph); reachableMethods = Scene.v().getReachableMethods(); ofcgb = new OnFlyCallGraphBuilder(cm, reachableMethods); reachablesReader = reachableMethods.listener(); callEdges = cm.callGraph().listener(); }
public void assureAllSyncInCallGraph(Collection<JavaCriticalSection> criticalSections) { System.out.println("[assureAllSyncInCallgraph] starting"); Date start = new Date(); ReachableMethods oldReach = Scene.v().getReachableMethods(); // Collection et = EntryPoints.v().all(); // ReachableMethods reachableFromMain = new ReachableMethods(cg, et); // reachableFromMain.update(); Set<SootMethod> notInCG = new HashSet<SootMethod>(); for (JavaCriticalSection cs : criticalSections) { SootMethod m = cs.getSootMethod(); if (!oldReach.contains(m)) notInCG.add(m); } Set<SootMethod> alreadyInCG = new HashSet<SootMethod>(); for (Iterator<MethodOrMethodContext> it = oldReach.listener(); it.hasNext(); ) { alreadyInCG.add(it.next().method()); } /* * for(Iterator<?> it=cg.sourceMethods();it.hasNext();){ SootMethod m = * (SootMethod)it.next(); alreadyInCG.add(m); if(notInCG.contains(m)){ * notInCG.remove(m); } } */ // add new methods to the call graph Stack<SootMethod> worklist = new Stack<SootMethod>(); for (SootMethod m : notInCG) { worklist.push(m); } while (!worklist.isEmpty()) { SootMethod m = worklist.pop(); if (alreadyInCG.contains(m) || m == null) { continue; } alreadyInCG.add(m); Body body = m.retrieveActiveBody(); for (Unit u : body.getUnits()) { if (!(u instanceof Stmt)) { continue; } Stmt s = (Stmt) u; if (!s.containsInvokeExpr()) { continue; } InvokeExpr invoke = s.getInvokeExpr(); SootMethod declCallee = invoke.getMethod(); Collection<SootMethod> targets = new ArrayList<SootMethod>(); if (declCallee.isStatic()) { targets.add(declCallee); } else { // XXX: pay attention to reflexive call, thread call, and // etc. // Here we do not add edges for implicit targets, as these // parts of methods is not reachable // from the entry, and they will most likely to be analyzed // in a very conservative ways. InstanceInvokeExpr iie = (InstanceInvokeExpr) invoke; Local receiver = (Local) iie.getBase(); NumberedString subSig = iie.getMethodRef().getSubSignature(); if (invoke instanceof SpecialInvokeExpr) { SootMethod tgt = VirtualCalls.v().resolveSpecial((SpecialInvokeExpr) invoke, subSig, m); targets.add(tgt); } else { Type t = receiver.getType(); if (t instanceof ArrayType) { // t = RefType.v("java.lang.Object"); targets.add(declCallee); } // BottomType bug else if (t instanceof soot.jimple.toolkits.typing.fast.BottomType) { System.out.println("BottomType:" + s); } else if (t instanceof soot.NullType) { System.out.println("NullType:" + s); } else { SootClass c = ((RefType) t).getSootClass(); // Soot has a type resolving bug, and here may be // exceptions try { Set<SootMethod> callees = Scene.v().getOrMakeFastHierarchy().resolveAbstractDispatch(c, declCallee); targets.addAll(callees); } catch (Exception e) { System.out.println(e.getMessage()); } } } } for (SootMethod t : targets) { // add call edge Edge e = new Edge(m, s, t); Scene.v().getCallGraph().addEdge(e); // add to worklist if (t.isConcrete() && !alreadyInCG.contains(t)) { worklist.push(t); } } } } // infer entries for the methods not reachable from main entry List<SootMethod> entries = Scene.v().getEntryPoints(); _patchedEntries = new ArrayList<SootMethod>(notInCG); for (SootMethod m : notInCG) { // XXX there can be recursive calls, so for simple processing, all // methods not in old // call graph should be added to the entry. Checking the // non-existence of incoming edges // may miss some recursively called methods // if(!cg.edgesInto(m).hasNext()){ entries.add(m); // } } // update reachable methods Scene.v().setReachableMethods(null); }