use of soot.MethodOrMethodContext 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.MethodOrMethodContext in project soot by Sable.
the class DeadlockDetector method detectComponentBasedDeadlock.
public MutableDirectedGraph<CriticalSectionGroup> detectComponentBasedDeadlock() {
MutableDirectedGraph<CriticalSectionGroup> lockOrder;
boolean foundDeadlock;
int iteration = 0;
do {
iteration++;
logger.debug("[DeadlockDetector] Deadlock Iteration #" + iteration);
foundDeadlock = false;
// start each iteration with a fresh graph
lockOrder = new HashMutableDirectedGraph<CriticalSectionGroup>();
// Assemble the partial ordering of locks
Iterator<CriticalSection> deadlockIt1 = criticalSections.iterator();
while (deadlockIt1.hasNext() && !foundDeadlock) {
CriticalSection tn1 = deadlockIt1.next();
// skip if unlocked
if (tn1.setNumber <= 0) {
continue;
}
// add a node for this set
if (!lockOrder.containsNode(tn1.group)) {
lockOrder.addNode(tn1.group);
}
// 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() && (!optionRepairDeadlock || !foundDeadlock)) {
CriticalSection tn2 = deadlockIt2.next();
// skip if unlocked or in same set as tn1
if (// this is wrong... dynamic locks in same group can be diff locks
tn2.setNumber <= 0 || (tn2.setNumber == tn1.setNumber && !optionAllowSelfEdges)) {
continue;
}
// add a node for this set
if (!lockOrder.containsNode(tn2.group)) {
lockOrder.addNode(tn2.group);
}
if (tn1.transitiveTargets.contains(tn2.method)) {
// This implies the partial ordering tn1lock before tn2lock
if (optionPrintDebug) {
logger.debug("group" + (tn1.setNumber) + " before group" + (tn2.setNumber) + ": " + "outer: " + tn1.name + " inner: " + tn2.name);
}
// Check if tn2lock before tn1lock is in our lock order
List<CriticalSectionGroup> afterTn2 = new ArrayList<CriticalSectionGroup>();
afterTn2.addAll(lockOrder.getSuccsOf(tn2.group));
for (int i = 0; i < afterTn2.size(); i++) {
for (CriticalSectionGroup o : lockOrder.getSuccsOf(afterTn2.get(i))) {
if (!afterTn2.contains(o)) {
afterTn2.add(o);
}
}
}
if (afterTn2.contains(tn1.group)) {
if (!optionRepairDeadlock) {
logger.debug("[DeadlockDetector] DEADLOCK HAS BEEN DETECTED: not correcting");
foundDeadlock = true;
} else {
logger.debug("[DeadlockDetector] DEADLOCK HAS BEEN DETECTED: merging group" + (tn1.setNumber) + " and group" + (tn2.setNumber) + " and restarting deadlock detection");
if (optionPrintDebug) {
logger.debug("tn1.setNumber was " + tn1.setNumber + " and tn2.setNumber was " + tn2.setNumber);
logger.debug("tn1.group.size was " + tn1.group.criticalSections.size() + " and tn2.group.size was " + tn2.group.criticalSections.size());
logger.debug("tn1.group.num was " + tn1.group.num() + " and tn2.group.num was " + tn2.group.num());
}
tn1.group.mergeGroups(tn2.group);
if (optionPrintDebug) {
logger.debug("tn1.setNumber is " + tn1.setNumber + " and tn2.setNumber is " + tn2.setNumber);
logger.debug("tn1.group.size is " + tn1.group.criticalSections.size() + " and tn2.group.size is " + tn2.group.criticalSections.size());
}
foundDeadlock = true;
}
}
lockOrder.addEdge(tn1.group, tn2.group);
}
}
}
} while (foundDeadlock && optionRepairDeadlock);
return lockOrder;
}
use of soot.MethodOrMethodContext in project soot by Sable.
the class CallGraphExample method main.
public static void main(String[] args) {
List<String> argsList = new ArrayList<String>(Arrays.asList(args));
argsList.addAll(Arrays.asList(new String[] { "-w", "-main-class", // main-class
"testers.CallGraphs", // argument classes
"testers.CallGraphs", //
"testers.A" }));
PackManager.v().getPack("wjtp").add(new Transform("wjtp.myTrans", new SceneTransformer() {
@Override
protected void internalTransform(String phaseName, Map options) {
CHATransformer.v().transform();
SootClass a = Scene.v().getSootClass("testers.A");
SootMethod src = Scene.v().getMainClass().getMethodByName("doStuff");
CallGraph cg = Scene.v().getCallGraph();
Iterator<MethodOrMethodContext> targets = new Targets(cg.edgesOutOf(src));
while (targets.hasNext()) {
SootMethod tgt = (SootMethod) targets.next();
System.out.println(src + " may call " + tgt);
}
}
}));
args = argsList.toArray(new String[0]);
soot.Main.main(args);
}
use of soot.MethodOrMethodContext in project soot by Sable.
the class LocalMustAliasAnalysis method trackableFields.
/**
* Computes the set of {@link EquivalentValue}s of all field references that are used
* in this method but not set by the method or any method transitively called by this method.
*/
private Set<Value> trackableFields() {
Set<Value> usedFieldRefs = new HashSet<Value>();
// add all field references that are in use boxes
for (Unit unit : this.graph) {
Stmt s = (Stmt) unit;
List<ValueBox> useBoxes = s.getUseBoxes();
for (ValueBox useBox : useBoxes) {
Value val = useBox.getValue();
if (val instanceof FieldRef) {
FieldRef fieldRef = (FieldRef) val;
if (fieldRef.getType() instanceof RefLikeType)
usedFieldRefs.add(new EquivalentValue(fieldRef));
}
}
}
// prune all fields that are written to
if (!usedFieldRefs.isEmpty()) {
if (!Scene.v().hasCallGraph()) {
throw new IllegalStateException("No call graph found!");
}
CallGraph cg = Scene.v().getCallGraph();
ReachableMethods reachableMethods = new ReachableMethods(cg, Collections.<MethodOrMethodContext>singletonList(container));
reachableMethods.update();
for (Iterator<MethodOrMethodContext> iterator = reachableMethods.listener(); iterator.hasNext(); ) {
SootMethod m = (SootMethod) iterator.next();
if (m.hasActiveBody() && // exclude static initializer of same class (assume that it has already been executed)
!(m.getName().equals(SootMethod.staticInitializerName) && m.getDeclaringClass().equals(container.getDeclaringClass()))) {
for (Unit u : m.getActiveBody().getUnits()) {
List<ValueBox> defBoxes = u.getDefBoxes();
for (ValueBox defBox : defBoxes) {
Value value = defBox.getValue();
if (value instanceof FieldRef) {
usedFieldRefs.remove(new EquivalentValue(value));
}
}
}
}
}
}
return usedFieldRefs;
}
use of soot.MethodOrMethodContext in project soot by Sable.
the class SideEffectAnalysis method writeSet.
public RWSet writeSet(SootMethod method, Stmt stmt) {
RWSet ret = null;
Iterator<MethodOrMethodContext> targets = tt.iterator(stmt);
while (targets.hasNext()) {
SootMethod target = (SootMethod) targets.next();
if (target.isNative()) {
if (ret == null)
ret = new SiteRWSet();
ret.setCallsNative();
} else if (target.isConcrete()) {
RWSet ntw = nonTransitiveWriteSet(target);
if (ntw != null) {
if (ret == null)
ret = new SiteRWSet();
ret.union(ntw);
}
}
}
if (ret == null)
return ntWriteSet(method, stmt);
ret.union(ntWriteSet(method, stmt));
return ret;
}
Aggregations