private Set<CGNode> findRecursiveMethods(IProgressMonitor progress) throws CancelException {
    CallGraph cg = sdg.getCallGraph();
    GraphReachability<CGNode, CGNode> reach =
        new GraphReachability<CGNode, CGNode>(cg, new TrueFilter());
    progress.subTask("Searching recursive methods");
    reach.solve(progress);

    Set<CGNode> recursive = HashSetFactory.make();

    for (CGNode node : cg) {
      OrdinalSet<CGNode> rset = reach.getReachableSet(node);
      for (CGNode target : rset) {
        if (target != node) {
          OrdinalSet<CGNode> tset = reach.getReachableSet(target);
          if (tset.contains(node)) {
            recursive.add(node);
            break;
          }
        }
      }

      progress.worked(1);
    }

    progress.done();

    return recursive;
  }
Beispiel #2
0
  public static Tuple2<CallGraph, PointerAnalysis> getCGnPA(final Setting setting)
      throws IllegalArgumentException, CancelException, PDGFormatException, IOException,
          WalaException, InvalidClassFileException {

    final String main = setting.main();

    final String mainClassSimpleName = main.replace('/', '.').replace('$', '.').substring(1);

    SDGFactory.Config cfg = setting.jsdgConf();

    Analyzer.cfg = cfg;

    IProgressMonitor progress = new VerboseProgressMonitor(System.out);
    final Result result = getJoanaSDG(cfg, progress);

    {
      progress.beginTask("Saving SDG to " + cfg.outputSDGfile, -1);
      BufferedOutputStream bOut = new BufferedOutputStream(new FileOutputStream(cfg.outputSDGfile));
      SDGSerializer.toPDGFormat(result.sdg, bOut);
      progress.done();
    }

    Util.dumpCallGraph(result.cg, mainClassSimpleName, null);

    return new Tuple2<CallGraph, PointerAnalysis>(result.cg, result.pts);
  }
Beispiel #3
0
  private static PDGNode[] getAllNodesSorted(SDGBuilder builder, IProgressMonitor progress)
      throws CancelException {
    ArrayList<PDGNode> nodes = new ArrayList<PDGNode>();

    for (PDG pdg : builder.getAllPDGs()) {
      for (PDGNode node : pdg.vertexSet()) {
        if (node.getPdgId() == pdg.getId()) {
          nodes.add(node);
        }
      }
    }

    PDGNode[] copy = new PDGNode[nodes.size()];
    copy = nodes.toArray(copy);

    progress.worked(1);
    MonitorUtil.throwExceptionIfCanceled(progress);

    Arrays.sort(
        copy,
        new Comparator<PDGNode>() {
          public int compare(PDGNode o1, PDGNode o2) {
            return o1.getId() - o2.getId();
          }
        });
    progress.worked(1);
    MonitorUtil.throwExceptionIfCanceled(progress);

    return copy;
  }
  private Set<CGNode> findLoopingMethods(IProgressMonitor progress) throws CancelException {
    CallGraph cg = sdg.getCallGraph();
    Set<CGNode> loops = HashSetFactory.make();

    progress.subTask("Searching methods with potential endless loops");

    for (CGNode node : cg) {
      IR ir = node.getIR();
      if (ir != null) {
        ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg = ir.getControlFlowGraph();
        final boolean ac = Acyclic.isAcyclic(cfg, cfg.entry());
        if (!ac && !loopsAreSimple(ir)) {
          loops.add(node);
        }
      } else {
        // Conservatively assume that methods may not terminate, iff we dont
        // have their code
        loops.add(node);
      }

      progress.worked(1);
    }

    progress.done();

    return loops;
  }
  private void computeControlDependence(Set<CallNode> nonTerm, IProgressMonitor progress) {
    progress.subTask("Compute intraprocedural nontermination sensitive control dependencies");

    for (PDG pdg : sdg.getAllContainedPDGs()) {
      NumberedGraph<AbstractPDGNode> cfg = SDGControlFlowGraph.create(pdg, false);
      for (CallNode call : pdg.getAllCalls()) {
        if (nonTerm.contains(call)) {
          // add a termination sink to all potential non-terminating calls
          AbstractPDGNode art = SDGControlFlowGraph.createArtificialNode();
          cfg.addNode(art);
          cfg.addEdge(call, art);
        }
      }

      NumberedGraph<AbstractPDGNode> cdg = NTSCDGraph.compute(cfg, pdg.getRoot(), pdg.getExit());

      removeArtificialNodes(cdg);

      for (AbstractPDGNode from : cdg) {
        for (Iterator<? extends AbstractPDGNode> it = cdg.getSuccNodes(from); it.hasNext(); ) {
          AbstractPDGNode to = it.next();
          pdg.addNonterminationSensitiveControlDependency(from, to);
        }
      }

      progress.worked(1);
    }

    progress.done();
  }
  private Set<CallNode> compute(IProgressMonitor progress) throws CancelException {
    Set<CallNode> calls = HashSetFactory.make();

    Set<CGNode> recursive = findRecursiveMethods(progress);

    Set<CGNode> loop = findLoopingMethods(progress);

    CallGraph cg = sdg.getCallGraph();
    Graph<CGNode> inverted = GraphInverter.invert(cg);
    GraphReachability<CGNode, CGNode> reach =
        new GraphReachability<CGNode, CGNode>(inverted, new TrueFilter());
    progress.subTask("Searching potential non-returning calls");
    reach.solve(progress);

    Set<CGNode> roots = HashSetFactory.make(loop);
    roots.addAll(recursive);

    OrdinalSet<CGNode> potential = OrdinalSet.empty();

    for (CGNode root : roots) {
      OrdinalSet<CGNode> reached = reach.getReachableSet(root);
      potential = OrdinalSet.unify(potential, reached);
    }

    Set<CGNode> terminating = HashSetFactory.make();
    Set<CGNode> nonTerminating = HashSetFactory.make();

    for (CGNode node : cg) {
      if (potential.contains(node)) {
        nonTerminating.add(node);
      } else {
        terminating.add(node);
      }
    }

    for (Call call : sdg.getAllCalls()) {
      if (nonTerminating.contains(call.callee.getCallGraphNode())) {
        calls.add(call.node);
      }
    }

    progress.done();

    computeControlDependence(calls, progress);

    return calls;
  }
Beispiel #7
0
  private static Map<PDGNode, SDGNode> convertNodes(
      SDG sdg, PDGNode[] nodes, SDGBuilder b, IProgressMonitor progress) throws CancelException {
    Map<PDGNode, SDGNode> map = new HashMap<PDGNode, SDGNode>(nodes.length);

    int i = 0;
    for (PDGNode node : nodes) {
      SDGNode snode = convertNode(b, node);
      sdg.addVertex(snode);
      map.put(node, snode);

      if (i++ % 100 == 0) {
        progress.worked(1);
        MonitorUtil.throwExceptionIfCanceled(progress);
      }
    }

    return map;
  }
Beispiel #8
0
  private static Result getOrigSDG(Config cfg, IProgressMonitor progress)
      throws IllegalArgumentException, CancelException, PDGFormatException, IOException,
          WalaException, InvalidClassFileException {
    progress.beginTask(Messages.getString("Analyzer.Task_Prepare_IR"), -1); // $NON-NLS-1$

    com.ibm.wala.ipa.callgraph.impl.Util.setNativeSpec(cfg.nativesXML);

    progress.subTask(Messages.getString("Analyzer.SubTask_Analysis_Scope")); // $NON-NLS-1$

    ClassLoader loader = cfg.getClass().getClassLoader();
    AnalysisScope scope = Util.makeAnalysisScope(cfg, loader);
    // AnalysisScopeReader.makeJavaBinaryAnalysisScope(cfg.scopeFile, cfg.classpath, null);
    progress.done();

    ClassHierarchy cha = ClassHierarchy.make(scope, progress);

    Iterable<Entrypoint> entrypoints =
        com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, cfg.mainClass);
    AnalysisOptions options = new AnalysisOptions(scope, entrypoints);
    AnalysisCache cache = new AnalysisCache();

    progress.subTask(
        Messages.getString("Analyzer.SubTask_Call_Graph_Builder") + cfg.pointsTo); // $NON-NLS-1$
    SSAPropagationCallGraphBuilder builder =
        SDGFactory.getCallGraphBuilder(cfg.pointsTo, options, cache, cha, scope);

    /**
     * Change the wala internal pointer and instancekeyfactory of the callgraph builder to our
     * adapter. So we can keep track of the created InstanceKeys and PointerKeys. This information
     * is used later on when creating subobject trees for accessed field variables.
     */
    InstanceAndPointerKeyFactoryAdapter adapter = null;
    InstanceKeyFactory ikFact = builder.getInstanceKeys();
    PointerKeyFactory pkFact = builder.getPointerKeyFactory();
    adapter = new InstanceAndPointerKeyFactoryAdapter(ikFact, pkFact);

    builder.setInstanceKeys(adapter);
    builder.setPointerKeyFactory(adapter);

    progress.done();

    progress.subTask(Messages.getString("Analyzer.SubTask_Call_Graph")); // $NON-NLS-1$
    CallGraph cg = builder.makeCallGraph(options, progress);

    if (cfg.optimizeCg >= 0) {
      CallGraphPruning opt = new CallGraphPruning(cg);
      System.out.println("Call Graph has " + cg.getNumberOfNodes() + " Nodes.");
      Set<CGNode> sopt = opt.findApplicationNodes(cfg.optimizeCg);
      cg = new PrunedCallGraph(cg, sopt);
      System.out.println("Optimized Call Graph has " + cg.getNumberOfNodes() + " Nodes.");
    }

    if (Debug.Var.DUMP_CALLGRAPH.isSet()) {
      Util.dumpCallGraph(cg, cfg.mainClass.replace('/', '.').substring(1), progress);
    }

    if (Debug.Var.DUMP_HEAP_GRAPH.isSet()) {
      PointerAnalysis pta = builder.getPointerAnalysis();
      HeapGraph hg = pta.getHeapGraph();
      Util.dumpHeapGraph(
          cfg.mainClass.replace('/', '.').substring(1) + "." + cfg.pointsTo, hg, null);
    }

    PointerAnalysis pta = builder.getPointerAnalysis();
    progress.done();

    DemandRefinementPointsTo demandPts = null;
    if (cfg.useDemandPts) {
      throw new UnsupportedOperationException();
      //		    MemoryAccessMap mam = new PABasedMemoryAccessMap(cg, builder.getPointerAnalysis());
      //			demandPts = new DemandRefinementPointsTo(cg,
      //				new ThisFilteringHeapModel(builder,cha), mam, cha, options, getStateMachineFactory());
    }

    IPointerAnalysis pts = new PointsToWrapper(demandPts, pta);

    progress.subTask(Messages.getString("Analyzer.SubTask_Search_Main")); // $NON-NLS-1$
    IMethod main =
        edu.kit.joana.deprecated.jsdg.util.Util.searchMethod(
            entrypoints, "main([Ljava/lang/String;)V"); // $NON-NLS-1$
    progress.done();

    progress.done();

    SDG sdg = SDG.create(main, cg, cache, adapter, pts, cfg, progress);
    sdg.setAnalysisScope(scope);
    sdg.setPointerAnalysis(pta);

    progress.done();

    if (Debug.Var.PRINT_FIELD_PTS_INFO.isSet()) {
      Log.info("search for field allocs called " + PDG.searchFieldAllocs + " times.");
    }

    if (Debug.Var.PRINT_UNRESOLVED_CLASSES.isSet()) {
      for (TypeReference tRef : cg.getClassHierarchy().getUnresolvedClasses()) {
        Log.warn("Could not resolve: " + Util.typeName(tRef.getName()));
      }
    }

    return new Result(null, sdg, cg, pta, null);
  }
Beispiel #9
0
  public static final Result getJoanaSDG(Config cfg, final IProgressMonitor progress)
      throws IllegalArgumentException, CancelException, PDGFormatException, IOException,
          WalaException, InvalidClassFileException {
    final Date start = initSDGcomputation(cfg);

    final Result jresult = getOrigSDG(cfg, progress);

    edu.kit.joana.ifc.sdg.graph.SDG joanaSdg =
        JoanaStyleSDG.createJoanaSDG(
            jresult.jsdg, cfg.addControlFlow, cfg.nonTermination, cfg.useSummaryOpt, progress);

    if (progress.isCanceled()) {
      throw CancelException.make("Operation aborted.");
    }

    // as long as we can not cope with nodes that do not belong to the control flow we do this...
    JoanaCFGSanitizer.sanitizeCFG(joanaSdg);

    //        assert assertVerify(joanaSdg, !cfg.useWalaSdg, cfg.addControlFlow);

    final Date beforeThreadAllocation = new Date();

    final MHPAnalysis mhp;

    if (cfg.computeInterference) {
      progress.beginTask("Creating cSDG from SDG " + cfg.outputSDGfile, -1);

      progress.subTask("Running Thread Allocation Analysis");
      Log.info("Running Thread Allocation Analysis");

      mhp = CSDGPreprocessor.runMHP(joanaSdg, progress);

      Log.info("Thread Allocation done.");
      progress.done();
    } else {
      mhp = null;
    }

    if (progress.isCanceled()) {
      throw CancelException.make("Operation aborted.");
    }

    final Date beforeSummaryEdge = new Date();

    if (cfg.computeSummaryEdges) {
      progress.subTask("Compute Summary Edges");
      Log.info("Compute Summary Edges");
      SummaryEdgeComputation.compute(joanaSdg, progress);

      Log.info("Summary Edges done.");
      progress.done();
    }

    if (progress.isCanceled()) {
      throw CancelException.make("Operation aborted.");
    }

    final Date end = new Date();

    long start2end = end.getTime() - start.getTime();
    long summary2end = end.getTime() - beforeSummaryEdge.getTime();
    long start2thread = beforeThreadAllocation.getTime() - start.getTime();
    long threadAlloc = beforeSummaryEdge.getTime() - beforeThreadAllocation.getTime();

    Log.info("Start 2 End: " + start2end / 1000 + "s (" + start2end + "ms)");
    Log.info("Create: " + start2thread / 1000 + "s (" + start2thread + "ms)");
    Log.info(
        "Summary: "
            + summary2end / 1000
            + "s ("
            + summary2end
            + "ms)"
            + (cfg.computeSummaryEdges ? "" : " [deactivated]"));
    Log.info(
        "Thread: "
            + threadAlloc / 1000
            + "s ("
            + threadAlloc
            + "ms)"
            + (cfg.computeInterference ? "" : " [deactivated]"));

    return new Result(joanaSdg, jresult.jsdg, jresult.cg, jresult.pts, mhp);
  }
Beispiel #10
0
  private static edu.kit.joana.ifc.sdg.graph.SDG createSDG(
      CallGraphResult cgResult, AnalysisOptions opt, IMethod method, boolean ignoreExceptions)
      throws CancelException, PDGFormatException, WalaException {
    DemandRefinementPointsTo demandPts = null;
    //		if (cfg.useDemandPts) {
    //		    MemoryAccessMap mam = new PABasedMemoryAccessMap(cg, builder.getPointerAnalysis());
    //			demandPts = new DemandRefinementPointsTo(cg,
    //				new ThisFilteringHeapModel(builder,cha), mam, cha, options,
    //			        getStateMachineFactory());
    //		}

    IPointerAnalysis pts = new PointsToWrapper(demandPts, cgResult.pts);
    IProgressMonitor progress = NullProgressMonitor.INSTANCE;
    // new VerboseProgressMonitor(System.out);
    IKey2Origin k2o = null;
    edu.kit.joana.deprecated.jsdg.SDGFactory.Config cfg =
        new edu.kit.joana.deprecated.jsdg.SDGFactory.Config();
    cfg.computeSummaryEdges = true;
    cfg.useSummaryOpt = false;
    cfg.addControlFlow = true;
    cfg.computeInterference = false;
    cfg.ignoreExceptions = ignoreExceptions;
    cfg.optimizeExceptions = false; // !ignoreExceptions;
    cfg.nonTermination = false;

    cfg.immutables =
        new String[] {
          "java.lang.String",
          "java.lang.Integer",
          "java.lang.Float",
          "java.lang.Double",
          "java.lang.Boolean",
          "java.lang.Character"
        };

    edu.kit.joana.deprecated.jsdg.sdg.SDG jSDG =
        edu.kit.joana.deprecated.jsdg.sdg.SDG.create(
            method, cgResult.cg, cgResult.cache, k2o, pts, cfg, progress);

    edu.kit.joana.ifc.sdg.graph.SDG sdg =
        JoanaStyleSDG.createJoanaSDG(
            jSDG, cfg.addControlFlow, cfg.nonTermination, cfg.useSummaryOpt, progress);

    RemoveLibraryClinits.removeLibraryClinits(sdg);
    StaticFieldMerge.mergeStaticFields(sdg);

    final Logger log = Log.getLogger(Log.L_WALA_CORE_DEBUG);

    if (cfg.computeSummaryEdges) {
      progress.subTask("Compute Summary Edges");
      log.outln("Compute Summary Edges");
      SummaryEdgeComputation.compute(sdg, progress);

      log.outln("Summary Edges done.");
      progress.done();
    }

    SummarizeDependencies.transformToSummary(sdg, method);

    return sdg;
  }
Beispiel #11
-1
  public static SDG convert(SDGBuilder b, IProgressMonitor progress) throws CancelException {
    SDG sdg = new SDG(PrettyWalaNames.methodName(b.getEntry()));

    progress.subTask("Building utility edges");
    addUtilityEdges(b);
    progress.worked(1);
    MonitorUtil.throwExceptionIfCanceled(progress);
    progress.done();

    progress.subTask("Sorting all nodes by their id");
    PDGNode allNodes[] = getAllNodesSorted(b, progress);
    progress.done();

    progress.subTask("Inserting " + allNodes.length + " nodes");
    Map<PDGNode, SDGNode> pdg2sdg = convertNodes(sdg, allNodes, b, progress);
    progress.done();

    progress.subTask("Inserting edges for " + allNodes.length + " nodes");
    for (int i = 0; i < allNodes.length; i++) {
      addEdgesForNode(sdg, allNodes[i], pdg2sdg, b);

      if (i % 100 == 0) {
        progress.worked(1);
        MonitorUtil.throwExceptionIfCanceled(progress);
      }
    }
    sdg.setNode2Instr(b.getPDGNode2IIndex());
    sdg.setEntryToCGNode(b.getEntryNode2CGNode());
    progress.done();

    return sdg;
  }