/** * 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; }
/** * Check properties of the InterproceduralCFG * * @param cg */ private static void checkICFG(CallGraph cg) { InterproceduralCFG icfg = new InterproceduralCFG(cg); try { GraphIntegrity.check(icfg); } catch (UnsoundGraphException e) { e.printStackTrace(); Assert.assertTrue(false); } // perform a little icfg exercise int count = 0; for (Iterator<BasicBlockInContext<ISSABasicBlock>> it = icfg.iterator(); it.hasNext(); ) { BasicBlockInContext<ISSABasicBlock> bb = it.next(); if (icfg.hasCall(bb)) { count++; } } }
/** * 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(); }