Search in sources :

Example 6 with Stack

use of soot.jimple.spark.ondemand.genericutil.Stack 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

HashSet (java.util.HashSet)6 ImmutableStack (soot.jimple.spark.ondemand.genericutil.ImmutableStack)6 Stack (soot.jimple.spark.ondemand.genericutil.Stack)6 AllocNode (soot.jimple.spark.pag.AllocNode)6 GlobalVarNode (soot.jimple.spark.pag.GlobalVarNode)6 LocalVarNode (soot.jimple.spark.pag.LocalVarNode)6 VarNode (soot.jimple.spark.pag.VarNode)6 Propagator (soot.jimple.spark.ondemand.genericutil.Propagator)5 AssignEdge (soot.jimple.spark.ondemand.pautil.AssignEdge)5 SparkField (soot.jimple.spark.pag.SparkField)5 PointsToSetInternal (soot.jimple.spark.sets.PointsToSetInternal)5 FieldRefNode (soot.jimple.spark.pag.FieldRefNode)4 Node (soot.jimple.spark.pag.Node)4 SootMethod (soot.SootMethod)3 HybridPointsToSet (soot.jimple.spark.sets.HybridPointsToSet)2 AnySubType (soot.AnySubType)1 ArrayType (soot.ArrayType)1 RefType (soot.RefType)1 Type (soot.Type)1 ArraySet (soot.jimple.spark.ondemand.genericutil.ArraySet)1