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; }
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); }
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; }
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; }
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); }
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); }
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; }
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; }