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;
}
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;
}
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;
}
}
}
}
}
}
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;
}
}
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);
}
Aggregations