private static DemandRefinementPointsTo makeDemandPointerAnalysis( String scopeFile, String mainClass, String benchName) throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(scopeFile, getExclusions(benchName)); // build a type hierarchy ClassHierarchy cha = ClassHierarchy.make(scope); // set up call graph construction options; mainly what should be considered // entrypoints? Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, mainClass); AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints); System.err.print("constructing call graph..."); final Pair<CallGraph, PointerAnalysis> cgAndPA = buildCallGraph(scope, cha, options); CallGraph cg = cgAndPA.fst; System.err.println("done"); System.err.println(CallGraphStats.getStats(cg)); MemoryAccessMap fam = new SimpleMemoryAccessMap(cg, cgAndPA.snd.getHeapModel(), false); DemandRefinementPointsTo fullDemandPointsTo = DemandRefinementPointsTo.makeWithDefaultFlowGraph( cg, heapModel, fam, cha, options, makeStateMachineFactory()); fullDemandPointsTo.setRefinementPolicyFactory(chooseRefinePolicyFactory(cha)); return fullDemandPointsTo; }
/** * Check consistency of a callgraph, and check that this call graph is a subset of a super-graph * * @param warnings object to track warnings * @param cg * @param superCG * @param superMethods * @param thisAlgorithm * @return a squashed version of cg */ private static Graph<MethodReference> checkCallGraph( CallGraph cg, Graph<MethodReference> superCG, Set<MethodReference> superMethods, String thisAlgorithm) { try { GraphIntegrity.check(cg); } catch (UnsoundGraphException e1) { Assert.assertTrue(e1.getMessage(), false); } Set<MethodReference> callGraphMethods = CallGraphStats.collectMethods(cg); System.err.println(thisAlgorithm + " methods reached: " + callGraphMethods.size()); System.err.println(CallGraphStats.getStats(cg)); Graph<MethodReference> thisCG = squashCallGraph(thisAlgorithm, cg); if (superCG != null) { com.ibm.wala.ipa.callgraph.impl.Util.checkGraphSubset(superCG, thisCG); } else { // SJF: RTA has rotted a bit since it doesn't handle LoadClass instructions. // Commenting this out for now. // if (!superMethods.containsAll(callGraphMethods)) { // Set<MethodReference> temp = HashSetFactory.make(); // temp.addAll(callGraphMethods); // temp.removeAll(superMethods); // System.err.println("Violations"); // for (MethodReference m : temp) { // System.err.println(m); // } // Assertions.UNREACHABLE(); // } } return thisCG; }
/** * Usage: ScopeFileCallGraph -sourceDir file_path -mainClass class_name * * <p>If given -mainClass, uses main() method of class_name as entrypoint. Class name should start * with an 'L'. * * <p>Example args: -sourceDir /tmp/srcTest -mainClass LFoo */ public static void main(String[] args) throws ClassHierarchyException, IllegalArgumentException, CallGraphBuilderCancelException, IOException { long start = System.currentTimeMillis(); Properties p = CommandLine.parse(args); String sourceDir = p.getProperty("sourceDir"); String mainClass = p.getProperty("mainClass"); AnalysisScope scope = new JavaSourceAnalysisScope(); // add standard libraries to scope String[] stdlibs = WalaProperties.getJ2SEJarFiles(); for (int i = 0; i < stdlibs.length; i++) { scope.addToScope(ClassLoaderReference.Primordial, new JarFile(stdlibs[i])); } // add the source directory scope.addToScope( JavaSourceAnalysisScope.SOURCE, new SourceDirectoryTreeModule(new File(sourceDir))); // build the class hierarchy IClassHierarchy cha = ClassHierarchy.make(scope, new ECJClassLoaderFactory(scope.getExclusions())); System.out.println(cha.getNumberOfClasses() + " classes"); System.out.println(Warnings.asString()); Warnings.clear(); AnalysisOptions options = new AnalysisOptions(); Iterable<Entrypoint> entrypoints = Util.makeMainEntrypoints(JavaSourceAnalysisScope.SOURCE, cha, new String[] {mainClass}); options.setEntrypoints(entrypoints); // you can dial down reflection handling if you like // options.setReflectionOptions(ReflectionOptions.NONE); AnalysisCache cache = new AnalysisCache(AstIRFactory.makeDefaultFactory()); // CallGraphBuilder builder = new ZeroCFABuilderFactory().make(options, cache, cha, scope, // false); CallGraphBuilder builder = new ZeroOneContainerCFABuilderFactory().make(options, cache, cha, scope, false); System.out.println("building call graph..."); CallGraph cg = builder.makeCallGraph(options, null); long end = System.currentTimeMillis(); System.out.println("done"); System.out.println("took " + (end - start) + "ms"); System.out.println(CallGraphStats.getStats(cg)); }
/** * TODO: refactor this to avoid excessive code bloat. * * @throws CancelException * @throws IllegalArgumentException */ public static void doCallGraphs( AnalysisOptions options, AnalysisCache cache, IClassHierarchy cha, AnalysisScope scope, boolean testPAToString) throws IllegalArgumentException, CancelException { // /////////////// // // RTA ///// // /////////////// CallGraph cg = CallGraphTestUtil.buildRTA(options, cache, cha, scope); try { GraphIntegrity.check(cg); } catch (UnsoundGraphException e1) { e1.printStackTrace(); Assert.assertTrue(e1.getMessage(), false); } Set<MethodReference> rtaMethods = CallGraphStats.collectMethods(cg); System.err.println("RTA methods reached: " + rtaMethods.size()); System.err.println(CallGraphStats.getStats(cg)); System.err.println("RTA warnings:\n"); // /////////////// // // 0-CFA ///// // /////////////// cg = CallGraphTestUtil.buildZeroCFA(options, cache, cha, scope, testPAToString); // FIXME: annoying special cases caused by clone2assign mean using // the rta graph for proper graph subset checking does not work. // (note that all the other such checks do use proper graph subset) Graph<MethodReference> squashZero = checkCallGraph(cg, null, rtaMethods, "0-CFA"); // test Pretransitive 0-CFA // not currently supported // warnings = new WarningSet(); // options.setUsePreTransitiveSolver(true); // CallGraph cgP = CallGraphTestUtil.buildZeroCFA(options, cha, scope, // warnings); // options.setUsePreTransitiveSolver(false); // Graph squashPT = checkCallGraph(warnings, cgP, squashZero, null, "Pre-T // 1"); // checkCallGraph(warnings, cg, squashPT, null, "Pre-T 2"); // /////////////// // // 0-1-CFA /// // /////////////// cg = CallGraphTestUtil.buildZeroOneCFA(options, cache, cha, scope, testPAToString); Graph<MethodReference> squashZeroOne = checkCallGraph(cg, squashZero, null, "0-1-CFA"); // /////////////////////////////////////////////////// // // 0-CFA augmented to disambiguate containers /// // /////////////////////////////////////////////////// cg = CallGraphTestUtil.buildZeroContainerCFA(options, cache, cha, scope); Graph<MethodReference> squashZeroContainer = checkCallGraph(cg, squashZero, null, "0-Container-CFA"); // /////////////////////////////////////////////////// // // 0-1-CFA augmented to disambiguate containers /// // /////////////////////////////////////////////////// cg = CallGraphTestUtil.buildZeroOneContainerCFA(options, cache, cha, scope); checkCallGraph(cg, squashZeroContainer, null, "0-1-Container-CFA"); checkCallGraph(cg, squashZeroOne, null, "0-1-Container-CFA"); // test ICFG checkICFG(cg); return; // ///////////// // // 1-CFA /// // ///////////// // warnings = new WarningSet(); // cg = buildOneCFA(); }