@Override public CGNode getFakeRootNode() { if (keep.contains(cg.getFakeRootNode())) { return cg.getFakeRootNode(); } else { return null; } }
@Override public CGNode getFakeRootNode() { if (keep.contains(cg.getFakeRootNode())) { return cg.getFakeRootNode(); } else { return null; } }
/** * Checks if a node is FakeRoot * * @param node * the node to check * @return true if node is FakeRoot */ public static boolean isFakeRoot(CallGraph CG, CGNode node) { return (node.equals(CG.getFakeRootNode())); }
/** * Checks if a node is FakeRoot * * @param node * the node to check * @return true if node is FakeRoot */ public static boolean isFakeRoot(CallGraph CG, CGNode node) { return (node.equals(CG.getFakeRootNode())); }
@Override public CGNode getFakeWorldClinitNode() { if (keep.contains(cg.getFakeWorldClinitNode())) { return cg.getFakeRootNode(); } else { return null; } }
@Override public CGNode getFakeWorldClinitNode() { if (keep.contains(cg.getFakeWorldClinitNode())) { return cg.getFakeRootNode(); } else { return null; } }
/** * Searches all nodes in the callgraph according to the given pruning policy. It includes all methods which * transitively may call methods which comply to the given pruning policy. All other methods are cut at the level * provided by parameter 'depth' * @param depth the level at which methods which do not comply to the given pruning policy are cut off. * @param policy pruning policy which decides which branches are kept in the call graph * @return set of relevant callgraph nodes */ public Set<CGNode> findNodes(final int depth, PruningPolicy policy) { if (DEBUG) { System.out.println("Running optimization with depth: " + depth); } this.marked = new LinkedList<>(); this.keep = new HashSet<>(); this.visited = new LinkedList<>(); this.depth = depth; this.pruningPolicy = policy; dfs(cg.getFakeRootNode()); return keep; }
/** * Searches all nodes in the callgraph according to the given pruning policy. It includes all methods which * transitively may call methods which comply to the given pruning policy. All other methods are cut at the level * provided by parameter 'depth' * @param depth the level at which methods which do not comply to the given pruning policy are cut off. * @param policy pruning policy which decides which branches are kept in the call graph * @return set of relevant callgraph nodes */ public Set<CGNode> findNodes(final int depth, PruningPolicy policy) { if (DEBUG) { System.out.println("Running optimization with depth: " + depth); } this.marked = new LinkedList<>(); this.keep = new HashSet<>(); this.visited = new LinkedList<>(); this.depth = depth; this.pruningPolicy = policy; dfs(cg.getFakeRootNode()); return keep; }
private JTree buildTree() { CGNode cgRoot = cg.getFakeRootNode(); DefaultMutableTreeNode root = new DefaultMutableTreeNode(cgRoot); expandNode(root); JTree tree = new JTree(root); tree.addTreeExpansionListener(new TreeExpansionListener() { @Override public void treeExpanded(TreeExpansionEvent event) { TreePath path = event.getPath(); if (path == null) { return; } DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent(); expandNode(lastNode); } @Override public void treeCollapsed(TreeExpansionEvent event) { } }); return tree; }
private JTree buildTree() { CGNode cgRoot = cg.getFakeRootNode(); DefaultMutableTreeNode root = new DefaultMutableTreeNode(cgRoot); expandNode(root); JTree tree = new JTree(root); tree.addTreeExpansionListener(new TreeExpansionListener() { @Override public void treeExpanded(TreeExpansionEvent event) { TreePath path = event.getPath(); if (path == null) { return; } DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent(); expandNode(lastNode); } @Override public void treeCollapsed(TreeExpansionEvent event) { } }); return tree; }
public static CGStats getCGStats(CallGraph cg) { if (cg == null) { throw new IllegalArgumentException("cg is null"); } Set<CGNode> reachableNodes = DFS.getReachableNodes(cg, Collections.singleton(cg.getFakeRootNode())); int nNodes = 0; int nEdges = 0; for (CGNode n : reachableNodes) { nNodes++; nEdges += cg.getSuccNodeCount(n); } return new CGStats(nNodes, nEdges, collectMethods(cg).size(), countBytecodeBytes(cg)); }
public static CGStats getCGStats(CallGraph cg) { if (cg == null) { throw new IllegalArgumentException("cg is null"); } Set<CGNode> reachableNodes = DFS.getReachableNodes(cg, Collections.singleton(cg.getFakeRootNode())); int nNodes = 0; int nEdges = 0; for (CGNode n : reachableNodes) { nNodes++; nEdges += cg.getSuccNodeCount(n); } return new CGStats(nNodes, nEdges, collectMethods(cg).size(), countBytecodeBytes(cg)); }
/** * filters a CallGraph * * @param fullCG * the original unfiltered CallGraph * @return the filtered CallGraph */ private CallGraph filter(final CallGraph fullCG) { // collect nodes not named for exclusion final HashSet<CGNode> nodes = new HashSet<>(); fullCG.forEach(node -> { if (!filter.contains(node.getMethod().getName())) nodes.add(node); }); final Set<CGNode> partialRoots = Collections.singleton(fullCG.getFakeRootNode()); // delete the nodes final PartialCallGraph partialCG1 = PartialCallGraph.make(fullCG, partialRoots, nodes); // delete the nodes not reachable by root (consider the different implementations of "make") final PartialCallGraph partialCG2 = PartialCallGraph.make(partialCG1, partialRoots); return partialCG2; } }
/** * filters a CallGraph * * @param fullCG * the original unfiltered CallGraph * @return the filtered CallGraph */ private CallGraph filter(final CallGraph fullCG) { // collect nodes not named for exclusion final HashSet<CGNode> nodes = new HashSet<>(); fullCG.forEach(node -> { if (!filter.contains(node.getMethod().getName())) nodes.add(node); }); final Set<CGNode> partialRoots = Collections.singleton(fullCG.getFakeRootNode()); // delete the nodes final PartialCallGraph partialCG1 = PartialCallGraph.make(fullCG, partialRoots, nodes); // delete the nodes not reachable by root (consider the different implementations of "make") final PartialCallGraph partialCG2 = PartialCallGraph.make(partialCG1, partialRoots); return partialCG2; } }
private static Graph<Statement> pruneSDG(final SDG<?> sdg) { Predicate<Statement> f = s -> { if (s.getNode().equals(sdg.getCallGraph().getFakeRootNode())) { return false; } else if (s instanceof MethodExitStatement || s instanceof MethodEntryStatement) { return false; } else { return true; } }; return GraphSlicer.prune(sdg, f); }
@Test public void testFinalize() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(TestConstants.WALA_TESTDATA, CallGraphTestUtil.REGRESSION_EXCLUSIONS); ClassHierarchy cha = ClassHierarchyFactory.make(scope); Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, "Lfinalizers/Finalizers"); AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints); CallGraph cg = CallGraphTestUtil.buildZeroCFA(options, new AnalysisCacheImpl(), cha, scope, false); // Find node corresponding to finalize TypeReference t = TypeReference.findOrCreate(ClassLoaderReference.Application, "Lfinalizers/Finalizers"); MethodReference m = MethodReference.findOrCreate(t, "finalize", "()V"); Assert.assertTrue("expect finalizer node", cg.getNodes(m).iterator().hasNext()); CGNode node = cg.getNodes(m).iterator().next(); // Check it's reachable from root Assert.assertTrue("should have call site from root", cg.getPossibleSites(cg.getFakeRootNode(), node).hasNext()); } }
@Test public void testNList() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(TestConstants.WALA_TESTDATA, CallGraphTestUtil.REGRESSION_EXCLUSIONS); ClassHierarchy cha = ClassHierarchyFactory.make(scope); Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, "Lrecurse/NList"); AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints); CallGraph cg = CallGraphTestUtil.buildZeroCFA(options, new AnalysisCacheImpl(), cha, scope, false); IBinaryNaturalRelation backEdges = Acyclic.computeBackEdges(cg, cg.getFakeRootNode()); Assert.assertTrue("NList should have cycles", backEdges.iterator().hasNext()); Map<CGNode, Set<CGNode>> cgBackEdges = HashMapFactory.make(); for (IntPair p : backEdges) { CGNode src = cg.getNode(p.getX()); if (!cgBackEdges.containsKey(src)) { cgBackEdges.put(src, HashSetFactory.<CGNode>make()); } cgBackEdges.get(src).add(cg.getNode(p.getY())); } PrunedCallGraph pcg = new PrunedCallGraph(cg, Iterator2Collection.toSet(cg.iterator()), cgBackEdges); Assert.assertTrue("cycles should be gone", !Acyclic.computeBackEdges(pcg, pcg.getFakeRootNode()).iterator().hasNext()); }
@Test public void testMultiSubtypes() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(TestConstants.WALA_TESTDATA, CallGraphTestUtil.REGRESSION_EXCLUSIONS); ClassHierarchy cha = ClassHierarchyFactory.make(scope); TypeReference t = TypeReference.findOrCreate(ClassLoaderReference.Application, "LmultiTypes/Foo"); MethodReference mref = MethodReference.findOrCreate(t, "foo", "(LmultiTypes/Foo$A;)V"); IMethod m = cha.resolveMethod(mref); assert m != null; SubtypesEntrypoint e = new SubtypesEntrypoint(m, cha); AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, Collections.<Entrypoint>singleton(e)); CallGraph cg = CallGraphTestUtil.buildZeroCFA(options, new AnalysisCacheImpl(), cha, scope, false); TypeReference tA = TypeReference.findOrCreate(ClassLoaderReference.Application, "LmultiTypes/Foo$A"); MethodReference barA = MethodReference.findOrCreate(tA, "bar", "()V"); TypeReference tB = TypeReference.findOrCreate(ClassLoaderReference.Application, "LmultiTypes/Foo$B"); MethodReference barB = MethodReference.findOrCreate(tB, "bar", "()V"); Assert.assertTrue(cg.getNodes(barA).size() == 1); Assert.assertTrue(cg.getNodes(barB).size() == 1); CGNode root = cg.getFakeRootNode(); IR ir = root.getIR(); Assert.assertTrue(ir.iteratePhis().hasNext()); }
public static CGNode findMainMethod(CallGraph cg) { Descriptor d = Descriptor.findOrCreateUTF8("([Ljava/lang/String;)V"); Atom name = Atom.findOrCreateUnicodeAtom("main"); for (CGNode n : Iterator2Iterable.make(cg.getSuccNodes(cg.getFakeRootNode()))) { if (n.getMethod().getName().equals(name) && n.getMethod().getDescriptor().equals(d)) { return n; } } Assertions.UNREACHABLE("failed to find method"); return null; }
private static CGNode findMethod(CallGraph cg, Descriptor d, Atom name) { for (CGNode n : Iterator2Iterable.make(cg.getSuccNodes(cg.getFakeRootNode()))) { if (n.getMethod().getName().equals(name) && n.getMethod().getDescriptor().equals(d)) { return n; } } // if it's not a successor of fake root, just iterate over everything for (CGNode n : cg) { if (n.getMethod().getName().equals(name) && n.getMethod().getDescriptor().equals(d)) { return n; } } Assertions.UNREACHABLE("failed to find method " + name); return null; }