Search in sources :

Example 1 with Node

use of soot.jimple.spark.pag.Node in project soot by Sable.

the class GeomPointsTo method finalizeInternalData.

/**
 * 1. Update the call graph;
 * 2. Eliminate the pointers, objects, and constraints related to the unreachable code.
 */
private void finalizeInternalData() {
    // Compute the set of reachable functions after the points-to analysis
    markReachableMethods();
    // Clean the unreachable objects
    for (Iterator<IVarAbstraction> it = allocations.iterator(); it.hasNext(); ) {
        IVarAbstraction po = it.next();
        AllocNode obj = (AllocNode) po.getWrappedNode();
        SootMethod sm = obj.getMethod();
        if (sm != null && func2int.containsKey(sm) == false)
            it.remove();
    }
    // Clean the unreachable pointers
    final Vector<AllocNode> removeSet = new Vector<AllocNode>();
    for (Iterator<IVarAbstraction> it = pointers.iterator(); it.hasNext(); ) {
        IVarAbstraction pn = it.next();
        // Is this pointer obsoleted?
        Node vn = pn.getWrappedNode();
        SootMethod sm = null;
        if (vn instanceof LocalVarNode) {
            sm = ((LocalVarNode) vn).getMethod();
        } else if (vn instanceof AllocDotField) {
            sm = ((AllocDotField) vn).getBase().getMethod();
        }
        if (sm != null) {
            if (func2int.containsKey(sm) == false) {
                pn.deleteAll();
                vn.discardP2Set();
                it.remove();
                continue;
            }
        }
        if (pn.getRepresentative() != pn)
            continue;
        removeSet.clear();
        if (pn.hasPTResult()) {
            // We remove the useless shapes or objects
            Set<AllocNode> objSet = pn.get_all_points_to_objects();
            for (Iterator<AllocNode> oit = objSet.iterator(); oit.hasNext(); ) {
                AllocNode obj = oit.next();
                IVarAbstraction po = consG.get(obj);
                if (!po.reachable() || pn.isDeadObject(obj)) {
                    removeSet.add(obj);
                }
            }
            for (AllocNode obj : removeSet) pn.remove_points_to(obj);
            pn.drop_duplicates();
        } else {
            // We also remove unreachable objects for SPARK nodes
            PointsToSetInternal pts = vn.getP2Set();
            pts.forall(new P2SetVisitor() {

                @Override
                public void visit(Node n) {
                    IVarAbstraction pan = findInternalNode(n);
                    // The removeSet is misused as a contains set
                    if (pan.reachable())
                        removeSet.add((AllocNode) n);
                }
            });
            pts = vn.makeP2Set();
            for (AllocNode an : removeSet) pts.add(an);
        }
    }
    // Clean the useless constraints
    for (Iterator<PlainConstraint> cIt = constraints.iterator(); cIt.hasNext(); ) {
        PlainConstraint cons = cIt.next();
        IVarAbstraction lhs = cons.getLHS();
        IVarAbstraction rhs = cons.getRHS();
        if (!lhs.reachable() || !rhs.reachable() || getMethodIDFromPtr(lhs) == Constants.UNKNOWN_FUNCTION || getMethodIDFromPtr(rhs) == Constants.UNKNOWN_FUNCTION) {
            cIt.remove();
        }
    }
    // We reassign the IDs to the pointers, objects and constraints
    pointers.reassign();
    allocations.reassign();
    constraints.reassign();
}
Also used : AllocDotField(soot.jimple.spark.pag.AllocDotField) PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint) PointsToSetInternal(soot.jimple.spark.sets.PointsToSetInternal) 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) AllocNode(soot.jimple.spark.pag.AllocNode) SootMethod(soot.SootMethod) Vector(java.util.Vector) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) P2SetVisitor(soot.jimple.spark.sets.P2SetVisitor)

Example 2 with Node

use of soot.jimple.spark.pag.Node in project soot by Sable.

the class GeomPointsTo method field_p2set.

// --------------------------------------------------------------------------------------------------------
// -------------------------------Soot Standard Points-to Query Interface----------------------------------
// --------------------------------------------------------------------------------------------------------
private PointsToSetInternal field_p2set(PointsToSet s, final SparkField f) {
    if (!(s instanceof PointsToSetInternal))
        throw new RuntimeException("Base pointers must be stored in *PointsToSetInternal*.");
    PointsToSetInternal bases = (PointsToSetInternal) s;
    final PointsToSetInternal ret = getSetFactory().newSet(f.getType(), this);
    bases.forall(new P2SetVisitor() {

        public final void visit(Node n) {
            Node nDotF = ((AllocNode) n).dot(f);
            if (nDotF != null) {
                // nDotF.getP2Set() has been discarded in solve()
                IVarAbstraction pn = consG.get(nDotF);
                if (pn == null || hasTransformed || nDotF.getP2Set() != EmptyPointsToSet.v()) {
                    ret.addAll(nDotF.getP2Set(), null);
                    return;
                }
                pn = pn.getRepresentative();
                // PointsToSetInternal ptSet = nDotF.makeP2Set();
                for (AllocNode obj : pn.get_all_points_to_objects()) {
                    ret.add(obj);
                // ptSet.add(obj);
                }
            }
        }
    });
    return ret;
}
Also used : AllocNode(soot.jimple.spark.pag.AllocNode) PointsToSetInternal(soot.jimple.spark.sets.PointsToSetInternal) 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) P2SetVisitor(soot.jimple.spark.sets.P2SetVisitor)

Example 3 with Node

use of soot.jimple.spark.pag.Node in project soot by Sable.

the class GeomPointsTo method finalizeSootData.

/**
 * Update the reachable methods and SPARK points-to results.
 */
private void finalizeSootData() {
    // We remove the unreachable functions from Soot internal structures
    Scene.v().releaseReachableMethods();
    // The we rebuild it from the updated Soot call graph
    Scene.v().getReachableMethods();
    if (!opts.geom_trans()) {
        // At querying time, the SPARK points-to container acts as a query cache
        for (IVarAbstraction pn : pointers) {
            // Keep only the points-to results for representatives
            if (pn != pn.getRepresentative()) {
                continue;
            }
            // Simplify
            if (pn.hasPTResult()) {
                pn.keepPointsToOnly();
                Node vn = pn.getWrappedNode();
                vn.discardP2Set();
            }
        }
    } else {
        // Do we need to obtain the context insensitive points-to result?
        transformToCIResult();
    }
}
Also used : 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)

Example 4 with Node

use of soot.jimple.spark.pag.Node in project soot by Sable.

the class GeomPointsTo method mergeLocalVariables.

/**
 * As pointed out by the single entry graph contraction, temporary variables incur high redundancy in points-to relations.
 * Find and eliminate the redundancies as early as possible.
 *
 * Methodology:
 * If q has unique incoming edge p -> q, p and q are both local to the same function, and they have the same type, we merge them.
 */
private void mergeLocalVariables() {
    IVarAbstraction my_lhs, my_rhs;
    Node lhs, rhs;
    int[] count = new int[pointers.size()];
    // We count how many ways a local pointer can be assigned
    for (PlainConstraint cons : constraints) {
        my_lhs = cons.getLHS();
        my_rhs = cons.getRHS();
        switch(cons.type) {
            case Constants.NEW_CONS:
            case Constants.ASSIGN_CONS:
                count[my_rhs.id]++;
                break;
            case Constants.LOAD_CONS:
                lhs = my_lhs.getWrappedNode();
                count[my_rhs.id] += lhs.getP2Set().size();
                break;
        }
    }
    // Second time scan, we delete those constraints that only duplicate points-to information
    for (Iterator<PlainConstraint> cons_it = constraints.iterator(); cons_it.hasNext(); ) {
        PlainConstraint cons = cons_it.next();
        if (cons.type == Constants.ASSIGN_CONS) {
            my_lhs = cons.getLHS();
            my_rhs = cons.getRHS();
            lhs = my_lhs.getWrappedNode();
            rhs = my_rhs.getWrappedNode();
            if ((lhs instanceof LocalVarNode) && (rhs instanceof LocalVarNode)) {
                SootMethod sm1 = ((LocalVarNode) lhs).getMethod();
                SootMethod sm2 = ((LocalVarNode) rhs).getMethod();
                if (sm1 == sm2 && count[my_rhs.id] == 1 && lhs.getType() == rhs.getType()) {
                    // They are local to the same function and the receiver pointer has unique incoming edge
                    // More importantly, they have the same type.
                    my_rhs.merge(my_lhs);
                    cons_it.remove();
                }
            }
        }
    }
    // Third scan, update the constraints with the representatives
    for (PlainConstraint cons : constraints) {
        my_lhs = cons.getLHS();
        my_rhs = cons.getRHS();
        switch(cons.type) {
            case Constants.NEW_CONS:
                cons.setRHS(my_rhs.getRepresentative());
                break;
            case Constants.ASSIGN_CONS:
            case Constants.LOAD_CONS:
            case Constants.STORE_CONS:
                cons.setLHS(my_lhs.getRepresentative());
                cons.setRHS(my_rhs.getRepresentative());
                break;
        }
    }
}
Also used : PlainConstraint(soot.jimple.spark.geom.dataRep.PlainConstraint) 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) SootMethod(soot.SootMethod) LocalVarNode(soot.jimple.spark.pag.LocalVarNode)

Example 5 with Node

use of soot.jimple.spark.pag.Node 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

Node (soot.jimple.spark.pag.Node)65 AllocNode (soot.jimple.spark.pag.AllocNode)62 VarNode (soot.jimple.spark.pag.VarNode)54 FieldRefNode (soot.jimple.spark.pag.FieldRefNode)36 LocalVarNode (soot.jimple.spark.pag.LocalVarNode)36 PointsToSetInternal (soot.jimple.spark.sets.PointsToSetInternal)25 P2SetVisitor (soot.jimple.spark.sets.P2SetVisitor)23 GlobalVarNode (soot.jimple.spark.pag.GlobalVarNode)18 ClassConstantNode (soot.jimple.spark.pag.ClassConstantNode)17 NewInstanceNode (soot.jimple.spark.pag.NewInstanceNode)17 SparkField (soot.jimple.spark.pag.SparkField)17 SootMethod (soot.SootMethod)15 RefType (soot.RefType)12 Type (soot.Type)11 StringConstantNode (soot.jimple.spark.pag.StringConstantNode)11 PlainConstraint (soot.jimple.spark.geom.dataRep.PlainConstraint)10 AllocDotField (soot.jimple.spark.pag.AllocDotField)10 HashSet (java.util.HashSet)9 SootClass (soot.SootClass)9 Value (soot.Value)6