Search in sources :

Example 1 with CgEdge

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

the class GeomPointsTo method callGraphDFS.

/**
 * Using Tarjan's algorithm to contract the SCCs.
 */
private void callGraphDFS(int s) {
    int t;
    CgEdge p;
    vis_cg[s] = low_cg[s] = pre_cnt++;
    queue_cg.addLast(s);
    p = call_graph[s];
    while (p != null) {
        t = p.t;
        if (vis_cg[t] == 0)
            callGraphDFS(t);
        if (low_cg[t] < low_cg[s])
            low_cg[s] = low_cg[t];
        p = p.next;
    }
    if (low_cg[s] < vis_cg[s]) {
        scc_size[s] = 1;
        return;
    }
    scc_size[s] = queue_cg.size();
    do {
        t = queue_cg.getLast();
        queue_cg.removeLast();
        rep_cg[t] = s;
        low_cg[t] += n_func;
    } while (s != t);
    scc_size[s] -= queue_cg.size();
    if (scc_size[s] > max_scc_size) {
        max_scc_size = scc_size[s];
        max_scc_id = s;
    }
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint)

Example 2 with CgEdge

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

the class GeomPointsTo method buildRevCallGraph.

/**
 * The reversed call graph might be used by evaluating queries.
 */
private void buildRevCallGraph() {
    rev_call_graph = new HashMap<Integer, LinkedList<CgEdge>>();
    for (int i = 0; i < n_func; ++i) {
        CgEdge p = call_graph[i];
        while (p != null) {
            LinkedList<CgEdge> list = rev_call_graph.get(p.t);
            if (list == null) {
                list = new LinkedList<CgEdge>();
                rev_call_graph.put(p.t, list);
            }
            list.add(p);
            p = p.next;
        }
    }
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) LinkedList(java.util.LinkedList) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint)

Example 3 with CgEdge

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

the class GeomPointsTo method reachingObjects.

/*
	 * Currently, we only accept one call unit context (1CFA).
	 * For querying K-CFA (K >1), please see GeomQueries.contextsByCallChain
	 */
@Override
public PointsToSet reachingObjects(Context c, Local l) {
    if (!hasExecuted)
        return super.reachingObjects(c, l);
    if (hasTransformed || !(c instanceof Unit))
        return reachingObjects(l);
    LocalVarNode vn = findLocalVarNode(l);
    if (vn == null)
        return EmptyPointsToSet.v();
    // Lookup the context sensitive points-to information for this pointer
    IVarAbstraction pn = consG.get(vn);
    if (pn == null)
        return vn.getP2Set();
    pn = pn.getRepresentative();
    // Obtain the context sensitive points-to result
    SootMethod callee = vn.getMethod();
    Edge e = Scene.v().getCallGraph().findEdge((Unit) c, callee);
    if (e == null)
        return vn.getP2Set();
    // Compute the contexts interval
    CgEdge myEdge = getInternalEdgeFromSootEdge(e);
    if (myEdge == null)
        return vn.getP2Set();
    long low = myEdge.map_offset;
    long high = low + max_context_size_block[myEdge.s];
    // Lookup the cache
    ContextVarNode cvn = vn.context(c);
    if (cvn != null) {
        PointsToSetInternal ans = cvn.getP2Set();
        if (ans != EmptyPointsToSet.v())
            return ans;
    } else {
        // Create a new context sensitive variable
        // The points-to vector is set to empty at start
        cvn = makeContextVarNode(vn, c);
    }
    // Fill
    PointsToSetInternal ptset = cvn.makeP2Set();
    for (AllocNode an : pn.get_all_points_to_objects()) {
        if (pn.pointer_interval_points_to(low, high, an))
            ptset.add(an);
    }
    return ptset;
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) AllocNode(soot.jimple.spark.pag.AllocNode) PointsToSetInternal(soot.jimple.spark.sets.PointsToSetInternal) SootMethod(soot.SootMethod) ContextVarNode(soot.jimple.spark.pag.ContextVarNode) Unit(soot.Unit) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) Edge(soot.jimple.toolkits.callgraph.Edge) CgEdge(soot.jimple.spark.geom.dataRep.CgEdge)

Example 4 with CgEdge

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

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

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