Search in sources :

Example 31 with PointsToSetInternal

use of soot.jimple.spark.sets.PointsToSetInternal 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 32 with PointsToSetInternal

use of soot.jimple.spark.sets.PointsToSetInternal in project soot by Sable.

the class GeomPointsTo method reachingObjects.

// An extra query interfaces not provided by SPARK
public PointsToSet reachingObjects(AllocNode an, SootField f) {
    AllocDotField adf = an.dot(f);
    IVarAbstraction pn = consG.get(adf);
    // No such pointer seen by SPARK
    if (adf == null)
        return EmptyPointsToSet.v();
    // Not seen by geomPTA
    if (pn == null)
        return adf.getP2Set();
    if (hasTransformed || adf.getP2Set() != EmptyPointsToSet.v())
        return adf.getP2Set();
    // We transform and cache the result for the next query
    pn = pn.getRepresentative();
    PointsToSetInternal ptSet = adf.makeP2Set();
    for (AllocNode obj : pn.getRepresentative().get_all_points_to_objects()) {
        ptSet.add(obj);
    }
    return ptSet;
}
Also used : AllocDotField(soot.jimple.spark.pag.AllocDotField) AllocNode(soot.jimple.spark.pag.AllocNode) PointsToSetInternal(soot.jimple.spark.sets.PointsToSetInternal)

Example 33 with PointsToSetInternal

use of soot.jimple.spark.sets.PointsToSetInternal in project soot by Sable.

the class DemandCSPointsTo method processIncomingEdges.

protected void processIncomingEdges(IncomingEdgeHandler h, Stack<VarAndContext> worklist) {
    while (!worklist.isEmpty()) {
        incrementNodesTraversed();
        VarAndContext varAndContext = worklist.pop();
        if (DEBUG) {
            debugPrint("looking at " + varAndContext);
        }
        VarNode v = varAndContext.var;
        ImmutableStack<Integer> callingContext = varAndContext.context;
        Node[] newEdges = pag.allocInvLookup(v);
        for (int i = 0; i < newEdges.length; i++) {
            AllocNode allocNode = (AllocNode) newEdges[i];
            h.handleAlloc(allocNode, varAndContext);
            if (h.terminate()) {
                return;
            }
        }
        Collection<AssignEdge> assigns = filterAssigns(v, callingContext, true, true);
        for (AssignEdge assignEdge : assigns) {
            VarNode src = assignEdge.getSrc();
            // }
            if (h.shouldHandleSrc(src)) {
                ImmutableStack<Integer> newContext = callingContext;
                if (assignEdge.isParamEdge()) {
                    if (!callingContext.isEmpty()) {
                        if (!callEdgeInSCC(assignEdge)) {
                            assert assignEdge.getCallSite().equals(callingContext.peek()) : assignEdge + " " + callingContext;
                            newContext = callingContext.pop();
                        } else {
                            newContext = popRecursiveCallSites(callingContext);
                        }
                    }
                // } else if (refiningCallSite) {
                // if (!fieldCheckHeuristic.aggressiveVirtCallRefine())
                // {
                // // throw new CallSiteException();
                // }
                // }
                } else if (assignEdge.isReturnEdge()) {
                    if (DEBUG)
                        debugPrint("entering call site " + assignEdge.getCallSite());
                    // if (!isRecursive(callingContext, assignEdge)) {
                    // newContext = callingContext.push(assignEdge
                    // .getCallSite());
                    // }
                    newContext = pushWithRecursionCheck(callingContext, assignEdge);
                }
                if (assignEdge.isParamEdge()) {
                    Integer callSite = assignEdge.getCallSite();
                    if (csInfo.isVirtCall(callSite) && !weirdCall(callSite)) {
                        Set<SootMethod> targets = refineCallSite(callSite, newContext);
                        if (DEBUG) {
                            debugPrint(targets.toString());
                        }
                        SootMethod targetMethod = ((LocalVarNode) assignEdge.getDst()).getMethod();
                        if (!targets.contains(targetMethod)) {
                            if (DEBUG) {
                                debugPrint("skipping call because of call graph");
                            }
                            continue;
                        }
                    }
                }
                if (src instanceof GlobalVarNode) {
                    newContext = EMPTY_CALLSTACK;
                }
                h.handleAssignSrc(new VarAndContext(src, newContext), varAndContext, assignEdge);
                if (h.terminate()) {
                    return;
                }
            }
        }
        Set<VarNode> matchSources = vMatches.vMatchInvLookup(v);
        Node[] loads = pag.loadInvLookup(v);
        for (int i = 0; i < loads.length; i++) {
            FieldRefNode frNode = (FieldRefNode) loads[i];
            final VarNode loadBase = frNode.getBase();
            SparkField field = frNode.getField();
            // FieldRefNode>(v, frNode);
            for (Pair<VarNode, VarNode> store : fieldToStores.get(field)) {
                final VarNode storeBase = store.getO2();
                final PointsToSetInternal storeBaseP2Set = storeBase.getP2Set();
                final PointsToSetInternal loadBaseP2Set = loadBase.getP2Set();
                final VarNode matchSrc = store.getO1();
                if (matchSources.contains(matchSrc)) {
                    if (h.shouldHandleSrc(matchSrc)) {
                        if (DEBUG) {
                            debugPrint("match source " + matchSrc);
                        }
                        PointsToSetInternal intersection = SootUtil.constructIntersection(storeBaseP2Set, loadBaseP2Set, pag);
                        boolean checkGetfield = fieldCheckHeuristic.validateMatchesForField(field);
                        h.handleMatchSrc(matchSrc, intersection, loadBase, storeBase, varAndContext, field, checkGetfield);
                        if (h.terminate())
                            return;
                    }
                }
            }
        }
    }
}
Also used : GlobalVarNode(soot.jimple.spark.pag.GlobalVarNode) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) VarNode(soot.jimple.spark.pag.VarNode) GlobalVarNode(soot.jimple.spark.pag.GlobalVarNode) PointsToSetInternal(soot.jimple.spark.sets.PointsToSetInternal) FieldRefNode(soot.jimple.spark.pag.FieldRefNode) GlobalVarNode(soot.jimple.spark.pag.GlobalVarNode) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) Node(soot.jimple.spark.pag.Node) VarNode(soot.jimple.spark.pag.VarNode) AllocNode(soot.jimple.spark.pag.AllocNode) AssignEdge(soot.jimple.spark.ondemand.pautil.AssignEdge) SparkField(soot.jimple.spark.pag.SparkField) FieldRefNode(soot.jimple.spark.pag.FieldRefNode) AllocNode(soot.jimple.spark.pag.AllocNode) SootMethod(soot.SootMethod) LocalVarNode(soot.jimple.spark.pag.LocalVarNode)

Example 34 with PointsToSetInternal

use of soot.jimple.spark.sets.PointsToSetInternal in project soot by Sable.

the class DemandCSPointsTo method findVarContextsFromAlloc.

protected CallingContextSet findVarContextsFromAlloc(AllocAndContext allocAndContext, VarNode targetVar) {
    CallingContextSet tmpSet = checkAllocAndContextCache(allocAndContext, targetVar);
    if (tmpSet != null) {
        return tmpSet;
    }
    CallingContextSet ret = new CallingContextSet();
    allocAndContextCache.get(allocAndContext).put(targetVar, ret);
    try {
        HashSet<VarAndContext> marked = new HashSet<VarAndContext>();
        Stack<VarAndContext> worklist = new Stack<VarAndContext>();
        Propagator<VarAndContext> p = new Propagator<VarAndContext>(marked, worklist);
        AllocNode alloc = allocAndContext.alloc;
        ImmutableStack<Integer> allocContext = allocAndContext.context;
        Node[] newBarNodes = pag.allocLookup(alloc);
        for (int i = 0; i < newBarNodes.length; i++) {
            VarNode v = (VarNode) newBarNodes[i];
            p.prop(new VarAndContext(v, allocContext));
        }
        while (!worklist.isEmpty()) {
            incrementNodesTraversed();
            VarAndContext curVarAndContext = worklist.pop();
            if (DEBUG) {
                debugPrint("looking at " + curVarAndContext);
            }
            VarNode curVar = curVarAndContext.var;
            ImmutableStack<Integer> curContext = curVarAndContext.context;
            if (curVar == targetVar) {
                ret.add(curContext);
            }
            // assign
            Collection<AssignEdge> assignEdges = filterAssigns(curVar, curContext, false, true);
            for (AssignEdge assignEdge : assignEdges) {
                VarNode dst = assignEdge.getDst();
                ImmutableStack<Integer> newContext = curContext;
                if (assignEdge.isReturnEdge()) {
                    if (!curContext.isEmpty()) {
                        if (!callEdgeInSCC(assignEdge)) {
                            assert assignEdge.getCallSite().equals(curContext.peek()) : assignEdge + " " + curContext;
                            newContext = curContext.pop();
                        } else {
                            newContext = popRecursiveCallSites(curContext);
                        }
                    }
                } else if (assignEdge.isParamEdge()) {
                    if (DEBUG)
                        debugPrint("entering call site " + assignEdge.getCallSite());
                    // if (!isRecursive(curContext, assignEdge)) {
                    // newContext = curContext.push(assignEdge
                    // .getCallSite());
                    // }
                    newContext = pushWithRecursionCheck(curContext, assignEdge);
                }
                if (assignEdge.isReturnEdge() && curContext.isEmpty() && csInfo.isVirtCall(assignEdge.getCallSite())) {
                    Set<SootMethod> targets = refineCallSite(assignEdge.getCallSite(), newContext);
                    if (!targets.contains(((LocalVarNode) assignEdge.getDst()).getMethod())) {
                        continue;
                    }
                }
                if (dst instanceof GlobalVarNode) {
                    newContext = EMPTY_CALLSTACK;
                }
                p.prop(new VarAndContext(dst, newContext));
            }
            // putfield_bars
            Set<VarNode> matchTargets = vMatches.vMatchLookup(curVar);
            Node[] pfTargets = pag.storeLookup(curVar);
            for (int i = 0; i < pfTargets.length; i++) {
                FieldRefNode frNode = (FieldRefNode) pfTargets[i];
                final VarNode storeBase = frNode.getBase();
                SparkField field = frNode.getField();
                // FieldRefNode>(curVar, frNode);
                for (Pair<VarNode, VarNode> load : fieldToLoads.get(field)) {
                    final VarNode loadBase = load.getO2();
                    final PointsToSetInternal loadBaseP2Set = loadBase.getP2Set();
                    final PointsToSetInternal storeBaseP2Set = storeBase.getP2Set();
                    final VarNode matchTgt = load.getO1();
                    if (matchTargets.contains(matchTgt)) {
                        if (DEBUG) {
                            debugPrint("match source " + matchTgt);
                        }
                        PointsToSetInternal intersection = SootUtil.constructIntersection(storeBaseP2Set, loadBaseP2Set, pag);
                        boolean checkField = fieldCheckHeuristic.validateMatchesForField(field);
                        if (checkField) {
                            AllocAndContextSet sharedAllocContexts = findContextsForAllocs(new VarAndContext(storeBase, curContext), intersection);
                            for (AllocAndContext curAllocAndContext : sharedAllocContexts) {
                                CallingContextSet upContexts;
                                if (fieldCheckHeuristic.validFromBothEnds(field)) {
                                    upContexts = findUpContextsForVar(curAllocAndContext, new VarContextAndUp(loadBase, EMPTY_CALLSTACK, EMPTY_CALLSTACK));
                                } else {
                                    upContexts = findVarContextsFromAlloc(curAllocAndContext, loadBase);
                                }
                                for (ImmutableStack<Integer> upContext : upContexts) {
                                    p.prop(new VarAndContext(matchTgt, upContext));
                                }
                            }
                        } else {
                            p.prop(new VarAndContext(matchTgt, EMPTY_CALLSTACK));
                        }
                    // h.handleMatchSrc(matchSrc, intersection,
                    // storeBase,
                    // loadBase, varAndContext, checkGetfield);
                    // if (h.terminate())
                    // return;
                    }
                }
            }
        }
        return ret;
    } catch (CallSiteException e) {
        allocAndContextCache.remove(allocAndContext);
        throw e;
    }
}
Also used : GlobalVarNode(soot.jimple.spark.pag.GlobalVarNode) FieldRefNode(soot.jimple.spark.pag.FieldRefNode) GlobalVarNode(soot.jimple.spark.pag.GlobalVarNode) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) Node(soot.jimple.spark.pag.Node) VarNode(soot.jimple.spark.pag.VarNode) AllocNode(soot.jimple.spark.pag.AllocNode) AssignEdge(soot.jimple.spark.ondemand.pautil.AssignEdge) SparkField(soot.jimple.spark.pag.SparkField) Propagator(soot.jimple.spark.ondemand.genericutil.Propagator) HashSet(java.util.HashSet) GlobalVarNode(soot.jimple.spark.pag.GlobalVarNode) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) VarNode(soot.jimple.spark.pag.VarNode) PointsToSetInternal(soot.jimple.spark.sets.PointsToSetInternal) Stack(soot.jimple.spark.ondemand.genericutil.Stack) ImmutableStack(soot.jimple.spark.ondemand.genericutil.ImmutableStack) FieldRefNode(soot.jimple.spark.pag.FieldRefNode) AllocNode(soot.jimple.spark.pag.AllocNode) SootMethod(soot.SootMethod) LocalVarNode(soot.jimple.spark.pag.LocalVarNode)

Example 35 with PointsToSetInternal

use of soot.jimple.spark.sets.PointsToSetInternal in project soot by Sable.

the class DemandCSPointsTo method refineCallSite.

protected Set<SootMethod> refineCallSite(Integer callSite, ImmutableStack<Integer> origContext) {
    CallSiteAndContext callSiteAndContext = new CallSiteAndContext(callSite, origContext);
    if (queriedCallSites.contains(callSiteAndContext)) {
        // }
        return callSiteToResolvedTargets.get(callSiteAndContext);
    }
    if (callGraphStack.contains(callSiteAndContext)) {
        return Collections.<SootMethod>emptySet();
    } else {
        callGraphStack.push(callSiteAndContext);
    }
    final VarNode receiver = csInfo.getReceiverForVirtCallSite(callSite);
    final Type receiverType = receiver.getType();
    final SootMethod invokedMethod = csInfo.getInvokedMethod(callSite);
    final NumberedString methodSig = invokedMethod.getNumberedSubSignature();
    final Set<SootMethod> allTargets = csInfo.getCallSiteTargets(callSite);
    if (!refineCallGraph) {
        callGraphStack.pop();
        return allTargets;
    }
    if (DEBUG_VIRT) {
        debugPrint("refining call to " + invokedMethod + " on " + receiver + " " + origContext);
    }
    final HashSet<VarAndContext> marked = new HashSet<VarAndContext>();
    final Stack<VarAndContext> worklist = new Stack<VarAndContext>();
    final class Helper {

        void prop(VarAndContext varAndContext) {
            if (marked.add(varAndContext)) {
                worklist.push(varAndContext);
            }
        }
    }
    ;
    final Helper h = new Helper();
    h.prop(new VarAndContext(receiver, origContext));
    while (!worklist.isEmpty()) {
        incrementNodesTraversed();
        VarAndContext curVarAndContext = worklist.pop();
        if (DEBUG_VIRT) {
            debugPrint("virt looking at " + curVarAndContext);
        }
        VarNode curVar = curVarAndContext.var;
        ImmutableStack<Integer> curContext = curVarAndContext.context;
        // Set<SootMethod> curVarTargets = getCallTargets(curVar.getP2Set(),
        // methodSig, receiverType, allTargets);
        // if (curVarTargets.size() <= 1) {
        // for (SootMethod method : curVarTargets) {
        // callSiteToResolvedTargets.put(callSiteAndContext, method);
        // }
        // continue;
        // }
        Node[] newNodes = pag.allocInvLookup(curVar);
        for (int i = 0; i < newNodes.length; i++) {
            AllocNode allocNode = (AllocNode) newNodes[i];
            for (SootMethod method : getCallTargetsForType(allocNode.getType(), methodSig, receiverType, allTargets)) {
                callSiteToResolvedTargets.put(callSiteAndContext, method);
            }
        }
        Collection<AssignEdge> assigns = filterAssigns(curVar, curContext, true, true);
        for (AssignEdge assignEdge : assigns) {
            VarNode src = assignEdge.getSrc();
            ImmutableStack<Integer> newContext = curContext;
            if (assignEdge.isParamEdge()) {
                if (!curContext.isEmpty()) {
                    if (!callEdgeInSCC(assignEdge)) {
                        assert assignEdge.getCallSite().equals(curContext.peek());
                        newContext = curContext.pop();
                    } else {
                        newContext = popRecursiveCallSites(curContext);
                    }
                } else {
                    callSiteToResolvedTargets.putAll(callSiteAndContext, allTargets);
                    // }
                    continue;
                }
            } else if (assignEdge.isReturnEdge()) {
                // if (DEBUG)
                // logger.debug("entering call site "
                // + assignEdge.getCallSite());
                // if (!isRecursive(curContext, assignEdge)) {
                // newContext = curContext.push(assignEdge.getCallSite());
                // }
                newContext = pushWithRecursionCheck(curContext, assignEdge);
            } else if (src instanceof GlobalVarNode) {
                newContext = EMPTY_CALLSTACK;
            }
            h.prop(new VarAndContext(src, newContext));
        }
        // TODO respect heuristic
        Set<VarNode> matchSources = vMatches.vMatchInvLookup(curVar);
        final boolean oneMatch = matchSources.size() == 1;
        Node[] loads = pag.loadInvLookup(curVar);
        for (int i = 0; i < loads.length; i++) {
            FieldRefNode frNode = (FieldRefNode) loads[i];
            final VarNode loadBase = frNode.getBase();
            SparkField field = frNode.getField();
            for (Pair<VarNode, VarNode> store : fieldToStores.get(field)) {
                final VarNode storeBase = store.getO2();
                final PointsToSetInternal storeBaseP2Set = storeBase.getP2Set();
                final PointsToSetInternal loadBaseP2Set = loadBase.getP2Set();
                final VarNode matchSrc = store.getO1();
                if (matchSources.contains(matchSrc)) {
                    // optimize for common case of constructor init
                    boolean skipMatch = false;
                    if (oneMatch) {
                        PointsToSetInternal matchSrcPTo = matchSrc.getP2Set();
                        Set<SootMethod> matchSrcCallTargets = getCallTargets(matchSrcPTo, methodSig, receiverType, allTargets);
                        if (matchSrcCallTargets.size() <= 1) {
                            skipMatch = true;
                            for (SootMethod method : matchSrcCallTargets) {
                                callSiteToResolvedTargets.put(callSiteAndContext, method);
                            }
                        }
                    }
                    if (!skipMatch) {
                        final PointsToSetInternal intersection = SootUtil.constructIntersection(storeBaseP2Set, loadBaseP2Set, pag);
                        AllocAndContextSet allocContexts = null;
                        boolean oldRefining = refiningCallSite;
                        int oldNesting = nesting;
                        try {
                            refiningCallSite = true;
                            allocContexts = findContextsForAllocs(new VarAndContext(loadBase, curContext), intersection);
                        } catch (CallSiteException e) {
                            callSiteToResolvedTargets.putAll(callSiteAndContext, allTargets);
                            continue;
                        } finally {
                            refiningCallSite = oldRefining;
                            nesting = oldNesting;
                        }
                        for (AllocAndContext allocAndContext : allocContexts) {
                            CallingContextSet matchSrcContexts;
                            if (fieldCheckHeuristic.validFromBothEnds(field)) {
                                matchSrcContexts = findUpContextsForVar(allocAndContext, new VarContextAndUp(storeBase, EMPTY_CALLSTACK, EMPTY_CALLSTACK));
                            } else {
                                matchSrcContexts = findVarContextsFromAlloc(allocAndContext, storeBase);
                            }
                            for (ImmutableStack<Integer> matchSrcContext : matchSrcContexts) {
                                VarAndContext newVarAndContext = new VarAndContext(matchSrc, matchSrcContext);
                                h.prop(newVarAndContext);
                            }
                        }
                    }
                }
            }
        }
    }
    if (DEBUG_VIRT) {
        debugPrint("call of " + invokedMethod + " on " + receiver + " " + origContext + " goes to " + callSiteToResolvedTargets.get(callSiteAndContext));
    }
    callGraphStack.pop();
    queriedCallSites.add(callSiteAndContext);
    return callSiteToResolvedTargets.get(callSiteAndContext);
}
Also used : GlobalVarNode(soot.jimple.spark.pag.GlobalVarNode) FieldRefNode(soot.jimple.spark.pag.FieldRefNode) GlobalVarNode(soot.jimple.spark.pag.GlobalVarNode) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) Node(soot.jimple.spark.pag.Node) VarNode(soot.jimple.spark.pag.VarNode) AllocNode(soot.jimple.spark.pag.AllocNode) AssignEdge(soot.jimple.spark.ondemand.pautil.AssignEdge) SparkField(soot.jimple.spark.pag.SparkField) HashSet(java.util.HashSet) GlobalVarNode(soot.jimple.spark.pag.GlobalVarNode) LocalVarNode(soot.jimple.spark.pag.LocalVarNode) VarNode(soot.jimple.spark.pag.VarNode) NumberedString(soot.util.NumberedString) PointsToSetInternal(soot.jimple.spark.sets.PointsToSetInternal) Stack(soot.jimple.spark.ondemand.genericutil.Stack) ImmutableStack(soot.jimple.spark.ondemand.genericutil.ImmutableStack) RefType(soot.RefType) AnySubType(soot.AnySubType) Type(soot.Type) ArrayType(soot.ArrayType) FieldRefNode(soot.jimple.spark.pag.FieldRefNode) AllocNode(soot.jimple.spark.pag.AllocNode) SootMethod(soot.SootMethod)

Aggregations

PointsToSetInternal (soot.jimple.spark.sets.PointsToSetInternal)37 AllocNode (soot.jimple.spark.pag.AllocNode)32 VarNode (soot.jimple.spark.pag.VarNode)28 Node (soot.jimple.spark.pag.Node)25 FieldRefNode (soot.jimple.spark.pag.FieldRefNode)22 LocalVarNode (soot.jimple.spark.pag.LocalVarNode)15 P2SetVisitor (soot.jimple.spark.sets.P2SetVisitor)15 SparkField (soot.jimple.spark.pag.SparkField)12 ClassConstantNode (soot.jimple.spark.pag.ClassConstantNode)9 GlobalVarNode (soot.jimple.spark.pag.GlobalVarNode)9 NewInstanceNode (soot.jimple.spark.pag.NewInstanceNode)9 HashSet (java.util.HashSet)8 AllocDotField (soot.jimple.spark.pag.AllocDotField)8 SootMethod (soot.SootMethod)7 AssignEdge (soot.jimple.spark.ondemand.pautil.AssignEdge)7 Type (soot.Type)5 ImmutableStack (soot.jimple.spark.ondemand.genericutil.ImmutableStack)5 Stack (soot.jimple.spark.ondemand.genericutil.Stack)5 ContextVarNode (soot.jimple.spark.pag.ContextVarNode)5 Propagator (soot.jimple.spark.ondemand.genericutil.Propagator)4