use of soot.jimple.spark.pag.SparkField 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;
}
}
}
}
}
}
use of soot.jimple.spark.pag.SparkField 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;
}
}
use of soot.jimple.spark.pag.SparkField 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);
}
use of soot.jimple.spark.pag.SparkField in project soot by Sable.
the class SootUtil method storesOnField.
public static FieldToEdgesMap storesOnField(PAG pag) {
FieldToEdgesMap storesOnField = new FieldToEdgesMap();
Iterator frNodeIter = pag.storeInvSourcesIterator();
while (frNodeIter.hasNext()) {
FieldRefNode frNode = (FieldRefNode) frNodeIter.next();
VarNode source = frNode.getBase();
SparkField field = frNode.getField();
Node[] targets = pag.storeInvLookup(frNode);
for (int i = 0; i < targets.length; i++) {
VarNode target = (VarNode) targets[i];
storesOnField.put(field, new Pair<VarNode, VarNode>(target, source));
}
}
return storesOnField;
}
Aggregations