Search in sources :

Example 11 with CgEdge

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

the class GeomPointsTo method markReachableMethods.

/**
 * Scan the call graph and mark the reachable methods.
 */
private void markReachableMethods() {
    int ans = 0;
    CgEdge p;
    for (int i = 0; i < n_func; ++i) vis_cg[i] = 0;
    queue_cg.clear();
    queue_cg.add(Constants.SUPER_MAIN);
    vis_cg[Constants.SUPER_MAIN] = 1;
    while (queue_cg.size() > 0) {
        int s = queue_cg.removeFirst();
        p = call_graph[s];
        while (p != null) {
            int t = p.t;
            if (vis_cg[t] == 0) {
                queue_cg.add(t);
                vis_cg[t] = 1;
                ++ans;
            }
            p = p.next;
        }
    }
    n_reach_methods = ans;
    // Scan again to remove unreachable methods
    ans = 0;
    for (int i = 1; i < n_func; ++i) {
        SootMethod sm = int2func.get(i);
        if (vis_cg[i] == 0) {
            func2int.remove(sm);
            int2func.remove(i);
        } else {
            if (!sm.isJavaLibraryMethod())
                ++ans;
        }
    }
    n_reach_user_methods = ans;
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) SootMethod(soot.SootMethod) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint)

Example 12 with CgEdge

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

the class GeomPointsTo method encodeContexts.

/**
 *  Build a call graph, merge the SCCs and name the contexts.
 *  Also permit clients to decide whether to connect the disjoint parts in the call graph or not.
 */
private void encodeContexts(boolean connectMissedEntries) {
    int i, j;
    int n_reachable = 0, n_scc_reachable = 0;
    int n_full = 0;
    long max_contexts = Long.MIN_VALUE;
    Random rGen = new Random();
    pre_cnt = 1;
    max_scc_size = 1;
    for (i = 0; i < n_func; ++i) {
        vis_cg[i] = 0;
        indeg_cg[i] = 0;
        max_context_size_block[i] = 0;
    }
    // We only consider all the methods which are reachable from SUPER_MAIN
    queue_cg.clear();
    callGraphDFS(Constants.SUPER_MAIN);
    if (connectMissedEntries) {
        // We also scan rest of the functions
        for (i = Constants.SUPER_MAIN + 1; i < n_func; ++i) if (vis_cg[i] == 0)
            callGraphDFS(i);
    }
    // And, we classify the call edges into SCC/non-SCC edges
    for (i = 0; i < n_func; ++i) {
        if (vis_cg[i] == 0)
            continue;
        CgEdge p = call_graph[i];
        while (p != null) {
            // Only count an edge that links two functions in the same SCC
            if (rep_cg[i] == rep_cg[p.t]) {
                p.scc_edge = true;
            } else {
                p.scc_edge = false;
                ++indeg_cg[rep_cg[p.t]];
            }
            p = p.next;
        }
        // Do simple statistics
        ++n_reachable;
        if (rep_cg[i] == i)
            ++n_scc_reachable;
    }
    if (connectMissedEntries) {
        // The functions other than SUPER_MAIN that have zero in-degrees are missed entry methods
        for (i = Constants.SUPER_MAIN + 1; i < n_func; ++i) {
            int rep_node = rep_cg[i];
            if (indeg_cg[rep_node] == 0) {
                CgEdge p = new CgEdge(Constants.SUPER_MAIN, i, null, call_graph[Constants.SUPER_MAIN]);
                call_graph[Constants.SUPER_MAIN] = p;
                n_calls++;
            }
        }
    }
    // context sensitive queries
    for (i = 0; i < n_func; ++i) if (vis_cg[i] != 0 && rep_cg[i] != i) {
        // Any node in a SCC must have at least one outgoing edge
        CgEdge p = call_graph[i];
        while (p.next != null) p = p.next;
        p.next = call_graph[rep_cg[i]];
        // Note that, call_graph[i] is not cleared after merging
        call_graph[rep_cg[i]] = call_graph[i];
    }
    // Now, we add all the source nodes to the queue
    max_context_size_block[Constants.SUPER_MAIN] = 1;
    queue_cg.addLast(Constants.SUPER_MAIN);
    while (!queue_cg.isEmpty()) {
        i = queue_cg.getFirst();
        queue_cg.removeFirst();
        CgEdge p = call_graph[i];
        while (p != null) {
            if (p.scc_edge == false) {
                // Consider the representative only
                j = rep_cg[p.t];
                /*
					 * We can control how many contexts created for a specified
					 * function. And, for any call edge, we can manually move
					 * the mapping interval from caller to callee.
					 */
                if (Constants.MAX_CONTEXTS - max_context_size_block[i] < max_context_size_block[j]) {
                    // The are more than 2^63 - 1 execution paths, terrible!
                    // We have to merge some contexts in order to make the analysis sound!
                    // The merging starting context is randomly picked
                    long start = rGen.nextLong();
                    if (start < 0)
                        start = -start;
                    if (start > Constants.MAX_CONTEXTS - max_context_size_block[i]) {
                        // We use the last max_context_size_block[i] bits for this mapping
                        start = Constants.MAX_CONTEXTS - max_context_size_block[i];
                        max_context_size_block[j] = Constants.MAX_CONTEXTS;
                    } else {
                        if (max_context_size_block[j] < start + max_context_size_block[i])
                            // We compensate the difference
                            max_context_size_block[j] = start + max_context_size_block[i];
                    }
                    p.map_offset = start + 1;
                } else {
                    // Accumulate the contexts
                    p.map_offset = max_context_size_block[j] + 1;
                    max_context_size_block[j] += max_context_size_block[i];
                }
                // Add to the worklist
                if (--indeg_cg[j] == 0)
                    queue_cg.addLast(j);
            } else {
                // 0-CFA modeling for the SCC, the default mode
                p.map_offset = 1;
            }
            p = p.next;
        }
        if (max_context_size_block[i] > max_contexts)
            max_contexts = max_context_size_block[i];
    }
    // Now we restore the call graph
    for (i = n_func - 1; i > -1; --i) {
        if (vis_cg[i] == 0)
            continue;
        if (rep_cg[i] != i) {
            // All nodes in the same SCC have the same number of contexts
            max_context_size_block[i] = max_context_size_block[rep_cg[i]];
            // Put all the call edges back
            CgEdge p = call_graph[i];
            while (p.next.s == i) // p.next.s may not be i because it would be linked to another scc member
            p = p.next;
            call_graph[rep_cg[i]] = p.next;
            p.next = null;
        }
        if (max_context_size_block[i] == Constants.MAX_CONTEXTS)
            ++n_full;
        context_size[i] = max_context_size_block[i];
        block_num[i] = 1;
    }
    // The implementation is slightly different from our paper (the non-SCC edges are not moved, they still use their current context mappings)
    if (getOpts().geom_blocking()) {
        // We don't manipulate the non-SCC edges, because they don't induce problems
        for (i = 0; i < n_func; ++i) {
            if (vis_cg[i] == 0)
                continue;
            CgEdge p = call_graph[i];
            while (p != null) {
                j = p.t;
                if (// This is not a self-loop, and a self-loop is treated specially in the initial encoding phase
                j != i && p.scc_edge == true) {
                    // So, we don't distinguish them
                    if (context_size[j] <= Constants.MAX_CONTEXTS - max_context_size_block[i]) {
                        p.map_offset = context_size[j] + 1;
                        context_size[j] += max_context_size_block[i];
                        ++block_num[j];
                    } else {
                        // We randomly pick a block for reuse (try best to avoid reusing the first block)
                        int iBlock = 0;
                        if (block_num[j] > 1)
                            iBlock = rGen.nextInt(block_num[j] - 1) + 1;
                        p.map_offset = iBlock * max_context_size_block[j] + 1;
                    }
                }
                p = p.next;
            }
        }
    }
    // Print debug info
    ps.printf("Reachable Methods = %d, in which #Condensed Nodes = %d, #Full Context Nodes = %d \n", n_reachable - 1, n_scc_reachable - 1, n_full);
    ps.printf("Maximum SCC = %d \n", max_scc_size);
    ps.printf("The maximum context size = %e\n", (double) max_contexts);
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) Random(java.util.Random) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint)

Example 13 with CgEdge

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

the class EvalResults method test_1cfa_call_graph.

/**
 * We assess the quality of building the 1-cfa call graph with the geometric
 * points-to result.
 */
private void test_1cfa_call_graph(LocalVarNode vn, SootMethod caller, SootMethod callee_signature, Histogram ce_range) {
    long l, r;
    IVarAbstraction pn = ptsProvider.findInternalNode(vn);
    if (pn == null)
        return;
    pn = pn.getRepresentative();
    Set<SootMethod> tgts = new HashSet<SootMethod>();
    Set<AllocNode> set = pn.get_all_points_to_objects();
    LinkedList<CgEdge> list = ptsProvider.getCallEdgesInto(ptsProvider.getIDFromSootMethod(caller));
    FastHierarchy hierarchy = Scene.v().getOrMakeFastHierarchy();
    for (Iterator<CgEdge> it = list.iterator(); it.hasNext(); ) {
        CgEdge p = it.next();
        l = p.map_offset;
        r = l + ptsProvider.max_context_size_block[p.s];
        tgts.clear();
        for (AllocNode obj : set) {
            if (!pn.pointer_interval_points_to(l, r, obj))
                continue;
            Type t = obj.getType();
            if (t == null)
                continue;
            else if (t instanceof AnySubType)
                t = ((AnySubType) t).getBase();
            else if (t instanceof ArrayType)
                t = RefType.v("java.lang.Object");
            try {
                tgts.add(hierarchy.resolveConcreteDispatch(((RefType) t).getSootClass(), callee_signature));
            } catch (Exception e) {
            }
        }
        tgts.remove(null);
        ce_range.addNumber(tgts.size());
    }
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) ArrayType(soot.ArrayType) RefType(soot.RefType) FastHierarchy(soot.FastHierarchy) RefType(soot.RefType) AnySubType(soot.AnySubType) RefLikeType(soot.RefLikeType) ArrayType(soot.ArrayType) Type(soot.Type) AllocNode(soot.jimple.spark.pag.AllocNode) IVarAbstraction(soot.jimple.spark.geom.geomPA.IVarAbstraction) SootMethod(soot.SootMethod) AnySubType(soot.AnySubType) HashSet(java.util.HashSet)

Example 14 with CgEdge

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

the class GeomQueries method prepareIntervalPropagations.

/**
 * Only needed by part of the queries.
 * Therefore, it is called on demand.
 */
private void prepareIntervalPropagations() {
    if (prop_initialized)
        return;
    // We layout the nodes hierarchically by topological sorting
    // The topological labels are used for speeding up reachability
    top_rank = new int[n_func];
    Arrays.fill(top_rank, 0);
    topQ = new LinkedList<Integer>();
    topQ.add(Constants.SUPER_MAIN);
    while (!topQ.isEmpty()) {
        int s = topQ.poll();
        CgEdge p = call_graph[s];
        while (p != null) {
            int t = p.t;
            int rep_t = rep_cg[t];
            int w = top_rank[s] + 1;
            if (top_rank[rep_t] < w)
                top_rank[rep_t] = w;
            if (--in_degree[rep_t] == 0)
                topQ.add(rep_t);
            p = p.next;
        }
    }
    // Prepare for querying artifacts
    contextsForMethods = new ContextsCollector[n_func];
    for (int i = 0; i < n_func; ++i) {
        ContextsCollector cc = new ContextsCollector();
        cc.setBudget(Parameters.qryBudgetSize);
        contextsForMethods[i] = cc;
    }
    prop_initialized = true;
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) ContextsCollector(soot.jimple.spark.geom.dataMgr.ContextsCollector)

Example 15 with CgEdge

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

the class GeomQueries method propagateIntervals.

/**
 * Compute the mapping from interval [L, R) of method start to the intervals of method target.
 * Return true if the mapping is feasible.
 *
 * @param start
 * @param L
 * @param R
 * @param target
 * @return
 */
protected boolean propagateIntervals(int start, long L, long R, int target) {
    // We first identify the subgraph, where all edges in the subgraph lead to the target
    if (!dfsScanSubgraph(start, target))
        return false;
    // Now we prepare for iteration
    int rep_start = rep_cg[start];
    int rep_target = rep_cg[target];
    ContextsCollector targetContexts = contextsForMethods[target];
    if (rep_start == rep_target) {
        // Fast path for the special case
        transferInSCC(start, target, L, R, targetContexts);
    } else {
        // We start traversal from the representative method
        transferInSCC(start, rep_start, L, R, contextsForMethods[rep_start]);
        // Start topsort
        topQ.clear();
        topQ.add(rep_start);
        while (!topQ.isEmpty()) {
            // Every function in the queue is representative function
            int s = topQ.poll();
            ContextsCollector sContexts = contextsForMethods[s];
            // Loop over the edges
            CgEdge p = call_graph[s];
            while (p != null) {
                int t = p.t;
                int rep_t = rep_cg[t];
                if (in_degree[rep_t] != 0) {
                    // This node has a path to target
                    ContextsCollector reptContexts = contextsForMethods[rep_t];
                    long block_size = max_context_size_block[s];
                    for (SimpleInterval si : sContexts.bars) {
                        // Compute the offset within the block for si
                        long in_block_offset = (si.L - 1) % block_size;
                        long newL = p.map_offset + in_block_offset;
                        long newR = si.R - si.L + newL;
                        if (rep_t == rep_target) {
                            // t and target are in the same SCC
                            // We directly transfer this context interval to target
                            transferInSCC(t, target, newL, newR, targetContexts);
                        } else {
                            // We transfer this interval to its SCC representative
                            // It might be t == rep_t
                            transferInSCC(t, rep_t, newL, newR, reptContexts);
                        }
                    }
                    if (--in_degree[rep_t] == 0 && rep_t != rep_target) {
                        topQ.add(rep_t);
                    }
                }
                p = p.next;
            }
            sContexts.clear();
        }
    }
    return true;
}
Also used : CgEdge(soot.jimple.spark.geom.dataRep.CgEdge) SimpleInterval(soot.jimple.spark.geom.dataRep.SimpleInterval) 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