Search in sources :

Example 1 with SparkOptions

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);
    }
}
Also used : PAGDumper(soot.jimple.spark.pag.PAGDumper) GeomPointsTo(soot.jimple.spark.geom.geomPA.GeomPointsTo) EBBCollapser(soot.jimple.spark.solver.EBBCollapser) ContextInsensitiveBuilder(soot.jimple.spark.builder.ContextInsensitiveBuilder) ReachingTypeDumper(soot.jimple.ReachingTypeDumper) Date(java.util.Date) SparkOptions(soot.options.SparkOptions) CallGraphBuilder(soot.jimple.toolkits.callgraph.CallGraphBuilder) PAG(soot.jimple.spark.pag.PAG) PAG2HTML(soot.jimple.spark.pag.PAG2HTML) SCCCollapser(soot.jimple.spark.solver.SCCCollapser) PointsToAnalysis(soot.PointsToAnalysis)

Example 2 with SparkOptions

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();
    }
}
Also used : AllocNodesFinder(soot.jimple.toolkits.thread.mhp.findobject.AllocNodesFinder) AbstractRuntimeThread(soot.jimple.toolkits.thread.AbstractRuntimeThread) DemandCSPointsTo(soot.jimple.spark.ondemand.DemandCSPointsTo) MultiRunStatementsFinder(soot.jimple.toolkits.thread.mhp.findobject.MultiRunStatementsFinder) SparkOptions(soot.options.SparkOptions) PegCallGraph(soot.jimple.toolkits.thread.mhp.pegcallgraph.PegCallGraph) PegCallGraph(soot.jimple.toolkits.thread.mhp.pegcallgraph.PegCallGraph)

Aggregations

SparkOptions (soot.options.SparkOptions)2 Date (java.util.Date)1 PointsToAnalysis (soot.PointsToAnalysis)1 ReachingTypeDumper (soot.jimple.ReachingTypeDumper)1 ContextInsensitiveBuilder (soot.jimple.spark.builder.ContextInsensitiveBuilder)1 GeomPointsTo (soot.jimple.spark.geom.geomPA.GeomPointsTo)1 DemandCSPointsTo (soot.jimple.spark.ondemand.DemandCSPointsTo)1 PAG (soot.jimple.spark.pag.PAG)1 PAG2HTML (soot.jimple.spark.pag.PAG2HTML)1 PAGDumper (soot.jimple.spark.pag.PAGDumper)1 EBBCollapser (soot.jimple.spark.solver.EBBCollapser)1 SCCCollapser (soot.jimple.spark.solver.SCCCollapser)1 CallGraphBuilder (soot.jimple.toolkits.callgraph.CallGraphBuilder)1 AbstractRuntimeThread (soot.jimple.toolkits.thread.AbstractRuntimeThread)1 AllocNodesFinder (soot.jimple.toolkits.thread.mhp.findobject.AllocNodesFinder)1 MultiRunStatementsFinder (soot.jimple.toolkits.thread.mhp.findobject.MultiRunStatementsFinder)1 PegCallGraph (soot.jimple.toolkits.thread.mhp.pegcallgraph.PegCallGraph)1