Search in sources :

Example 1 with MethodOrMethodContext

use of soot.MethodOrMethodContext 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 2 with MethodOrMethodContext

use of soot.MethodOrMethodContext in project soot by Sable.

the class DeadlockDetector method detectComponentBasedDeadlock.

public MutableDirectedGraph<CriticalSectionGroup> detectComponentBasedDeadlock() {
    MutableDirectedGraph<CriticalSectionGroup> lockOrder;
    boolean foundDeadlock;
    int iteration = 0;
    do {
        iteration++;
        logger.debug("[DeadlockDetector] Deadlock Iteration #" + iteration);
        foundDeadlock = false;
        // start each iteration with a fresh graph
        lockOrder = new HashMutableDirectedGraph<CriticalSectionGroup>();
        // Assemble the partial ordering of locks
        Iterator<CriticalSection> deadlockIt1 = criticalSections.iterator();
        while (deadlockIt1.hasNext() && !foundDeadlock) {
            CriticalSection tn1 = deadlockIt1.next();
            // skip if unlocked
            if (tn1.setNumber <= 0) {
                continue;
            }
            // add a node for this set
            if (!lockOrder.containsNode(tn1.group)) {
                lockOrder.addNode(tn1.group);
            }
            // Get list of tn1's target methods
            if (tn1.transitiveTargets == null) {
                tn1.transitiveTargets = new HashSet<MethodOrMethodContext>();
                for (Unit tn1Invoke : tn1.invokes) {
                    Iterator<MethodOrMethodContext> targetIt = tt.iterator(tn1Invoke);
                    while (targetIt.hasNext()) {
                        tn1.transitiveTargets.add(targetIt.next());
                    }
                }
            }
            // compare to each other tn
            Iterator<CriticalSection> deadlockIt2 = criticalSections.iterator();
            while (deadlockIt2.hasNext() && (!optionRepairDeadlock || !foundDeadlock)) {
                CriticalSection tn2 = deadlockIt2.next();
                // skip if unlocked or in same set as tn1
                if (// this is wrong... dynamic locks in same group can be diff locks
                tn2.setNumber <= 0 || (tn2.setNumber == tn1.setNumber && !optionAllowSelfEdges)) {
                    continue;
                }
                // add a node for this set
                if (!lockOrder.containsNode(tn2.group)) {
                    lockOrder.addNode(tn2.group);
                }
                if (tn1.transitiveTargets.contains(tn2.method)) {
                    // This implies the partial ordering tn1lock before tn2lock
                    if (optionPrintDebug) {
                        logger.debug("group" + (tn1.setNumber) + " before group" + (tn2.setNumber) + ": " + "outer: " + tn1.name + " inner: " + tn2.name);
                    }
                    // Check if tn2lock before tn1lock is in our lock order
                    List<CriticalSectionGroup> afterTn2 = new ArrayList<CriticalSectionGroup>();
                    afterTn2.addAll(lockOrder.getSuccsOf(tn2.group));
                    for (int i = 0; i < afterTn2.size(); i++) {
                        for (CriticalSectionGroup o : lockOrder.getSuccsOf(afterTn2.get(i))) {
                            if (!afterTn2.contains(o)) {
                                afterTn2.add(o);
                            }
                        }
                    }
                    if (afterTn2.contains(tn1.group)) {
                        if (!optionRepairDeadlock) {
                            logger.debug("[DeadlockDetector]  DEADLOCK HAS BEEN DETECTED: not correcting");
                            foundDeadlock = true;
                        } else {
                            logger.debug("[DeadlockDetector]  DEADLOCK HAS BEEN DETECTED: merging group" + (tn1.setNumber) + " and group" + (tn2.setNumber) + " and restarting deadlock detection");
                            if (optionPrintDebug) {
                                logger.debug("tn1.setNumber was " + tn1.setNumber + " and tn2.setNumber was " + tn2.setNumber);
                                logger.debug("tn1.group.size was " + tn1.group.criticalSections.size() + " and tn2.group.size was " + tn2.group.criticalSections.size());
                                logger.debug("tn1.group.num was  " + tn1.group.num() + " and tn2.group.num was  " + tn2.group.num());
                            }
                            tn1.group.mergeGroups(tn2.group);
                            if (optionPrintDebug) {
                                logger.debug("tn1.setNumber is  " + tn1.setNumber + " and tn2.setNumber is  " + tn2.setNumber);
                                logger.debug("tn1.group.size is  " + tn1.group.criticalSections.size() + " and tn2.group.size is  " + tn2.group.criticalSections.size());
                            }
                            foundDeadlock = true;
                        }
                    }
                    lockOrder.addEdge(tn1.group, tn2.group);
                }
            }
        }
    } while (foundDeadlock && optionRepairDeadlock);
    return lockOrder;
}
Also used : ArrayList(java.util.ArrayList) Unit(soot.Unit) MethodOrMethodContext(soot.MethodOrMethodContext)

Example 3 with MethodOrMethodContext

use of soot.MethodOrMethodContext in project soot by Sable.

the class CallGraphExample method main.

public static void main(String[] args) {
    List<String> argsList = new ArrayList<String>(Arrays.asList(args));
    argsList.addAll(Arrays.asList(new String[] { "-w", "-main-class", // main-class
    "testers.CallGraphs", // argument classes
    "testers.CallGraphs", // 
    "testers.A" }));
    PackManager.v().getPack("wjtp").add(new Transform("wjtp.myTrans", new SceneTransformer() {

        @Override
        protected void internalTransform(String phaseName, Map options) {
            CHATransformer.v().transform();
            SootClass a = Scene.v().getSootClass("testers.A");
            SootMethod src = Scene.v().getMainClass().getMethodByName("doStuff");
            CallGraph cg = Scene.v().getCallGraph();
            Iterator<MethodOrMethodContext> targets = new Targets(cg.edgesOutOf(src));
            while (targets.hasNext()) {
                SootMethod tgt = (SootMethod) targets.next();
                System.out.println(src + " may call " + tgt);
            }
        }
    }));
    args = argsList.toArray(new String[0]);
    soot.Main.main(args);
}
Also used : CallGraph(soot.jimple.toolkits.callgraph.CallGraph) ArrayList(java.util.ArrayList) SootMethod(soot.SootMethod) Targets(soot.jimple.toolkits.callgraph.Targets) Transform(soot.Transform) SootClass(soot.SootClass) MethodOrMethodContext(soot.MethodOrMethodContext) Map(java.util.Map) SceneTransformer(soot.SceneTransformer)

Example 4 with MethodOrMethodContext

use of soot.MethodOrMethodContext in project soot by Sable.

the class LocalMustAliasAnalysis method trackableFields.

/**
 * Computes the set of {@link EquivalentValue}s of all field references that are used
 * in this method but not set by the method or any method transitively called by this method.
 */
private Set<Value> trackableFields() {
    Set<Value> usedFieldRefs = new HashSet<Value>();
    // add all field references that are in use boxes
    for (Unit unit : this.graph) {
        Stmt s = (Stmt) unit;
        List<ValueBox> useBoxes = s.getUseBoxes();
        for (ValueBox useBox : useBoxes) {
            Value val = useBox.getValue();
            if (val instanceof FieldRef) {
                FieldRef fieldRef = (FieldRef) val;
                if (fieldRef.getType() instanceof RefLikeType)
                    usedFieldRefs.add(new EquivalentValue(fieldRef));
            }
        }
    }
    // prune all fields that are written to
    if (!usedFieldRefs.isEmpty()) {
        if (!Scene.v().hasCallGraph()) {
            throw new IllegalStateException("No call graph found!");
        }
        CallGraph cg = Scene.v().getCallGraph();
        ReachableMethods reachableMethods = new ReachableMethods(cg, Collections.<MethodOrMethodContext>singletonList(container));
        reachableMethods.update();
        for (Iterator<MethodOrMethodContext> iterator = reachableMethods.listener(); iterator.hasNext(); ) {
            SootMethod m = (SootMethod) iterator.next();
            if (m.hasActiveBody() && // exclude static initializer of same class (assume that it has already been executed)
            !(m.getName().equals(SootMethod.staticInitializerName) && m.getDeclaringClass().equals(container.getDeclaringClass()))) {
                for (Unit u : m.getActiveBody().getUnits()) {
                    List<ValueBox> defBoxes = u.getDefBoxes();
                    for (ValueBox defBox : defBoxes) {
                        Value value = defBox.getValue();
                        if (value instanceof FieldRef) {
                            usedFieldRefs.remove(new EquivalentValue(value));
                        }
                    }
                }
            }
        }
    }
    return usedFieldRefs;
}
Also used : EquivalentValue(soot.EquivalentValue) FieldRef(soot.jimple.FieldRef) Unit(soot.Unit) Stmt(soot.jimple.Stmt) DefinitionStmt(soot.jimple.DefinitionStmt) RefLikeType(soot.RefLikeType) ReachableMethods(soot.jimple.toolkits.callgraph.ReachableMethods) CallGraph(soot.jimple.toolkits.callgraph.CallGraph) ValueBox(soot.ValueBox) EquivalentValue(soot.EquivalentValue) Value(soot.Value) SootMethod(soot.SootMethod) MethodOrMethodContext(soot.MethodOrMethodContext) HashSet(java.util.HashSet)

Example 5 with MethodOrMethodContext

use of soot.MethodOrMethodContext in project soot by Sable.

the class SideEffectAnalysis method writeSet.

public RWSet writeSet(SootMethod method, Stmt stmt) {
    RWSet ret = null;
    Iterator<MethodOrMethodContext> targets = tt.iterator(stmt);
    while (targets.hasNext()) {
        SootMethod target = (SootMethod) targets.next();
        if (target.isNative()) {
            if (ret == null)
                ret = new SiteRWSet();
            ret.setCallsNative();
        } else if (target.isConcrete()) {
            RWSet ntw = nonTransitiveWriteSet(target);
            if (ntw != null) {
                if (ret == null)
                    ret = new SiteRWSet();
                ret.union(ntw);
            }
        }
    }
    if (ret == null)
        return ntWriteSet(method, stmt);
    ret.union(ntWriteSet(method, stmt));
    return ret;
}
Also used : SootMethod(soot.SootMethod) MethodOrMethodContext(soot.MethodOrMethodContext)

Aggregations

MethodOrMethodContext (soot.MethodOrMethodContext)12 SootMethod (soot.SootMethod)7 ArrayList (java.util.ArrayList)3 Unit (soot.Unit)3 Value (soot.Value)3 CallGraph (soot.jimple.toolkits.callgraph.CallGraph)3 EquivalentValue (soot.EquivalentValue)2 Type (soot.Type)2 Stmt (soot.jimple.Stmt)2 AllocNode (soot.jimple.spark.pag.AllocNode)2 Node (soot.jimple.spark.pag.Node)2 PointsToSetInternal (soot.jimple.spark.sets.PointsToSetInternal)2 Collection (java.util.Collection)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 Map (java.util.Map)1 Local (soot.Local)1 PointsToSet (soot.PointsToSet)1 RefLikeType (soot.RefLikeType)1 RefType (soot.RefType)1