private static void myDebug(String message) { logger.info("start debug... " + message); { CallGraph cg = Scene.v().getCallGraph(); Iterator<Edge> edges = cg .edgesOutOf(Scene .v() .getMethod( "<android.accounts.IAccountAuthenticatorResponse$Stub$Proxy: void onError(int,java.lang.String)>")); while (edges.hasNext()) { Edge e = edges.next(); logger.info("edge: " + e); } } logger.info("end debug... " + message); }
private void initIFDS() { Scene.v().setCallGraph(new CallGraph()); this.jumpFunctions = new JumpFunctions<Unit, FlowAbstraction, IFDSSolver.BinaryDomain>(IFDSSolver.getAllTop()); this.endSum = HashBasedTable.create(); this.inc = HashBasedTable.create(); this.icfg = new JitIcfg(new ArrayList<SootMethod>()) { @Override public Set<SootMethod> getCalleesOfCallAt(Unit u) { if (currentTask != null) return currentTask.calleesOfCallAt(u); else // Empty by default (same behaviour as L1) return new HashSet<SootMethod>(); } }; this.reporter.setIFDS(icfg, jumpFunctions); }
public static void searchPermissions(CallGraph cg, Map<SootMethod, Set<String>> methodToPermissionSet) { ForwardSearch.methodToPermissionSet = methodToPermissionSet; // Set<SootMethod> checkGEOnePermn = new HashSet<SootMethod>(); // methods which check at least one permission // for (SootMethod sm: methodToPermissionSet.keySet()) { // if (methodToPermissionSet.get(sm).size() == 0) // continue; // checkGEOnePermn.add(sm); // alreadyComputed.add(sm); // System.out.println("already computed: "+ sm); // } SootMethod main = Scene.v().getMainMethod(); Stack<SootMethod> stack = new Stack<SootMethod>(); stack.push(main); search(cg, main, stack, 0); computeEntryPointPermissions(); }
public static Set<Class> getDependencies(Scene scene, CallGraph callGraph, Class<?> clazz) { Set<Class> dependencies = Sets.newHashSet(); SootClass sootClass = scene.getSootClass(clazz.getName()); for(SootMethod method: sootClass.getMethods()) if(!method.isPhantom()) callGraph.edgesInto(method).forEachRemaining(edge -> { try { dependencies.add(Class.forName(edge.getSrc().method().getDeclaringClass().getName())); } catch (ClassNotFoundException e) { log.info(String.format("Class not found: %s", edge.getSrc().method().getDeclaringClass().getName())); } }); return dependencies; }
private List<SootMethod> findTargetMethods(Unit unit, CallGraph cg, boolean canBeNullList, boolean canBeNative){ List<SootMethod> target = new ArrayList<SootMethod>(); Iterator<Edge> it = cg.edgesOutOf(unit); while (it.hasNext()){ Edge edge = it.next(); SootMethod targetMethod = edge.tgt(); if (targetMethod.isNative() && !canBeNative ) continue; if (edge.kind() == Kind.CLINIT ) continue; target.add(targetMethod); } if (target.size() < 1 && !canBeNullList){ throw new RuntimeException("No target method for: "+unit); } return target; }
/** * Do a recursion analysis. We even look at recursive thread generations. * @param cba The callback resolver for thread calls. * @param cg The callgraph. */ RecAnalysis(CallbackResolver cba, CallGraph cg) { int size = 0; Scene scene = Scene.v(); allMethods = new HashSet <SootMethod>(); for (SootClass cl : (Collection <SootClass>) scene.getClasses()) { for (SootMethod m : (Collection <SootMethod>) cl.getMethods()) { size++; allMethods.add(m); } } graph = new CGraph(size,cg,cba); tarjAnalysis = new Tarjan <SootMethod>(graph); }
public List<List<SootMethod>> executeTarjan(CallGraph graph){ scc.clear(); index = 0; stack.clear(); SootMethod mainMethod = Scene.v().getMethod("<MainClass: void main(java.lang.String[])>"); tarjan(mainMethod, graph); return scc; }
public static void main(String[] args) { List<String> argsList = new ArrayList<String>(Arrays.asList(args)); argsList.addAll(Arrays.asList(new String[]{ "-w", "-main-class", "testers.CallGraphs",//main-class "testers.CallGraphs",//argument classes "testers.A" // })); PackManager.v().getPack("wjtp").add(new Transform("wjtp.myTrans", new SceneTransformer() { @Override protected void internalTransform(String phaseName, Map options) { CHATransformer.v().transform(); SootClass a = Scene.v().getSootClass("testers.A"); SootMethod src = Scene.v().getMainClass().getMethodByName("doStuff"); CallGraph cg = Scene.v().getCallGraph(); Iterator<MethodOrMethodContext> targets = new Targets(cg.edgesOutOf(src)); while (targets.hasNext()) { SootMethod tgt = (SootMethod)targets.next(); System.out.println(src + " may call " + tgt); } } })); args = argsList.toArray(new String[0]); soot.Main.main(args); }
public CallGraph getCallGraph() { if(!hasCallGraph()) { throw new RuntimeException( "No call graph present in Scene. Maybe you want Whole Program mode (-w)." ); } return activeCallGraph; }
public static int countCallEdgesForCallsite(Stmt callsite, boolean stopForMutiple) { CallGraph cg = Scene.v().getCallGraph(); int count = 0; for ( Iterator<Edge> it = cg.edgesOutOf(callsite); it.hasNext(); ) { it.next(); ++count; if ( stopForMutiple && count > 1) break; } return count; }
protected HashMutableDirectedGraph<EquivalentValue> getInvokeInfoFlowSummary( InvokeExpr ie, Stmt is, SootMethod context) { // get the data flow graph for each possible target of ie, // then combine them conservatively and return the result. HashMutableDirectedGraph<EquivalentValue> ret = null; SootMethodRef methodRef = ie.getMethodRef(); String subSig = methodRef.resolve().getSubSignature(); CallGraph cg = Scene.v().getCallGraph(); for(Iterator<Edge> edges = cg.edgesOutOf(is); edges.hasNext();) { Edge e = edges.next(); SootMethod target = e.getTgt().method(); // Verify that this target is an implementation of the method we intend to call, // and not just a class initializer or other unintended control flow. if(target.getSubSignature().equals(subSig)) { HashMutableDirectedGraph<EquivalentValue> ifs = getMethodInfoFlowSummary( target, context.getDeclaringClass().isApplicationClass()); if(ret == null) ret = ifs; else { for(EquivalentValue node : ifs.getNodes()) { if(!ret.containsNode(node)) ret.addNode(node); for(EquivalentValue succ : ifs.getSuccsOf(node)) ret.addEdge(node, succ); } } } } return ret; // return getMethodInfoFlowSummary(methodRef.resolve(), context.getDeclaringClass().isApplicationClass()); }
public MultiRunStatementsFinder(UnitGraph g, SootMethod sm, Set<SootMethod> multiCalledMethods, CallGraph cg) { super(g); nodeToIndex = new HashMap<Object, Integer>(); // System.out.println("===entering MultiObjectAllocSites=="); doAnalysis(); //testMultiObjSites(sm); findMultiCalledMethodsIntra(multiCalledMethods, cg); // testMultiObjSites(sm); }
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(); } }
public static Set<Class> getTransientDependencies(Scene scene, CallGraph callGraph, Class<?> clazz) { Queue<Class> pendingClasses = ArrayUtilities.newArrayDeque(clazz); Set<Class> classes = Sets.newHashSet(); while(!pendingClasses.isEmpty()) { Set<Class> newClasses = getDependencies(scene, callGraph, pendingClasses.poll()) .stream() .filter(c -> !classes.contains(c)) .collect(Collectors.toSet()); classes.addAll(newClasses); pendingClasses.addAll(newClasses); } return classes; }
private void handleInvokeExpr(InvokeExpr ie, Stmt is) { // if(is.toString().contains("hashCode")) // System.out.println(); CallGraph cg = Scene.v().getCallGraph(); for(Iterator<Edge> edges = cg.edgesOutOf(is); edges.hasNext();) { Edge e = edges.next(); SootMethod target = e.getTgt().method(); //if(method.getDeclaringClass().isApplicationClass()) if(!Util.skipPackage(target.getDeclaringClass().getPackageName())) { //SootMethodRef methodRef = ie.getMethodRef(); //String subSig = methodRef.resolve().getSubSignature();//MAY NOT BE SOUND // Verify that this target is an implementation of the method we intend to call, // and not just a class initializer or other unintended control flow. //if(target.getSubSignature().equals(subSig)) { analyze(target); } } } }
public MultiRunStatementsFinderX(UnitGraph g, SootMethod sm, Set<SootMethod> multiCalledMethods, CallGraph cg) { super(g); nodeToIndex = new HashMap<Object, Integer>(); // System.out.println("===entering MultiObjectAllocSites=="); doAnalysis(); //testMultiObjSites(sm); findMultiCalledMethodsIntra(multiCalledMethods, cg); // testMultiObjSites(sm); }
private void byMCalledS0(PegCallGraphX pcg) { Iterator it = pcg.iterator(); while (it.hasNext()){ SootMethod sm = (SootMethod)it.next(); UnitGraph graph = new CompleteUnitGraph(sm.getActiveBody()); CallGraph callGraph = Scene.v().getCallGraph(); MultiRunStatementsFinderX finder = new MultiRunStatementsFinderX(graph, sm, multiCalledMethods, callGraph); FlowSet fs = finder.getMultiRunStatements(); } }
private static void visitAncestors(CallGraph cg, Set<Edge> seen, Deque<SootMethod> stack, Visitor visitor, SootMethod m) { Iterator <Edge> it = cg.edgesInto(m); stack.push(m); while(it.hasNext()) { Edge e = it.next(); if (seen.contains(e)) continue; seen.add(e); visitor.visit(e,stack); visitAncestors(cg, seen, stack, visitor, e.src()); } stack.pop(); }
private static void search(CallGraph cg, SootMethod l, Stack<SootMethod> stack, int depth) { logger.debug(" <"+ depth +"> propagate from "+ l); if (depth == 1) currentWrapper = l; if (depth == 2) { currentEntryPoint = l; if (currentEntryPoint.toString().contains("GenerationGG") || //currentEntryPoint.toString().contains("init>") || currentEntryPoint.toString().contains("ServicesInit:")) { } else { if (!currentEntryPoint.toString().contains("DumbClass:")) { EntryPointKey epk = new EntryPointKey(currentWrapper, currentEntryPoint); entryPointsToPermissionSet.put(epk, null); } } } if (alreadyComputed.contains(l)) { addPermissionsToStack(stack, l); return; } Iterator<Edge> it = cg.edgesOutOf(l); while (it.hasNext()) { Edge e = it.next(); SootMethod outMethod = e.tgt(); if (outMethod.toString().equals(l.toString())){ logger.warn("outMethod same as l: "+ l); continue; } if (stack.contains(outMethod)) throw new RuntimeException("cycle in stack!\n" + outMethod +"\n"+ Util.printStack(stack)); addPermissionsToStack(stack, outMethod); stack.push(outMethod); search(cg, outMethod, stack, depth+1); stack.pop(); } alreadyComputed.add(l); if (!methodToPermissionSet.containsKey(l)) methodToPermissionSet.put(l, new HashSet<String>()); }
public OutputGraph(CallGraph cg) { this.cg = cg; }
public void setCallGraph(CallGraph cg) { reachableMethods = null; activeCallGraph = cg; }
/** * Report the virtual callsites resolution result for the user's code. */ public void checkCallGraph() { int[] limits = new int[] { 1, 2, 4, 8 }; evalRes.total_call_edges = new Histogram(limits); CallGraph cg = Scene.v().getCallGraph(); for ( Stmt callsite : ptsProvider.multiCallsites ) { Iterator<Edge> edges = cg.edgesOutOf(callsite); if ( !edges.hasNext() ) continue; evalRes.n_callsites++; // get an edge Edge anyEdge = edges.next(); SootMethod src = anyEdge.src(); if ( !ptsProvider.isReachableMethod(src) || !ptsProvider.isValidMethod(src) ) continue; // get the base pointer CgEdge p = ptsProvider.getInternalEdgeFromSootEdge(anyEdge); LocalVarNode vn = (LocalVarNode)p.base_var; // test the call graph int edge_cnt = 1; while ( edges.hasNext() ) { ++edge_cnt; edges.next(); } evalRes.n_geom_call_edges += edge_cnt; if ( edge_cnt == 1 ) ++evalRes.n_geom_solved_all; // test app method if ( !src.isJavaLibraryMethod() ) { InvokeExpr ie = callsite.getInvokeExpr(); if ( edge_cnt == 1 ) { ++evalRes.n_geom_solved_app; if ( ptsProvider.getOpts().verbose() ) { outputer.println(); outputer.println("<<<<<<<<< Additional Solved Call >>>>>>>>>>"); outputer.println(src.toString()); outputer.println(ie.toString()); } } else { // We try to test if this callsite is solvable // under some contexts Histogram call_edges = new Histogram(limits); test_1cfa_call_graph(vn, src, ie.getMethod(), call_edges); evalRes.total_call_edges.merge(call_edges); call_edges = null; } evalRes.n_geom_user_edges += edge_cnt; evalRes.n_user_callsites++; } } ptsProvider.ps.println(); ptsProvider.ps.println("--------> Virtual Callsites Evaluation <---------"); ptsProvider.ps.printf("Total virtual callsites (app code): %d (%d)\n", evalRes.n_callsites, evalRes.n_user_callsites); ptsProvider.ps.printf("Total virtual call edges (app code): %d (%d)\n", evalRes.n_geom_call_edges, evalRes.n_geom_user_edges); ptsProvider.ps.printf("Virtual callsites additionally solved by geomPTA compared to SPARK (app code) = %d (%d)\n", evalRes.n_geom_solved_all, evalRes.n_geom_solved_app); evalRes.total_call_edges.printResult(ptsProvider.ps, "Testing of unsolved callsites on 1-CFA call graph: "); if (ptsProvider.getOpts().verbose()) ptsProvider.outputNotEvaluatedMethods(); }
/** * Computes the set of {@link EquivalentValue}s of all field references that are used * in this method but not set by the method or any method transitively called by this method. */ private Set<Value> trackableFields() { Set<Value> usedFieldRefs = new HashSet<Value>(); //add all field references that are in use boxes for (Unit unit : this.graph) { Stmt s = (Stmt) unit; List<ValueBox> useBoxes = s.getUseBoxes(); for (ValueBox useBox : useBoxes) { Value val = useBox.getValue(); if(val instanceof FieldRef) { FieldRef fieldRef = (FieldRef) val; if(fieldRef.getType() instanceof RefLikeType) usedFieldRefs.add(new EquivalentValue(fieldRef)); } } } //prune all fields that are written to if(!usedFieldRefs.isEmpty()) { if(!Scene.v().hasCallGraph()) { throw new IllegalStateException("No call graph found!"); } CallGraph cg = Scene.v().getCallGraph(); ReachableMethods reachableMethods = new ReachableMethods(cg,Collections.<MethodOrMethodContext>singletonList(container)); reachableMethods.update(); for (Iterator<MethodOrMethodContext> iterator = reachableMethods.listener(); iterator.hasNext();) { SootMethod m = (SootMethod) iterator.next(); if(m.hasActiveBody() && //exclude static initializer of same class (assume that it has already been executed) !(m.getName().equals(SootMethod.staticInitializerName) && m.getDeclaringClass().equals(container.getDeclaringClass()))) { for (Unit u : m.getActiveBody().getUnits()) { List<ValueBox> defBoxes = u.getDefBoxes(); for (ValueBox defBox : defBoxes) { Value value = defBox.getValue(); if(value instanceof FieldRef) { usedFieldRefs.remove(new EquivalentValue(value)); } } } } } } return usedFieldRefs; }
@Override protected void internalTransform(String phaseName, @SuppressWarnings("rawtypes") Map options) { PropagationTimers.v().totalTimer.start(); PropagationTimers.v().misc.start(); StringValueAnalysis.initialize(); JimpleBasedInterproceduralCFG iCfg = new PropagationIcfg(); AnalysisParameters.v().setIcfg(iCfg); PropagationProblem problem = new PropagationProblem(iCfg); for (SootMethod ep : Scene.v().getEntryPoints()) { if (ep.isConcrete()) { problem.getInitialSeeds().add(ep.getActiveBody().getUnits().getFirst()); } } int iterationCounter = 0; PropagationSolver solver = null; while (iterationCounter < MAX_ITERATIONS) { IterationSolver.v().initialize(solver); PropagationTimers.v().misc.end(); PropagationTimers.v().problemGeneration.start(); solver = new PropagationSolver(problem); PropagationTimers.v().problemGeneration.end(); PropagationTimers.v().ideSolution.start(); logger.info("Solving propagation problem (iteration " + iterationCounter + ")"); solver.solve(); PropagationTimers.v().ideSolution.end(); PropagationTimers.v().misc.start(); if (!AnalysisParameters.v().isIterative() || IterationSolver.v().hasFoundFixedPoint()) { iterationCounter = MAX_ITERATIONS; } else { ++iterationCounter; } } PropagationTimers.v().misc.end(); logger.info("Reached a fixed point"); Results.addResult(resultBuilder.buildResult(solver)); PropagationTimers.v().totalTimer.end(); if (logger.isDebugEnabled()) { CallGraph cg = Scene.v().getCallGraph(); Iterator<Edge> it = cg.listener(); while (it.hasNext()) { soot.jimple.toolkits.callgraph.Edge e = (soot.jimple.toolkits.callgraph.Edge) it.next(); logger.debug("" + e.src() + e.srcStmt() + " =" + e.kind() + "=> " + e.tgt()); } if (printer != null) { printer.print(solver); } } }
public SootMethod appendNonComponents(SootMethod mainMethod) { Set<String> coveredMethods = new HashSet<String>(); CallGraph cg = Scene.v().getCallGraph(); for (Iterator<Edge> iter = cg.iterator(); iter.hasNext(); ) { Edge edge = iter.next(); coveredMethods.add(edge.src().getSignature()); coveredMethods.add(edge.tgt().getSignature()); } Chain<SootClass> sootClasses = Scene.v().getApplicationClasses(); for (Iterator<SootClass> iter = sootClasses.iterator(); iter.hasNext();) { SootClass sc = iter.next(); List<SootMethod> methodList = sc.getMethods(); for (SootMethod sm : methodList) { if (sm.getDeclaringClass().getName().startsWith("android.support")) { continue; } if (sc.isPhantom() || ! sm.isConcrete()) { continue; } if (sm.getName().equals("<init>") || sm.getName().equals("<clinit>")) { continue; } if (coveredMethods.contains(sm.getSignature())) { //Already covered. continue; } mainMethod = addMethod(mainMethod, sm.getSignature()); } } return mainMethod; }
public ThreadAnalysis(CallGraph cg) { callGraph=cg; threadsEntryMethod=new LinkedList<SootMethod>(); }
/** * @param size the number of methods. * @param cg the regular callgraph computed by Soot * @param cba The callback resolver to use to cross thread calls for example */ CGraph(int size, CallGraph cg, CallbackResolver cba) { this.size = size; this.cg = cg; this.cba = cba; }