use of soot.jimple.spark.pag.LocalVarNode in project soot by Sable.
the class EvalResults method checkCallGraph.
/**
* Report the virtual callsites resolution result for the user's code.
*/
public void checkCallGraph() {
int[] limits = new int[] { 1, 2, 4, 8 };
evalRes.total_call_edges = new Histogram(limits);
CallGraph cg = Scene.v().getCallGraph();
for (Stmt callsite : ptsProvider.multiCallsites) {
Iterator<Edge> edges = cg.edgesOutOf(callsite);
if (!edges.hasNext())
continue;
evalRes.n_callsites++;
// get an edge
Edge anyEdge = edges.next();
SootMethod src = anyEdge.src();
if (!ptsProvider.isReachableMethod(src) || !ptsProvider.isValidMethod(src))
continue;
// get the base pointer
CgEdge p = ptsProvider.getInternalEdgeFromSootEdge(anyEdge);
LocalVarNode vn = (LocalVarNode) p.base_var;
// test the call graph
int edge_cnt = 1;
while (edges.hasNext()) {
++edge_cnt;
edges.next();
}
evalRes.n_geom_call_edges += edge_cnt;
if (edge_cnt == 1)
++evalRes.n_geom_solved_all;
// test app method
if (!src.isJavaLibraryMethod()) {
InvokeExpr ie = callsite.getInvokeExpr();
if (edge_cnt == 1) {
++evalRes.n_geom_solved_app;
if (ptsProvider.getOpts().verbose()) {
outputer.println();
outputer.println("<<<<<<<<< Additional Solved Call >>>>>>>>>>");
outputer.println(src.toString());
outputer.println(ie.toString());
}
} else {
// We try to test if this callsite is solvable
// under some contexts
Histogram call_edges = new Histogram(limits);
test_1cfa_call_graph(vn, src, ie.getMethod(), call_edges);
evalRes.total_call_edges.merge(call_edges);
call_edges = null;
}
evalRes.n_geom_user_edges += edge_cnt;
evalRes.n_user_callsites++;
}
}
ptsProvider.ps.println();
ptsProvider.ps.println("--------> Virtual Callsites Evaluation <---------");
ptsProvider.ps.printf("Total virtual callsites (app code): %d (%d)\n", evalRes.n_callsites, evalRes.n_user_callsites);
ptsProvider.ps.printf("Total virtual call edges (app code): %d (%d)\n", evalRes.n_geom_call_edges, evalRes.n_geom_user_edges);
ptsProvider.ps.printf("Virtual callsites additionally solved by geomPTA compared to SPARK (app code) = %d (%d)\n", evalRes.n_geom_solved_all, evalRes.n_geom_solved_app);
evalRes.total_call_edges.printResult(ptsProvider.ps, "Testing of unsolved callsites on 1-CFA call graph: ");
if (ptsProvider.getOpts().verbose())
ptsProvider.outputNotEvaluatedMethods();
}
use of soot.jimple.spark.pag.LocalVarNode in project soot by Sable.
the class DemandCSPointsTo method getFlowsToHelper.
protected Set<VarNode> getFlowsToHelper(AllocAndContext allocAndContext) {
Set<VarNode> ret = new ArraySet<VarNode>();
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];
ret.add(v);
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;
ret.add(curVar);
// 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.LocalVarNode in project soot by Sable.
the class GeomQueries method kCFA.
/**
* Standard K-CFA querying for arbitrary K.
*
* @param callEdgeChain: last K call edges leading to the method that contains l. callEdgeChain[0] is the farthest call edge in the chain.
* @param l: the querying pointer
* @param visitor: the querying result container
* @return false, l does not have points-to information under the given context
*/
@SuppressWarnings("rawtypes")
public boolean kCFA(Edge[] callEdgeChain, Local l, PtSensVisitor visitor) {
// Prepare for initial contexts
SootMethod firstMethod = callEdgeChain[0].src();
int firstMethodID = geomPTA.getIDFromSootMethod(firstMethod);
if (firstMethodID == -1)
return false;
// Obtain the internal representation for querying pointer
LocalVarNode vn = geomPTA.findLocalVarNode(l);
if (vn == null) {
// Normally this could not happen, perhaps it's a bug
return false;
}
IVarAbstraction pn = geomPTA.findInternalNode(vn);
if (pn == null) {
// This pointer is no longer reachable
return false;
}
pn = pn.getRepresentative();
if (!pn.hasPTResult())
return false;
SootMethod sm = vn.getMethod();
if (geomPTA.getIDFromSootMethod(sm) == -1)
return false;
// Iterate the call edges and compute the contexts mapping iteratively
visitor.prepare();
long L = 1;
for (int i = 0; i < callEdgeChain.length; ++i) {
Edge sootEdge = callEdgeChain[i];
CgEdge ctxt = geomPTA.getInternalEdgeFromSootEdge(sootEdge);
if (ctxt == null || ctxt.is_obsoleted == true)
return false;
// Following searching procedure works for both methods in SCC and out of SCC
// with blocking scheme or without blocking scheme
int caller = geomPTA.getIDFromSootMethod(sootEdge.src());
// We obtain the block that contains current offset L
long block_size = max_context_size_block[rep_cg[caller]];
long in_block_offset = (L - 1) % block_size;
// Transfer to the target block with the same in-block offset
L = ctxt.map_offset + in_block_offset;
}
long ctxtLength = max_context_size_block[rep_cg[firstMethodID]];
long R = L + ctxtLength;
pn.get_all_context_sensitive_objects(L, R, visitor);
visitor.finish();
return visitor.numOfDiffObjects() != 0;
}
use of soot.jimple.spark.pag.LocalVarNode in project soot by Sable.
the class GeomQueries method contextsGoBy.
/**
* Answer contexts-go-by query.
*
* Usually, users specify the last K paths as the context. We call it k-CFA context.
* However, k-CFA is too restrictive.
* In contexts-go-by query, user specifies arbitrary call edge in the call graph.
* The query searches for all contexts induced by the specified call edge and collect points-to results under these contexts.
*
* @param sootEdge: the specified context edge in soot edge format
* @param l: the querying pointer
* @param visitor: container for querying result
* @return false, l does not have points-to information under the contexts induced by the given call edge
*/
@SuppressWarnings("rawtypes")
public boolean contextsGoBy(Edge sootEdge, Local l, PtSensVisitor visitor) {
// Obtain the internal representation of specified context
CgEdge ctxt = geomPTA.getInternalEdgeFromSootEdge(sootEdge);
if (ctxt == null || ctxt.is_obsoleted == true)
return false;
// Obtain the internal representation for querying pointer
LocalVarNode vn = geomPTA.findLocalVarNode(l);
if (vn == null) {
// Normally this could not happen, perhaps it's a bug
return false;
}
IVarAbstraction pn = geomPTA.findInternalNode(vn);
if (pn == null) {
// This pointer is no longer reachable
return false;
}
pn = pn.getRepresentative();
if (!pn.hasPTResult())
return false;
// Obtain the internal representation of the method that encloses the querying pointer
SootMethod sm = vn.getMethod();
int target = geomPTA.getIDFromSootMethod(sm);
if (target == -1)
return false;
// Start call graph traversal
long L = ctxt.map_offset;
long R = L + max_context_size_block[rep_cg[ctxt.s]];
assert L < R;
visitor.prepare();
prepareIntervalPropagations();
if (propagateIntervals(ctxt.t, L, R, target)) {
// We calculate the points-to results
ContextsCollector targetContexts = contextsForMethods[target];
for (SimpleInterval si : targetContexts.bars) {
assert si.L < si.R;
pn.get_all_context_sensitive_objects(si.L, si.R, visitor);
}
// Reset
targetContexts.clear();
}
visitor.finish();
return visitor.numOfDiffObjects() != 0;
}
use of soot.jimple.spark.pag.LocalVarNode in project soot by Sable.
the class GeomQueries method isAlias.
/**
* Decide if under any contexts, pointers @param l1 and @param l2 can be an alias.
*/
public boolean isAlias(Local l1, Local l2) {
// Obtain the internal representation for querying pointers
LocalVarNode vn1 = geomPTA.findLocalVarNode(l1);
LocalVarNode vn2 = geomPTA.findLocalVarNode(l2);
if (vn1 == null || vn2 == null) {
// Normally this could not happen, perhaps it's a bug
return false;
}
IVarAbstraction pn1 = geomPTA.findInternalNode(vn1);
IVarAbstraction pn2 = geomPTA.findInternalNode(vn2);
if (pn1 == null || pn2 == null) {
return isAliasCI(l1, l2);
}
pn1 = pn1.getRepresentative();
pn2 = pn2.getRepresentative();
if (!pn1.hasPTResult() || !pn2.hasPTResult()) {
return isAliasCI(l1, l2);
}
return pn1.heap_sensitive_intersection(pn2);
}
Aggregations