use of soot.options.SparkOptions in project soot by Sable.
the class SparkTransformer method internalTransform.
protected void internalTransform(String phaseName, Map<String, String> options) {
SparkOptions opts = new SparkOptions(options);
final String output_dir = SourceLocator.v().getOutputDir();
// Build pointer assignment graph
ContextInsensitiveBuilder b = new ContextInsensitiveBuilder();
if (opts.pre_jimplify())
b.preJimplify();
if (opts.force_gc())
doGC();
Date startBuild = new Date();
final PAG pag = b.setup(opts);
b.build();
Date endBuild = new Date();
reportTime("Pointer Assignment Graph", startBuild, endBuild);
if (opts.force_gc())
doGC();
// Build type masks
Date startTM = new Date();
pag.getTypeManager().makeTypeMask();
Date endTM = new Date();
reportTime("Type masks", startTM, endTM);
if (opts.force_gc())
doGC();
if (opts.verbose()) {
logger.debug("VarNodes: " + pag.getVarNodeNumberer().size());
logger.debug("FieldRefNodes: " + pag.getFieldRefNodeNumberer().size());
logger.debug("AllocNodes: " + pag.getAllocNodeNumberer().size());
}
// Simplify pag
Date startSimplify = new Date();
// these option interdependencies more cleanly would be nice...
if ((opts.simplify_sccs() && !opts.on_fly_cg()) || opts.vta()) {
new SCCCollapser(pag, opts.ignore_types_for_sccs()).collapse();
}
if (opts.simplify_offline() && !opts.on_fly_cg()) {
new EBBCollapser(pag).collapse();
}
if (true || opts.simplify_sccs() || opts.vta() || opts.simplify_offline()) {
pag.cleanUpMerges();
}
Date endSimplify = new Date();
reportTime("Pointer Graph simplified", startSimplify, endSimplify);
if (opts.force_gc())
doGC();
// Dump pag
PAGDumper dumper = null;
if (opts.dump_pag() || opts.dump_solution()) {
dumper = new PAGDumper(pag, output_dir);
}
if (opts.dump_pag())
dumper.dump();
// Propagate
Date startProp = new Date();
propagatePAG(opts, pag);
Date endProp = new Date();
reportTime("Propagation", startProp, endProp);
reportTime("Solution found", startSimplify, endProp);
if (opts.force_gc())
doGC();
if (!opts.on_fly_cg() || opts.vta()) {
CallGraphBuilder cgb = new CallGraphBuilder(pag);
cgb.build();
}
if (opts.verbose()) {
logger.debug("[Spark] Number of reachable methods: " + Scene.v().getReachableMethods().size());
}
if (opts.set_mass())
findSetMass(pag);
if (opts.dump_answer())
new ReachingTypeDumper(pag, output_dir).dump();
if (opts.dump_solution())
dumper.dumpPointsToSets();
if (opts.dump_html())
new PAG2HTML(pag, output_dir).dump();
Scene.v().setPointsToAnalysis(pag);
if (opts.add_tags()) {
addTags(pag);
}
if (opts.geom_pta()) {
if (opts.simplify_offline() || opts.simplify_sccs()) {
logger.debug("" + "Please turn off the simplify-offline and simplify-sccs to run the geometric points-to analysis");
logger.debug("Now, we keep the SPARK result for querying.");
} else {
// We perform the geometric points-to analysis
GeomPointsTo geomPTA = (GeomPointsTo) pag;
geomPTA.parametrize(endProp.getTime() - startSimplify.getTime());
geomPTA.solve();
}
}
if (opts.cs_demand()) {
// replace by demand-driven refinement-based context-sensitive analysis
Date startOnDemand = new Date();
PointsToAnalysis onDemandAnalysis = DemandCSPointsTo.makeWithBudget(opts.traversal(), opts.passes(), opts.lazy_pts());
Date endOndemand = new Date();
reportTime("Initialized on-demand refinement-based context-sensitive analysis", startOnDemand, endOndemand);
Scene.v().setPointsToAnalysis(onDemandAnalysis);
}
}
use of soot.options.SparkOptions in project soot by Sable.
the class SynchObliviousMhpAnalysis method run.
public void run() {
SootMethod mainMethod = Scene.v().getMainClass().getMethodByName("main");
PointsToAnalysis pta = Scene.v().getPointsToAnalysis();
if (pta instanceof DemandCSPointsTo) {
DemandCSPointsTo demandCSPointsTo = (DemandCSPointsTo) pta;
pta = demandCSPointsTo.getPAG();
}
if (!(pta instanceof PAG)) {
throw new RuntimeException("You must use Spark for points-to analysis when computing MHP information!");
}
PAG pag = (PAG) pta;
SparkOptions so = pag.getOpts();
if (so.rta())
throw new RuntimeException("MHP cannot be calculated using RTA due to incomplete call graph");
CallGraph callGraph = Scene.v().getCallGraph();
// Get a call graph trimmed to contain only the relevant methods (non-lib, non-native)
// logger.debug(" MHP: PegCallGraph");
PegCallGraph pecg = new PegCallGraph(callGraph);
// Find allocation nodes that are run more than once
// Also find methods that are run more than once
// logger.debug(" MHP: AllocNodesFinder");
AllocNodesFinder anf = new AllocNodesFinder(pecg, callGraph, (PAG) pta);
Set<AllocNode> multiRunAllocNodes = anf.getMultiRunAllocNodes();
Set<SootMethod> multiCalledMethods = anf.getMultiCalledMethods();
// Find Thread.start() and Thread.join() statements (in live code)
// logger.debug(" MHP: StartJoinFinder");
// does analysis
StartJoinFinder sjf = new StartJoinFinder(callGraph, (PAG) pta);
Map<Stmt, List<AllocNode>> startToAllocNodes = sjf.getStartToAllocNodes();
Map<Stmt, List<SootMethod>> startToRunMethods = sjf.getStartToRunMethods();
Map<Stmt, SootMethod> startToContainingMethod = sjf.getStartToContainingMethod();
Map<Stmt, Stmt> startToJoin = sjf.getStartToJoin();
// Build MHP Lists
// logger.debug(" MHP: Building MHP Lists");
List<AbstractRuntimeThread> runAtOnceCandidates = new ArrayList<AbstractRuntimeThread>();
Iterator threadIt = startToRunMethods.entrySet().iterator();
int threadNum = 0;
while (threadIt.hasNext()) {
// Get list of possible Runnable.run methods (actually, a list of peg chains)
// and a list of allocation sites for this thread start statement
// and the thread start statement itself
Map.Entry e = (Map.Entry) threadIt.next();
Stmt startStmt = (Stmt) e.getKey();
List runMethods = (List) e.getValue();
List threadAllocNodes = startToAllocNodes.get(e.getKey());
// Get a list of all possible unique Runnable.run methods for this thread start statement
// provides a list interface to the methods in a thread's sub-call-graph
AbstractRuntimeThread thread = new AbstractRuntimeThread();
thread.setStartStmt(startStmt);
// List threadMethods = new ArrayList();
Iterator runMethodsIt = runMethods.iterator();
while (runMethodsIt.hasNext()) {
SootMethod method = (SootMethod) runMethodsIt.next();
if (!thread.containsMethod(method)) {
thread.addMethod(method);
thread.addRunMethod(method);
}
}
// Get a list containing all methods in the call graph(s) rooted at the possible run methods for this thread start statement
// AKA a list of all methods that might be called by the thread started here
int methodNum = 0;
while (// iterate over all methods in threadMethods, even as new methods are being added to it
methodNum < thread.methodCount()) {
Iterator succMethodsIt = pecg.getSuccsOf(thread.getMethod(methodNum)).iterator();
while (succMethodsIt.hasNext()) {
SootMethod method = (SootMethod) succMethodsIt.next();
// if all edges into this method are of Kind THREAD, ignore it
// (because it's a run method that won't be called as part of THIS thread) THIS IS NOT OPTIMAL
boolean ignoremethod = true;
Iterator edgeInIt = callGraph.edgesInto(method);
while (edgeInIt.hasNext()) {
Edge edge = (Edge) edgeInIt.next();
if (edge.kind() != Kind.THREAD && edge.kind() != Kind.EXECUTOR && edge.kind() != Kind.ASYNCTASK && // called directly by any of the thread methods?
thread.containsMethod(edge.src()))
ignoremethod = false;
}
if (!ignoremethod && !thread.containsMethod(method))
thread.addMethod(method);
}
methodNum++;
}
// Add this list of methods to MHPLists
threadList.add(thread);
if (optionPrintDebug)
System.out.println(thread.toString());
// Find out if the "thread" in "thread.start()" could be more than one object
boolean mayStartMultipleThreadObjects = (threadAllocNodes.size() > 1) || so.types_for_sites();
if (// if there's only one alloc node
!mayStartMultipleThreadObjects) {
if (// but it gets run more than once
multiRunAllocNodes.contains(threadAllocNodes.iterator().next())) {
// then "thread" in "thread.start()" could be more than one object
mayStartMultipleThreadObjects = true;
}
}
if (mayStartMultipleThreadObjects)
thread.setStartStmtHasMultipleReachingObjects();
// Find out if the "thread.start()" statement may be run more than once
SootMethod startStmtMethod = startToContainingMethod.get(startStmt);
thread.setStartStmtMethod(startStmtMethod);
// if method is called more than once...
boolean mayBeRunMultipleTimes = multiCalledMethods.contains(startStmtMethod);
if (!mayBeRunMultipleTimes) {
UnitGraph graph = new CompleteUnitGraph(startStmtMethod.getActiveBody());
MultiRunStatementsFinder finder = new MultiRunStatementsFinder(graph, startStmtMethod, multiCalledMethods, callGraph);
// list of all units that may be run more than once in this method
FlowSet multiRunStatements = finder.getMultiRunStatements();
if (multiRunStatements.contains(startStmt))
mayBeRunMultipleTimes = true;
}
if (mayBeRunMultipleTimes) {
thread.setStartStmtMayBeRunMultipleTimes();
}
// by one thread (sounds strict, but actually this is the most common case)
if (mayBeRunMultipleTimes && startToJoin.containsKey(startStmt)) {
thread.setJoinStmt(startToJoin.get(startStmt));
// well, actually, we don't know yet
mayBeRunMultipleTimes = false;
methodNum = 0;
List<SootMethod> containingMethodCalls = new ArrayList<SootMethod>();
containingMethodCalls.add(startStmtMethod);
while (// iterate over all methods in threadMethods, even as new methods are being added to it
methodNum < containingMethodCalls.size()) {
Iterator succMethodsIt = pecg.getSuccsOf(containingMethodCalls.get(methodNum)).iterator();
while (succMethodsIt.hasNext()) {
SootMethod method = (SootMethod) succMethodsIt.next();
if (method == startStmtMethod) {
// this method is reentrant
// this time it's for sure
mayBeRunMultipleTimes = true;
thread.setStartMethodIsReentrant();
thread.setRunsMany();
break;
}
if (!containingMethodCalls.contains(method))
containingMethodCalls.add(method);
}
methodNum++;
}
if (!mayBeRunMultipleTimes) {
// There's still one thing that might cause this to be run multiple times: if it can be run in parallel with itself
// but we can't find that out 'till we're done
runAtOnceCandidates.add(thread);
}
}
// then add this list of methods to MHPLists *AGAIN*
if (optionPrintDebug)
System.out.println("Start Stmt " + startStmt.toString() + " mayStartMultipleThreadObjects=" + mayStartMultipleThreadObjects + " mayBeRunMultipleTimes=" + mayBeRunMultipleTimes);
if (mayStartMultipleThreadObjects && mayBeRunMultipleTimes) {
// add another copy
threadList.add(thread);
thread.setRunsMany();
if (optionPrintDebug)
System.out.println(thread.toString());
} else
thread.setRunsOnce();
threadNum++;
}
// do same for main method
AbstractRuntimeThread mainThread = new AbstractRuntimeThread();
// List mainMethods = new ArrayList();
threadList.add(mainThread);
mainThread.setRunsOnce();
mainThread.addMethod(mainMethod);
mainThread.addRunMethod(mainMethod);
mainThread.setIsMainThread();
// get all the successors, add to threadMethods
int methodNum = 0;
while (methodNum < mainThread.methodCount()) {
Iterator succMethodsIt = pecg.getSuccsOf(mainThread.getMethod(methodNum)).iterator();
while (succMethodsIt.hasNext()) {
SootMethod method = (SootMethod) succMethodsIt.next();
// if all edges into this are of Kind THREAD, ignore it
boolean ignoremethod = true;
Iterator edgeInIt = callGraph.edgesInto(method);
while (edgeInIt.hasNext()) {
if (((Edge) edgeInIt.next()).kind() != Kind.THREAD)
ignoremethod = false;
}
if (!ignoremethod && !mainThread.containsMethod(method))
mainThread.addMethod(method);
}
methodNum++;
}
if (optionPrintDebug)
logger.debug("" + mainThread.toString());
// Revisit the containing methods of start-join pairs that are non-reentrant but might be called in parallel
boolean addedNew = true;
while (addedNew) {
addedNew = false;
ListIterator<AbstractRuntimeThread> it = runAtOnceCandidates.listIterator();
while (it.hasNext()) {
AbstractRuntimeThread someThread = it.next();
SootMethod someStartMethod = someThread.getStartStmtMethod();
if (mayHappenInParallelInternal(someStartMethod, someStartMethod)) {
// add a second copy of it
threadList.add(someThread);
someThread.setStartMethodMayHappenInParallel();
someThread.setRunsMany();
it.remove();
if (optionPrintDebug)
logger.debug("" + someThread.toString());
addedNew = true;
}
}
}
// mark the remaining threads here as run-one-at-a-time
Iterator<AbstractRuntimeThread> it = runAtOnceCandidates.iterator();
while (it.hasNext()) {
AbstractRuntimeThread someThread = it.next();
someThread.setRunsOneAtATime();
}
}
Aggregations