use of soot.jimple.toolkits.callgraph.CallGraph in project soot by Sable.
the class GeomPointsTo method updateCallGraph.
/**
* Remove unreachable call targets at the virtual callsites using the up-to-date points-to information.
*/
private int updateCallGraph() {
int all_virtual_edges = 0, n_obsoleted = 0;
CallGraph cg = Scene.v().getCallGraph();
ChunkedQueue<SootMethod> targetsQueue = new ChunkedQueue<SootMethod>();
QueueReader<SootMethod> targets = targetsQueue.reader();
Set<SootMethod> resolvedMethods = new HashSet<SootMethod>();
// We first update the virtual callsites
for (Iterator<Stmt> csIt = multiCallsites.iterator(); csIt.hasNext(); ) {
Stmt callsite = csIt.next();
Iterator<Edge> edges = cg.edgesOutOf(callsite);
if (!edges.hasNext()) {
csIt.remove();
continue;
}
Edge anyEdge = edges.next();
CgEdge p = edgeMapping.get(anyEdge);
SootMethod src = anyEdge.src();
if (!isReachableMethod(src)) {
// The source method is no longer reachable
// We move this callsite
csIt.remove();
continue;
}
if (!edges.hasNext()) {
// We keep this resolved site for call graph profiling
continue;
}
IVarAbstraction pn = consG.get(p.base_var);
if (pn != null) {
pn = pn.getRepresentative();
// We resolve the call targets with the new points-to result
getCallTargets(pn, src, callsite, targetsQueue);
resolvedMethods.clear();
while (targets.hasNext()) {
resolvedMethods.add(targets.next());
}
// We delete the edges that are proven to be spurious
while (true) {
SootMethod tgt = anyEdge.tgt();
if (!resolvedMethods.contains(tgt) && !anyEdge.kind().isFake()) {
p = edgeMapping.get(anyEdge);
p.is_obsoleted = true;
}
if (!edges.hasNext())
break;
anyEdge = edges.next();
}
}
}
// We delete the spurious edges
for (int i = 1; i < n_func; ++i) {
// New outgoing edge list is pointed to by q
CgEdge p = call_graph[i];
CgEdge q = null;
while (p != null) {
if (vis_cg[i] == 0) {
// If this method is unreachable, we delete all its outgoing edges
p.is_obsoleted = true;
}
if (p.base_var != null) {
++all_virtual_edges;
}
CgEdge temp = p.next;
if (p.is_obsoleted == false) {
p.next = q;
q = p;
} else {
// Update the corresponding SOOT call graph
// ps.println("%%% Remove an call edge: " + p.toString());
cg.removeEdge(p.sootEdge);
// We record this obsoleted edge
// obsoletedEdges.add(p);
++n_obsoleted;
}
p = temp;
}
call_graph[i] = q;
}
ps.printf("%d of %d virtual call edges are proved to be spurious.\n", n_obsoleted, all_virtual_edges);
return n_obsoleted;
}
use of soot.jimple.toolkits.callgraph.CallGraph in project soot by Sable.
the class GeomPointsTo method preprocess.
/**
* Read in the program facts generated by SPARK.
* We also construct our own call graph and pointer variables.
*/
private void preprocess() {
int id;
int s, t;
// Build the call graph
n_func = Scene.v().getReachableMethods().size() + 1;
call_graph = new CgEdge[n_func];
n_calls = 0;
n_reach_spark_user_methods = 0;
id = 1;
QueueReader<MethodOrMethodContext> smList = Scene.v().getReachableMethods().listener();
CallGraph soot_callgraph = Scene.v().getCallGraph();
while (smList.hasNext()) {
final SootMethod func = smList.next().method();
func2int.put(func, id);
int2func.put(id, func);
/*
* We cannot identify all entry methods since some entry methods call themselves.
* In that case, the Soot CallGraph.isEntryMethod() function returns false.
*/
if (soot_callgraph.isEntryMethod(func) || func.isEntryMethod()) {
CgEdge p = new CgEdge(Constants.SUPER_MAIN, id, null, call_graph[Constants.SUPER_MAIN]);
call_graph[Constants.SUPER_MAIN] = p;
n_calls++;
}
if (!func.isJavaLibraryMethod())
++n_reach_spark_user_methods;
id++;
}
// Next, we scan all the call edges and rebuild the call graph in our own vocabulary
QueueReader<Edge> edgeList = Scene.v().getCallGraph().listener();
while (edgeList.hasNext()) {
Edge edge = edgeList.next();
if (edge.isClinit()) {
continue;
}
SootMethod src_func = edge.src();
SootMethod tgt_func = edge.tgt();
s = func2int.get(src_func);
t = func2int.get(tgt_func);
// Create a new call edge in our own format
CgEdge p = new CgEdge(s, t, edge, call_graph[s]);
call_graph[s] = p;
edgeMapping.put(edge, p);
// We collect callsite information
Stmt callsite = edge.srcStmt();
if (edge.isThreadRunCall() || edge.kind().isExecutor() || edge.kind().isAsyncTask()) {
// We don't modify the treatment to the thread run() calls
thread_run_callsites.add(callsite);
} else if (edge.isInstance() && !edge.isSpecial()) {
// We try to refine the virtual callsites (virtual + interface) with multiple call targets
InstanceInvokeExpr expr = (InstanceInvokeExpr) callsite.getInvokeExpr();
if (expr.getMethodRef().getSignature().contains("<java.lang.Thread: void start()>")) {
// It is a thread start function
thread_run_callsites.add(callsite);
} else {
p.base_var = findLocalVarNode(expr.getBase());
if (SootInfo.countCallEdgesForCallsite(callsite, true) > 1 && p.base_var != null) {
multiCallsites.add(callsite);
}
}
}
++n_calls;
}
// We build the wrappers for all the pointers built by SPARK
for (Iterator<VarNode> it = getVarNodeNumberer().iterator(); it.hasNext(); ) {
VarNode vn = it.next();
IVarAbstraction pn = makeInternalNode(vn);
pointers.add(pn);
}
for (Iterator<AllocDotField> it = getAllocDotFieldNodeNumberer().iterator(); it.hasNext(); ) {
AllocDotField adf = it.next();
// Some allocdotfield is invalid, we check and remove them
SparkField field = adf.getField();
if (field instanceof SootField) {
// This is an instance field of a class
Type decType = ((SootField) field).getDeclaringClass().getType();
Type baseType = adf.getBase().getType();
// baseType must be a sub type of decType
if (!castNeverFails(baseType, decType))
continue;
}
IVarAbstraction pn = makeInternalNode(adf);
pointers.add(pn);
}
for (Iterator<AllocNode> it = getAllocNodeNumberer().iterator(); it.hasNext(); ) {
AllocNode obj = it.next();
IVarAbstraction pn = makeInternalNode(obj);
allocations.add(pn);
}
// The address constraints, new obj -> p
for (Object object : allocSources()) {
IVarAbstraction obj = makeInternalNode((AllocNode) object);
Node[] succs = allocLookup((AllocNode) object);
for (Node element0 : succs) {
PlainConstraint cons = new PlainConstraint();
IVarAbstraction p = makeInternalNode(element0);
cons.expr.setPair(obj, p);
cons.type = Constants.NEW_CONS;
constraints.add(cons);
}
}
// The assign constraints, p -> q
Pair<Node, Node> intercall = new Pair<Node, Node>();
for (Object object : simpleSources()) {
IVarAbstraction p = makeInternalNode((VarNode) object);
Node[] succs = simpleLookup((VarNode) object);
for (Node element0 : succs) {
PlainConstraint cons = new PlainConstraint();
IVarAbstraction q = makeInternalNode(element0);
cons.expr.setPair(p, q);
cons.type = Constants.ASSIGN_CONS;
intercall.setPair((VarNode) object, element0);
cons.interCallEdges = lookupEdgesForAssignment(intercall);
constraints.add(cons);
}
}
intercall = null;
assign2edges.clear();
// The load constraints, p.f -> q
for (Object object : loadSources()) {
FieldRefNode frn = (FieldRefNode) object;
IVarAbstraction p = makeInternalNode(frn.getBase());
Node[] succs = loadLookup(frn);
for (Node element0 : succs) {
PlainConstraint cons = new PlainConstraint();
IVarAbstraction q = makeInternalNode(element0);
cons.f = frn.getField();
cons.expr.setPair(p, q);
cons.type = Constants.LOAD_CONS;
constraints.add(cons);
}
}
// The store constraints, p -> q.f
for (Object object : storeSources()) {
IVarAbstraction p = makeInternalNode((VarNode) object);
Node[] succs = storeLookup((VarNode) object);
for (Node element0 : succs) {
PlainConstraint cons = new PlainConstraint();
FieldRefNode frn = (FieldRefNode) element0;
IVarAbstraction q = makeInternalNode(frn.getBase());
cons.f = frn.getField();
cons.expr.setPair(p, q);
cons.type = Constants.STORE_CONS;
constraints.add(cons);
}
}
n_init_constraints = constraints.size();
// Initialize other stuff
low_cg = new int[n_func];
vis_cg = new int[n_func];
rep_cg = new int[n_func];
indeg_cg = new int[n_func];
scc_size = new int[n_func];
block_num = new int[n_func];
context_size = new long[n_func];
max_context_size_block = new long[n_func];
}
use of soot.jimple.toolkits.callgraph.CallGraph 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.toolkits.callgraph.CallGraph in project soot by Sable.
the class SootInfo method countCallEdgesForCallsite.
public static int countCallEdgesForCallsite(Stmt callsite, boolean stopForMutiple) {
CallGraph cg = Scene.v().getCallGraph();
int count = 0;
for (Iterator<Edge> it = cg.edgesOutOf(callsite); it.hasNext(); ) {
it.next();
++count;
if (stopForMutiple && count > 1)
break;
}
return count;
}
use of soot.jimple.toolkits.callgraph.CallGraph in project soot by Sable.
the class MultiCalledMethods method byMCalledS0.
private void byMCalledS0(PegCallGraph pcg) {
Iterator it = pcg.iterator();
while (it.hasNext()) {
SootMethod sm = (SootMethod) it.next();
UnitGraph graph = new CompleteUnitGraph(sm.getActiveBody());
CallGraph callGraph = Scene.v().getCallGraph();
MultiRunStatementsFinder finder = new MultiRunStatementsFinder(graph, sm, multiCalledMethods, callGraph);
FlowSet fs = finder.getMultiRunStatements();
}
}
Aggregations