package jqian.sootex.util.callgraph;
import soot.*;
import soot.jimple.toolkits.callgraph.*;
import java.io.PrintStream;
import java.util.*;
/**
*/
public class CallGraphTracer{
private CallGraph _cg;
public CallGraphTracer(CallGraph cg){
this._cg = cg;
}
static class Pair {
public Pair(SootMethod m, LinkedList<SootMethod> tr) {
this.method = m;
this.trace = tr;
}
SootMethod method;
LinkedList<SootMethod> trace;
}
//FIXME Seems there is a dead loop.
@SuppressWarnings("unchecked")
public Collection<List<SootMethod>> findTraces(SootMethod start) {
Collection<List<SootMethod>> traces = new LinkedList<List<SootMethod>>();
Stack<Pair> stack = new Stack<Pair>();
Pair pair = new Pair(start, new LinkedList<SootMethod>());
stack.push(pair);
while (!stack.isEmpty()) {
Pair p = (Pair) stack.pop();
p.trace.add(p.method); //add an element to the trace
Iterator<Edge> inEdges = _cg.edgesInto(p.method);
if (inEdges.hasNext()) {
do {
Edge edge = (Edge) inEdges.next();
if (p.trace.contains(edge.src()))//avoid infinite loops
continue;
LinkedList<SootMethod> newTrace = (LinkedList<SootMethod>)p.trace.clone();
Pair newPair = new Pair(edge.src(), newTrace);
stack.push(newPair);
break;
} while (inEdges.hasNext());
}
else {
traces.add(p.trace);
}
}
return traces;
}
@SuppressWarnings("rawtypes")
public static void printTraces(Collection<List> traces, PrintStream out) {
for (List tr: traces) {
out.println("================================ Trace ===============================");
for (Iterator mIt = tr.iterator(); mIt.hasNext();) {
SootMethod m = (SootMethod) mIt.next();
out.println(" " + m);
}
}
}
}