Search in sources :

Example 11 with MethodOrMethodContext

use of soot.MethodOrMethodContext in project soot by Sable.

the class DeadlockDetector method detectLocksetDeadlock.

public MutableEdgeLabelledDirectedGraph<Integer, CriticalSection> detectLocksetDeadlock(Map<Value, Integer> lockToLockNum, List<PointsToSetInternal> lockPTSets) {
    HashMutableEdgeLabelledDirectedGraph<Integer, CriticalSection> permanentOrder = new HashMutableEdgeLabelledDirectedGraph<Integer, CriticalSection>();
    MutableEdgeLabelledDirectedGraph<Integer, CriticalSection> lockOrder;
    boolean foundDeadlock;
    int iteration = 0;
    do {
        iteration++;
        logger.debug("[DeadlockDetector] Deadlock Iteration #" + iteration);
        foundDeadlock = false;
        // start each iteration with a fresh copy of the permanent orders
        lockOrder = permanentOrder.clone();
        // Assemble the partial ordering of locks
        Iterator<CriticalSection> deadlockIt1 = criticalSections.iterator();
        while (deadlockIt1.hasNext() && !foundDeadlock) {
            CriticalSection tn1 = deadlockIt1.next();
            // skip if unlocked
            if (tn1.group == null) {
                continue;
            }
            // add a node for each lock in this lockset
            for (EquivalentValue lockEqVal : tn1.lockset) {
                Value lock = lockEqVal.getValue();
                if (!lockOrder.containsNode(lockToLockNum.get(lock))) {
                    lockOrder.addNode(lockToLockNum.get(lock));
                }
            }
            // 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() && !foundDeadlock) {
                CriticalSection tn2 = deadlockIt2.next();
                // skip if unlocked
                if (tn2.group == null) {
                    continue;
                }
                // add a node for each lock in this lockset
                for (EquivalentValue lockEqVal : tn2.lockset) {
                    Value lock = lockEqVal.getValue();
                    if (!lockOrder.containsNode(lockToLockNum.get(lock))) {
                        lockOrder.addNode(lockToLockNum.get(lock));
                    }
                }
                if (tn1.transitiveTargets.contains(tn2.method) && !foundDeadlock) {
                    // This implies the partial ordering (locks in tn1) before (locks in tn2)
                    if (// optionPrintDebug)
                    true) {
                        logger.debug("[DeadlockDetector] locks in " + (tn1.name) + " before locks in " + (tn2.name) + ": " + "outer: " + tn1.name + " inner: " + tn2.name);
                    }
                    // Check if tn2locks before tn1locks is in our lock order
                    for (EquivalentValue lock2EqVal : tn2.lockset) {
                        Value lock2 = lock2EqVal.getValue();
                        Integer lock2Num = lockToLockNum.get(lock2);
                        List<Integer> afterTn2 = new ArrayList<Integer>();
                        // filter here!
                        afterTn2.addAll(lockOrder.getSuccsOf(lock2Num));
                        ListIterator<Integer> lit = afterTn2.listIterator();
                        while (lit.hasNext()) {
                            // node the edges go to
                            Integer to = lit.next();
                            List<CriticalSection> labels = lockOrder.getLabelsForEdges(lock2Num, to);
                            boolean keep = false;
                            if (// this shouldn't really happen... is something wrong with the edge-labelled graph?
                            labels != null) {
                                for (CriticalSection labelTn : labels) {
                                    // Check if labelTn and tn1 share a static lock
                                    boolean tnsShareAStaticLock = false;
                                    for (EquivalentValue tn1LockEqVal : tn1.lockset) {
                                        Integer tn1LockNum = lockToLockNum.get(tn1LockEqVal.getValue());
                                        if (tn1LockNum < 0) {
                                            // this is a static lock... see if some lock in labelTn has the same #
                                            for (EquivalentValue labelTnLockEqVal : labelTn.lockset) {
                                                if (Objects.equals(lockToLockNum.get(labelTnLockEqVal.getValue()), tn1LockNum)) {
                                                    tnsShareAStaticLock = true;
                                                }
                                            }
                                        }
                                    }
                                    if (// !hasStaticLockInCommon(tn1, labelTn))
                                    !tnsShareAStaticLock) {
                                        keep = true;
                                        break;
                                    }
                                }
                            }
                            if (!keep) {
                                lit.remove();
                            }
                        }
                        /*				    			
                            for (int i = 0; i < afterTn2.size(); i++) {
                                List<Integer> succs = lockOrder.getSuccsOf(afterTn2.get(i)); // but not here
                                for (Integer o : succs) {
                                    if (!afterTn2.contains(o)) {
                                        afterTn2.add(o);
                                    }
                                }
                            }
                             */
                        for (EquivalentValue lock1EqVal : tn1.lockset) {
                            Value lock1 = lock1EqVal.getValue();
                            Integer lock1Num = lockToLockNum.get(lock1);
                            if ((!Objects.equals(lock1Num, lock2Num) || lock1Num > 0) && afterTn2.contains(lock1Num)) {
                                if (!optionRepairDeadlock) {
                                    logger.debug("[DeadlockDetector] DEADLOCK HAS BEEN DETECTED: not correcting");
                                    foundDeadlock = true;
                                } else {
                                    logger.debug("[DeadlockDetector] DEADLOCK HAS BEEN DETECTED while inspecting " + lock1Num + " (" + lock1 + ") and " + lock2Num + " (" + lock2 + ") ");
                                    // Create a deadlock avoidance edge
                                    DeadlockAvoidanceEdge dae = new DeadlockAvoidanceEdge(tn1.method.getDeclaringClass());
                                    EquivalentValue daeEqVal = new EquivalentValue(dae);
                                    // Register it as a static lock
                                    // negative indicates a static lock
                                    Integer daeNum = -lockPTSets.size();
                                    permanentOrder.addNode(daeNum);
                                    lockToLockNum.put(dae, daeNum);
                                    PointsToSetInternal dummyLockPT = new HashPointsToSet(lock1.getType(), (PAG) Scene.v().getPointsToAnalysis());
                                    lockPTSets.add(dummyLockPT);
                                    // Add it to the locksets of tn1 and whoever says l2 before l1
                                    for (EquivalentValue lockEqVal : tn1.lockset) {
                                        Integer lockNum = lockToLockNum.get(lockEqVal.getValue());
                                        if (!permanentOrder.containsNode(lockNum)) {
                                            permanentOrder.addNode(lockNum);
                                        }
                                        permanentOrder.addEdge(daeNum, lockNum, tn1);
                                    }
                                    tn1.lockset.add(daeEqVal);
                                    List<CriticalSection> forwardLabels = lockOrder.getLabelsForEdges(lock1Num, lock2Num);
                                    if (forwardLabels != null) {
                                        for (CriticalSection tn : forwardLabels) {
                                            if (!tn.lockset.contains(daeEqVal)) {
                                                for (EquivalentValue lockEqVal : tn.lockset) {
                                                    Integer lockNum = lockToLockNum.get(lockEqVal.getValue());
                                                    if (!permanentOrder.containsNode(lockNum)) {
                                                        permanentOrder.addNode(lockNum);
                                                    }
                                                    permanentOrder.addEdge(daeNum, lockNum, tn);
                                                }
                                                tn.lockset.add(daeEqVal);
                                            }
                                        }
                                    }
                                    List<CriticalSection> backwardLabels = lockOrder.getLabelsForEdges(lock2Num, lock1Num);
                                    if (backwardLabels != null) {
                                        for (CriticalSection tn : backwardLabels) {
                                            if (!tn.lockset.contains(daeEqVal)) {
                                                for (EquivalentValue lockEqVal : tn.lockset) {
                                                    Integer lockNum = lockToLockNum.get(lockEqVal.getValue());
                                                    if (!permanentOrder.containsNode(lockNum)) {
                                                        permanentOrder.addNode(lockNum);
                                                    }
                                                    permanentOrder.addEdge(daeNum, lockNum, tn);
                                                }
                                                tn.lockset.add(daeEqVal);
                                                logger.debug("[DeadlockDetector]   Adding deadlock avoidance edge between " + (tn1.name) + " and " + (tn.name));
                                            }
                                        }
                                        logger.debug("[DeadlockDetector]   Restarting deadlock detection");
                                    }
                                    foundDeadlock = true;
                                    break;
                                }
                            }
                            if (!Objects.equals(lock1Num, lock2Num)) {
                                lockOrder.addEdge(lock1Num, lock2Num, tn1);
                            }
                        }
                        if (foundDeadlock) {
                            break;
                        }
                    }
                }
            }
        }
    } while (foundDeadlock && optionRepairDeadlock);
    return lockOrder;
}
Also used : EquivalentValue(soot.EquivalentValue) PointsToSetInternal(soot.jimple.spark.sets.PointsToSetInternal) ArrayList(java.util.ArrayList) Unit(soot.Unit) EquivalentValue(soot.EquivalentValue) Value(soot.Value) HashPointsToSet(soot.jimple.spark.sets.HashPointsToSet) HashMutableEdgeLabelledDirectedGraph(soot.toolkits.graph.HashMutableEdgeLabelledDirectedGraph) MethodOrMethodContext(soot.MethodOrMethodContext)

Example 12 with MethodOrMethodContext

use of soot.MethodOrMethodContext in project soot by Sable.

the class OnFlyCallGraph method processReachables.

private void processReachables() {
    reachableMethods.update();
    while (reachablesReader.hasNext()) {
        MethodOrMethodContext m = reachablesReader.next();
        MethodPAG mpag = MethodPAG.v(pag, m.method());
        mpag.build();
        mpag.addToPAG(m.context());
    }
}
Also used : MethodPAG(soot.jimple.spark.pag.MethodPAG) 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