Search in sources :

Example 6 with CgEdge

use of soot.jimple.spark.geom.dataRep.CgEdge 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 7 with CgEdge

use of soot.jimple.spark.geom.dataRep.CgEdge in project soot by Sable.

the class PtInsNodeGenerator method initFlowGraph.

@Override
public void initFlowGraph(GeomPointsTo ptAnalyzer) {
    int k;
    int n_legal_cons;
    int nf1, nf2;
    int code;
    CgEdge q;
    IVarAbstraction my_lhs, my_rhs;
    // Visit all the simple constraints
    n_legal_cons = 0;
    for (PlainConstraint cons : ptAnalyzer.constraints) {
        if (!cons.isActive)
            continue;
        my_lhs = cons.getLHS().getRepresentative();
        my_rhs = cons.getRHS().getRepresentative();
        nf1 = ptAnalyzer.getMethodIDFromPtr(my_lhs);
        nf2 = ptAnalyzer.getMethodIDFromPtr(my_rhs);
        // Test how many globals are in this constraint
        code = ((nf1 == Constants.SUPER_MAIN ? 1 : 0) << 1) | (nf2 == Constants.SUPER_MAIN ? 1 : 0);
        switch(cons.type) {
            case Constants.NEW_CONS:
                // We directly add the objects to the points-to set
                my_rhs.add_points_to_3((AllocNode) my_lhs.getWrappedNode(), nf2 == Constants.SUPER_MAIN ? 0 : 1, nf1 == Constants.SUPER_MAIN ? 0 : 1, nf2 == Constants.SUPER_MAIN ? ptAnalyzer.context_size[nf1] : ptAnalyzer.context_size[nf2]);
                // Enqueue to the worklist
                ptAnalyzer.getWorklist().push(my_rhs);
                break;
            case Constants.ASSIGN_CONS:
                // The core part of any context sensitive algorithms
                if (cons.interCallEdges != null) {
                    // Inter-procedural assignment
                    for (Iterator<Edge> it = cons.interCallEdges.iterator(); it.hasNext(); ) {
                        Edge sEdge = it.next();
                        q = ptAnalyzer.getInternalEdgeFromSootEdge(sEdge);
                        if (q.is_obsoleted == true) {
                            continue;
                        }
                        if (nf2 == q.t) {
                            // The receiver is a local, while the sender is perhaps not
                            if (nf1 == Constants.SUPER_MAIN) {
                                my_lhs.add_simple_constraint_3(my_rhs, 0, q.map_offset, ptAnalyzer.max_context_size_block[q.s]);
                            } else {
                                // We should treat the self recursive calls specially
                                if (q.s == q.t) {
                                    my_lhs.add_simple_constraint_3(my_rhs, 1, 1, ptAnalyzer.context_size[nf1]);
                                } else {
                                    for (k = 0; k < ptAnalyzer.block_num[nf1]; ++k) {
                                        my_lhs.add_simple_constraint_3(my_rhs, k * ptAnalyzer.max_context_size_block[nf1] + 1, q.map_offset, ptAnalyzer.max_context_size_block[nf1]);
                                    }
                                }
                            }
                        } else {
                            if (q.s == q.t) {
                                my_lhs.add_simple_constraint_3(my_rhs, 1, 1, ptAnalyzer.context_size[nf2]);
                            } else {
                                for (k = 0; k < ptAnalyzer.block_num[nf2]; ++k) {
                                    my_lhs.add_simple_constraint_3(my_rhs, q.map_offset, k * ptAnalyzer.max_context_size_block[nf2] + 1, ptAnalyzer.max_context_size_block[nf2]);
                                }
                            }
                        }
                    }
                } else {
                    // Intraprocedural
                    // And, assignment involves global variable goes here. By
                    // definition, global variables belong to SUPER_MAIN.
                    // By the Jimple IR, not both sides are global variables
                    my_lhs.add_simple_constraint_3(my_rhs, nf1 == Constants.SUPER_MAIN ? 0 : 1, nf2 == Constants.SUPER_MAIN ? 0 : 1, nf1 == Constants.SUPER_MAIN ? ptAnalyzer.context_size[nf2] : ptAnalyzer.context_size[nf1]);
                }
                break;
            case Constants.LOAD_CONS:
                // lhs is always a local
                // rhs = lhs.f
                cons.code = full_convertor[code];
                cons.otherSide = my_rhs;
                my_lhs.put_complex_constraint(cons);
                break;
            case Constants.STORE_CONS:
                // rhs is always a local
                // rhs.f = lhs
                cons.code = full_convertor[code];
                cons.otherSide = my_lhs;
                my_rhs.put_complex_constraint(cons);
                break;
            default:
                throw new RuntimeException("Invalid node type");
        }
        ++n_legal_cons;
    }
    ptAnalyzer.ps.printf("Only %d (%.1f%%) constraints are needed for this run.\n", n_legal_cons, ((double) n_legal_cons / ptAnalyzer.n_init_constraints) * 100);
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint) IVarAbstraction(soot.jimple.spark.geom.geomPA.IVarAbstraction) CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) Edge(soot.jimple.toolkits.callgraph.Edge) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint)

Example 8 with CgEdge

use of soot.jimple.spark.geom.dataRep.CgEdge in project soot by Sable.

the class GeomQueries method kCFA.

/**
 * Standard K-CFA querying for arbitrary K.
 *
 * @param callEdgeChain: last K call edges leading to the method that contains l. callEdgeChain[0] is the farthest call edge in the chain.
 * @param l: the querying pointer
 * @param visitor: the querying result container
 * @return false, l does not have points-to information under the given context
 */
@SuppressWarnings("rawtypes")
public boolean kCFA(Edge[] callEdgeChain, Local l, PtSensVisitor visitor) {
    // Prepare for initial contexts
    SootMethod firstMethod = callEdgeChain[0].src();
    int firstMethodID = geomPTA.getIDFromSootMethod(firstMethod);
    if (firstMethodID == -1)
        return false;
    // Obtain the internal representation for querying pointer
    LocalVarNode vn = geomPTA.findLocalVarNode(l);
    if (vn == null) {
        // Normally this could not happen, perhaps it's a bug
        return false;
    }
    IVarAbstraction pn = geomPTA.findInternalNode(vn);
    if (pn == null) {
        // This pointer is no longer reachable
        return false;
    }
    pn = pn.getRepresentative();
    if (!pn.hasPTResult())
        return false;
    SootMethod sm = vn.getMethod();
    if (geomPTA.getIDFromSootMethod(sm) == -1)
        return false;
    // Iterate the call edges and compute the contexts mapping iteratively
    visitor.prepare();
    long L = 1;
    for (int i = 0; i < callEdgeChain.length; ++i) {
        Edge sootEdge = callEdgeChain[i];
        CgEdge ctxt = geomPTA.getInternalEdgeFromSootEdge(sootEdge);
        if (ctxt == null || ctxt.is_obsoleted == true)
            return false;
        // Following searching procedure works for both methods in SCC and out of SCC
        // with blocking scheme or without blocking scheme
        int caller = geomPTA.getIDFromSootMethod(sootEdge.src());
        // We obtain the block that contains current offset L
        long block_size = max_context_size_block[rep_cg[caller]];
        long in_block_offset = (L - 1) % block_size;
        // Transfer to the target block with the same in-block offset
        L = ctxt.map_offset + in_block_offset;
    }
    long ctxtLength = max_context_size_block[rep_cg[firstMethodID]];
    long R = L + ctxtLength;
    pn.get_all_context_sensitive_objects(L, R, visitor);
    visitor.finish();
    return visitor.numOfDiffObjects() != 0;
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) SootMethod(soot.SootMethod) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) Edge(soot.jimple.toolkits.callgraph.Edge)

Example 9 with CgEdge

use of soot.jimple.spark.geom.dataRep.CgEdge in project soot by Sable.

the class GeomQueries method dfsScanSubgraph.

/**
 * Retrieve the subgraph from s->target.
 * An edge s->t is included in the subgraph iff target is reachable from t.
 * @param s
 * @param target
 * @return
 */
protected boolean dfsScanSubgraph(int s, int target) {
    int rep_s = rep_cg[s];
    int rep_target = rep_cg[target];
    if (rep_s == rep_target)
        return true;
    s = rep_s;
    boolean reachable = false;
    // We only traverse the SCC representatives
    CgEdge p = call_graph[s];
    while (p != null) {
        int t = p.t;
        int rep_t = rep_cg[t];
        if (in_degree[rep_t] != 0 || (top_rank[rep_t] <= top_rank[rep_target] && dfsScanSubgraph(t, target) == true)) {
            in_degree[rep_t]++;
            reachable = true;
        }
        p = p.next;
    }
    return reachable;
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge)

Example 10 with CgEdge

use of soot.jimple.spark.geom.dataRep.CgEdge in project soot by Sable.

the class GeomQueries method contextsGoBy.

/**
 * Answer contexts-go-by query.
 *
 * Usually, users specify the last K paths as the context. We call it k-CFA context.
 * However, k-CFA is too restrictive.
 * In contexts-go-by query, user specifies arbitrary call edge in the call graph.
 * The query searches for all contexts induced by the specified call edge and collect points-to results under these contexts.
 *
 * @param sootEdge: the specified context edge in soot edge format
 * @param l: the querying pointer
 * @param visitor: container for querying result
 * @return false, l does not have points-to information under the contexts induced by the given call edge
 */
@SuppressWarnings("rawtypes")
public boolean contextsGoBy(Edge sootEdge, Local l, PtSensVisitor visitor) {
    // Obtain the internal representation of specified context
    CgEdge ctxt = geomPTA.getInternalEdgeFromSootEdge(sootEdge);
    if (ctxt == null || ctxt.is_obsoleted == true)
        return false;
    // Obtain the internal representation for querying pointer
    LocalVarNode vn = geomPTA.findLocalVarNode(l);
    if (vn == null) {
        // Normally this could not happen, perhaps it's a bug
        return false;
    }
    IVarAbstraction pn = geomPTA.findInternalNode(vn);
    if (pn == null) {
        // This pointer is no longer reachable
        return false;
    }
    pn = pn.getRepresentative();
    if (!pn.hasPTResult())
        return false;
    // Obtain the internal representation of the method that encloses the querying pointer
    SootMethod sm = vn.getMethod();
    int target = geomPTA.getIDFromSootMethod(sm);
    if (target == -1)
        return false;
    // Start call graph traversal
    long L = ctxt.map_offset;
    long R = L + max_context_size_block[rep_cg[ctxt.s]];
    assert L < R;
    visitor.prepare();
    prepareIntervalPropagations();
    if (propagateIntervals(ctxt.t, L, R, target)) {
        // We calculate the points-to results
        ContextsCollector targetContexts = contextsForMethods[target];
        for (SimpleInterval si : targetContexts.bars) {
            assert si.L < si.R;
            pn.get_all_context_sensitive_objects(si.L, si.R, visitor);
        }
        // Reset
        targetContexts.clear();
    }
    visitor.finish();
    return visitor.numOfDiffObjects() != 0;
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) SootMethod(soot.SootMethod) SimpleInterval(soot.jimple.spark.geom.dataRep.SimpleInterval) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) ContextsCollector(soot.jimple.spark.geom.dataMgr.ContextsCollector)

Aggregations

CgEdge (soot.jimple.spark.geom.dataRep.CgEdge)17 PlainConstraint (soot.jimple.spark.geom.dataRep.PlainConstraint)9 SootMethod (soot.SootMethod)8 Edge (soot.jimple.toolkits.callgraph.Edge)8 LocalVarNode (soot.jimple.spark.pag.LocalVarNode)5 IVarAbstraction (soot.jimple.spark.geom.geomPA.IVarAbstraction)4 Stmt (soot.jimple.Stmt)3 ContextsCollector (soot.jimple.spark.geom.dataMgr.ContextsCollector)3 AllocNode (soot.jimple.spark.pag.AllocNode)3 CallGraph (soot.jimple.toolkits.callgraph.CallGraph)3 HashSet (java.util.HashSet)2 RefType (soot.RefType)2 Type (soot.Type)2 SimpleInterval (soot.jimple.spark.geom.dataRep.SimpleInterval)2 ContextVarNode (soot.jimple.spark.pag.ContextVarNode)2 LinkedList (java.util.LinkedList)1 Random (java.util.Random)1 AnySubType (soot.AnySubType)1 ArrayType (soot.ArrayType)1 FastHierarchy (soot.FastHierarchy)1