Search in sources :

Example 1 with CallGraph

use of soot.jimple.toolkits.callgraph.CallGraph in project soot by Sable.

the class GeomPointsTo method updateCallGraph.

/**
 * Remove unreachable call targets at the virtual callsites using the up-to-date points-to information.
 */
private int updateCallGraph() {
    int all_virtual_edges = 0, n_obsoleted = 0;
    CallGraph cg = Scene.v().getCallGraph();
    ChunkedQueue<SootMethod> targetsQueue = new ChunkedQueue<SootMethod>();
    QueueReader<SootMethod> targets = targetsQueue.reader();
    Set<SootMethod> resolvedMethods = new HashSet<SootMethod>();
    // We first update the virtual callsites
    for (Iterator<Stmt> csIt = multiCallsites.iterator(); csIt.hasNext(); ) {
        Stmt callsite = csIt.next();
        Iterator<Edge> edges = cg.edgesOutOf(callsite);
        if (!edges.hasNext()) {
            csIt.remove();
            continue;
        }
        Edge anyEdge = edges.next();
        CgEdge p = edgeMapping.get(anyEdge);
        SootMethod src = anyEdge.src();
        if (!isReachableMethod(src)) {
            // The source method is no longer reachable
            // We move this callsite
            csIt.remove();
            continue;
        }
        if (!edges.hasNext()) {
            // We keep this resolved site for call graph profiling
            continue;
        }
        IVarAbstraction pn = consG.get(p.base_var);
        if (pn != null) {
            pn = pn.getRepresentative();
            // We resolve the call targets with the new points-to result
            getCallTargets(pn, src, callsite, targetsQueue);
            resolvedMethods.clear();
            while (targets.hasNext()) {
                resolvedMethods.add(targets.next());
            }
            // We delete the edges that are proven to be spurious
            while (true) {
                SootMethod tgt = anyEdge.tgt();
                if (!resolvedMethods.contains(tgt) && !anyEdge.kind().isFake()) {
                    p = edgeMapping.get(anyEdge);
                    p.is_obsoleted = true;
                }
                if (!edges.hasNext())
                    break;
                anyEdge = edges.next();
            }
        }
    }
    // We delete the spurious edges
    for (int i = 1; i < n_func; ++i) {
        // New outgoing edge list is pointed to by q
        CgEdge p = call_graph[i];
        CgEdge q = null;
        while (p != null) {
            if (vis_cg[i] == 0) {
                // If this method is unreachable, we delete all its outgoing edges
                p.is_obsoleted = true;
            }
            if (p.base_var != null) {
                ++all_virtual_edges;
            }
            CgEdge temp = p.next;
            if (p.is_obsoleted == false) {
                p.next = q;
                q = p;
            } else {
                // Update the corresponding SOOT call graph
                // ps.println("%%% Remove an call edge: " + p.toString());
                cg.removeEdge(p.sootEdge);
                // We record this obsoleted edge
                // obsoletedEdges.add(p);
                ++n_obsoleted;
            }
            p = temp;
        }
        call_graph[i] = q;
    }
    ps.printf("%d of %d virtual call edges are proved to be spurious.\n", n_obsoleted, all_virtual_edges);
    return n_obsoleted;
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) ChunkedQueue(soot.util.queue.ChunkedQueue) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint) Stmt(soot.jimple.Stmt) CallGraph(soot.jimple.toolkits.callgraph.CallGraph) SootMethod(soot.SootMethod) Edge(soot.jimple.toolkits.callgraph.Edge) CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) HashSet(java.util.HashSet)

Example 2 with CallGraph

use of soot.jimple.toolkits.callgraph.CallGraph in project soot by Sable.

the class GeomPointsTo method preprocess.

/**
 *	Read in the program facts generated by SPARK.
 *  We also construct our own call graph and pointer variables.
 */
private void preprocess() {
    int id;
    int s, t;
    // Build the call graph
    n_func = Scene.v().getReachableMethods().size() + 1;
    call_graph = new CgEdge[n_func];
    n_calls = 0;
    n_reach_spark_user_methods = 0;
    id = 1;
    QueueReader<MethodOrMethodContext> smList = Scene.v().getReachableMethods().listener();
    CallGraph soot_callgraph = Scene.v().getCallGraph();
    while (smList.hasNext()) {
        final SootMethod func = smList.next().method();
        func2int.put(func, id);
        int2func.put(id, func);
        /*
			 * We cannot identify all entry methods since some entry methods call themselves.
			 * In that case, the Soot CallGraph.isEntryMethod() function returns false.
			 */
        if (soot_callgraph.isEntryMethod(func) || func.isEntryMethod()) {
            CgEdge p = new CgEdge(Constants.SUPER_MAIN, id, null, call_graph[Constants.SUPER_MAIN]);
            call_graph[Constants.SUPER_MAIN] = p;
            n_calls++;
        }
        if (!func.isJavaLibraryMethod())
            ++n_reach_spark_user_methods;
        id++;
    }
    // Next, we scan all the call edges and rebuild the call graph in our own vocabulary
    QueueReader<Edge> edgeList = Scene.v().getCallGraph().listener();
    while (edgeList.hasNext()) {
        Edge edge = edgeList.next();
        if (edge.isClinit()) {
            continue;
        }
        SootMethod src_func = edge.src();
        SootMethod tgt_func = edge.tgt();
        s = func2int.get(src_func);
        t = func2int.get(tgt_func);
        // Create a new call edge in our own format
        CgEdge p = new CgEdge(s, t, edge, call_graph[s]);
        call_graph[s] = p;
        edgeMapping.put(edge, p);
        // We collect callsite information
        Stmt callsite = edge.srcStmt();
        if (edge.isThreadRunCall() || edge.kind().isExecutor() || edge.kind().isAsyncTask()) {
            // We don't modify the treatment to the thread run() calls
            thread_run_callsites.add(callsite);
        } else if (edge.isInstance() && !edge.isSpecial()) {
            // We try to refine the virtual callsites (virtual + interface) with multiple call targets
            InstanceInvokeExpr expr = (InstanceInvokeExpr) callsite.getInvokeExpr();
            if (expr.getMethodRef().getSignature().contains("<java.lang.Thread: void start()>")) {
                // It is a thread start function
                thread_run_callsites.add(callsite);
            } else {
                p.base_var = findLocalVarNode(expr.getBase());
                if (SootInfo.countCallEdgesForCallsite(callsite, true) > 1 && p.base_var != null) {
                    multiCallsites.add(callsite);
                }
            }
        }
        ++n_calls;
    }
    // We build the wrappers for all the pointers built by SPARK
    for (Iterator<VarNode> it = getVarNodeNumberer().iterator(); it.hasNext(); ) {
        VarNode vn = it.next();
        IVarAbstraction pn = makeInternalNode(vn);
        pointers.add(pn);
    }
    for (Iterator<AllocDotField> it = getAllocDotFieldNodeNumberer().iterator(); it.hasNext(); ) {
        AllocDotField adf = it.next();
        // Some allocdotfield is invalid, we check and remove them
        SparkField field = adf.getField();
        if (field instanceof SootField) {
            // This is an instance field of a class
            Type decType = ((SootField) field).getDeclaringClass().getType();
            Type baseType = adf.getBase().getType();
            // baseType must be a sub type of decType
            if (!castNeverFails(baseType, decType))
                continue;
        }
        IVarAbstraction pn = makeInternalNode(adf);
        pointers.add(pn);
    }
    for (Iterator<AllocNode> it = getAllocNodeNumberer().iterator(); it.hasNext(); ) {
        AllocNode obj = it.next();
        IVarAbstraction pn = makeInternalNode(obj);
        allocations.add(pn);
    }
    // The address constraints, new obj -> p
    for (Object object : allocSources()) {
        IVarAbstraction obj = makeInternalNode((AllocNode) object);
        Node[] succs = allocLookup((AllocNode) object);
        for (Node element0 : succs) {
            PlainConstraint cons = new PlainConstraint();
            IVarAbstraction p = makeInternalNode(element0);
            cons.expr.setPair(obj, p);
            cons.type = Constants.NEW_CONS;
            constraints.add(cons);
        }
    }
    // The assign constraints, p -> q
    Pair<Node, Node> intercall = new Pair<Node, Node>();
    for (Object object : simpleSources()) {
        IVarAbstraction p = makeInternalNode((VarNode) object);
        Node[] succs = simpleLookup((VarNode) object);
        for (Node element0 : succs) {
            PlainConstraint cons = new PlainConstraint();
            IVarAbstraction q = makeInternalNode(element0);
            cons.expr.setPair(p, q);
            cons.type = Constants.ASSIGN_CONS;
            intercall.setPair((VarNode) object, element0);
            cons.interCallEdges = lookupEdgesForAssignment(intercall);
            constraints.add(cons);
        }
    }
    intercall = null;
    assign2edges.clear();
    // The load constraints, p.f -> q
    for (Object object : loadSources()) {
        FieldRefNode frn = (FieldRefNode) object;
        IVarAbstraction p = makeInternalNode(frn.getBase());
        Node[] succs = loadLookup(frn);
        for (Node element0 : succs) {
            PlainConstraint cons = new PlainConstraint();
            IVarAbstraction q = makeInternalNode(element0);
            cons.f = frn.getField();
            cons.expr.setPair(p, q);
            cons.type = Constants.LOAD_CONS;
            constraints.add(cons);
        }
    }
    // The store constraints, p -> q.f
    for (Object object : storeSources()) {
        IVarAbstraction p = makeInternalNode((VarNode) object);
        Node[] succs = storeLookup((VarNode) object);
        for (Node element0 : succs) {
            PlainConstraint cons = new PlainConstraint();
            FieldRefNode frn = (FieldRefNode) element0;
            IVarAbstraction q = makeInternalNode(frn.getBase());
            cons.f = frn.getField();
            cons.expr.setPair(p, q);
            cons.type = Constants.STORE_CONS;
            constraints.add(cons);
        }
    }
    n_init_constraints = constraints.size();
    // Initialize other stuff
    low_cg = new int[n_func];
    vis_cg = new int[n_func];
    rep_cg = new int[n_func];
    indeg_cg = new int[n_func];
    scc_size = new int[n_func];
    block_num = new int[n_func];
    context_size = new long[n_func];
    max_context_size_block = new long[n_func];
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) AllocDotField(soot.jimple.spark.pag.AllocDotField) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint) SparkField(soot.jimple.spark.pag.SparkField) FieldRefNode(soot.jimple.spark.pag.FieldRefNode) ContextVarNode(soot.jimple.spark.pag.ContextVarNode) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) Node(soot.jimple.spark.pag.Node) VarNode(soot.jimple.spark.pag.VarNode) AllocNode(soot.jimple.spark.pag.AllocNode) Stmt(soot.jimple.Stmt) MethodOrMethodContext(soot.MethodOrMethodContext) Pair(soot.toolkits.scalar.Pair) ContextVarNode(soot.jimple.spark.pag.ContextVarNode) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) VarNode(soot.jimple.spark.pag.VarNode) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint) RefType(soot.RefType) Type(soot.Type) FieldRefNode(soot.jimple.spark.pag.FieldRefNode) CallGraph(soot.jimple.toolkits.callgraph.CallGraph) AllocNode(soot.jimple.spark.pag.AllocNode) SootMethod(soot.SootMethod) SootField(soot.SootField) Edge(soot.jimple.toolkits.callgraph.Edge) CgEdge(soot.jimple.spark.geom.dataRep.CgEdge)

Example 3 with CallGraph

use of soot.jimple.toolkits.callgraph.CallGraph in project soot by Sable.

the class EvalResults method checkCallGraph.

/**
 * 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();
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) Histogram(soot.jimple.spark.geom.utils.Histogram) InvokeExpr(soot.jimple.InvokeExpr) CallGraph(soot.jimple.toolkits.callgraph.CallGraph) SootMethod(soot.SootMethod) Edge(soot.jimple.toolkits.callgraph.Edge) CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt)

Example 4 with CallGraph

use of soot.jimple.toolkits.callgraph.CallGraph in project soot by Sable.

the class SootInfo method countCallEdgesForCallsite.

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;
}
Also used : CallGraph(soot.jimple.toolkits.callgraph.CallGraph) Edge(soot.jimple.toolkits.callgraph.Edge)

Example 5 with CallGraph

use of soot.jimple.toolkits.callgraph.CallGraph in project soot by Sable.

the class MultiCalledMethods method byMCalledS0.

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();
    }
}
Also used : UnitGraph(soot.toolkits.graph.UnitGraph) CompleteUnitGraph(soot.toolkits.graph.CompleteUnitGraph) CallGraph(soot.jimple.toolkits.callgraph.CallGraph) PegCallGraph(soot.jimple.toolkits.thread.mhp.pegcallgraph.PegCallGraph) FlowSet(soot.toolkits.scalar.FlowSet) SootMethod(soot.SootMethod) CompleteUnitGraph(soot.toolkits.graph.CompleteUnitGraph)

Aggregations

CallGraph (soot.jimple.toolkits.callgraph.CallGraph)11 SootMethod (soot.SootMethod)7 Edge (soot.jimple.toolkits.callgraph.Edge)7 Stmt (soot.jimple.Stmt)5 MethodOrMethodContext (soot.MethodOrMethodContext)3 CgEdge (soot.jimple.spark.geom.dataRep.CgEdge)3 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 SootClass (soot.SootClass)2 Unit (soot.Unit)2 Value (soot.Value)2 ValueBox (soot.ValueBox)2 InstanceInvokeExpr (soot.jimple.InstanceInvokeExpr)2 InvokeExpr (soot.jimple.InvokeExpr)2 PlainConstraint (soot.jimple.spark.geom.dataRep.PlainConstraint)2 LocalVarNode (soot.jimple.spark.pag.LocalVarNode)2 Targets (soot.jimple.toolkits.callgraph.Targets)2 HashMap (java.util.HashMap)1 Iterator (java.util.Iterator)1 LinkedList (java.util.LinkedList)1