use of soot.jimple.spark.geom.dataRep.CgEdge 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.geom.dataRep.CgEdge in project soot by Sable.
the class PtInsNodeGenerator method initFlowGraph.
@Override
public void initFlowGraph(GeomPointsTo ptAnalyzer) {
int k;
int n_legal_cons;
int nf1, nf2;
int code;
CgEdge q;
IVarAbstraction my_lhs, my_rhs;
// Visit all the simple constraints
n_legal_cons = 0;
for (PlainConstraint cons : ptAnalyzer.constraints) {
if (!cons.isActive)
continue;
my_lhs = cons.getLHS().getRepresentative();
my_rhs = cons.getRHS().getRepresentative();
nf1 = ptAnalyzer.getMethodIDFromPtr(my_lhs);
nf2 = ptAnalyzer.getMethodIDFromPtr(my_rhs);
// Test how many globals are in this constraint
code = ((nf1 == Constants.SUPER_MAIN ? 1 : 0) << 1) | (nf2 == Constants.SUPER_MAIN ? 1 : 0);
switch(cons.type) {
case Constants.NEW_CONS:
// We directly add the objects to the points-to set
my_rhs.add_points_to_3((AllocNode) my_lhs.getWrappedNode(), nf2 == Constants.SUPER_MAIN ? 0 : 1, nf1 == Constants.SUPER_MAIN ? 0 : 1, nf2 == Constants.SUPER_MAIN ? ptAnalyzer.context_size[nf1] : ptAnalyzer.context_size[nf2]);
// Enqueue to the worklist
ptAnalyzer.getWorklist().push(my_rhs);
break;
case Constants.ASSIGN_CONS:
// The core part of any context sensitive algorithms
if (cons.interCallEdges != null) {
// Inter-procedural assignment
for (Iterator<Edge> it = cons.interCallEdges.iterator(); it.hasNext(); ) {
Edge sEdge = it.next();
q = ptAnalyzer.getInternalEdgeFromSootEdge(sEdge);
if (q.is_obsoleted == true) {
continue;
}
if (nf2 == q.t) {
// The receiver is a local, while the sender is perhaps not
if (nf1 == Constants.SUPER_MAIN) {
my_lhs.add_simple_constraint_3(my_rhs, 0, q.map_offset, ptAnalyzer.max_context_size_block[q.s]);
} else {
// We should treat the self recursive calls specially
if (q.s == q.t) {
my_lhs.add_simple_constraint_3(my_rhs, 1, 1, ptAnalyzer.context_size[nf1]);
} else {
for (k = 0; k < ptAnalyzer.block_num[nf1]; ++k) {
my_lhs.add_simple_constraint_3(my_rhs, k * ptAnalyzer.max_context_size_block[nf1] + 1, q.map_offset, ptAnalyzer.max_context_size_block[nf1]);
}
}
}
} else {
if (q.s == q.t) {
my_lhs.add_simple_constraint_3(my_rhs, 1, 1, ptAnalyzer.context_size[nf2]);
} else {
for (k = 0; k < ptAnalyzer.block_num[nf2]; ++k) {
my_lhs.add_simple_constraint_3(my_rhs, q.map_offset, k * ptAnalyzer.max_context_size_block[nf2] + 1, ptAnalyzer.max_context_size_block[nf2]);
}
}
}
}
} else {
// Intraprocedural
// And, assignment involves global variable goes here. By
// definition, global variables belong to SUPER_MAIN.
// By the Jimple IR, not both sides are global variables
my_lhs.add_simple_constraint_3(my_rhs, nf1 == Constants.SUPER_MAIN ? 0 : 1, nf2 == Constants.SUPER_MAIN ? 0 : 1, nf1 == Constants.SUPER_MAIN ? ptAnalyzer.context_size[nf2] : ptAnalyzer.context_size[nf1]);
}
break;
case Constants.LOAD_CONS:
// lhs is always a local
// rhs = lhs.f
cons.code = full_convertor[code];
cons.otherSide = my_rhs;
my_lhs.put_complex_constraint(cons);
break;
case Constants.STORE_CONS:
// rhs is always a local
// rhs.f = lhs
cons.code = full_convertor[code];
cons.otherSide = my_lhs;
my_rhs.put_complex_constraint(cons);
break;
default:
throw new RuntimeException("Invalid node type");
}
++n_legal_cons;
}
ptAnalyzer.ps.printf("Only %d (%.1f%%) constraints are needed for this run.\n", n_legal_cons, ((double) n_legal_cons / ptAnalyzer.n_init_constraints) * 100);
}
use of soot.jimple.spark.geom.dataRep.CgEdge 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.geom.dataRep.CgEdge in project soot by Sable.
the class GeomQueries method dfsScanSubgraph.
/**
* Retrieve the subgraph from s->target.
* An edge s->t is included in the subgraph iff target is reachable from t.
* @param s
* @param target
* @return
*/
protected boolean dfsScanSubgraph(int s, int target) {
int rep_s = rep_cg[s];
int rep_target = rep_cg[target];
if (rep_s == rep_target)
return true;
s = rep_s;
boolean reachable = false;
// We only traverse the SCC representatives
CgEdge p = call_graph[s];
while (p != null) {
int t = p.t;
int rep_t = rep_cg[t];
if (in_degree[rep_t] != 0 || (top_rank[rep_t] <= top_rank[rep_target] && dfsScanSubgraph(t, target) == true)) {
in_degree[rep_t]++;
reachable = true;
}
p = p.next;
}
return reachable;
}
use of soot.jimple.spark.geom.dataRep.CgEdge 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;
}
Aggregations