package org.jf.dexlib.Code.Analysis.graphs; import org.jf.dexlib.Code.Analysis.graphs.CFG.Edge.Kind; import org.jgrapht.DirectedGraph; import org.jgrapht.graph.DirectedPseudograph; import org.jgrapht.graph.EdgeReversedGraph; /** * This is a control dependence graph. Control dependencies are computed for nodes * of a control flow graph. n -> m reads as "m is control dependent on n". * * Control dependencies tell us which nodes may control iff a certain node can be reached. * E.g. the following control flow graph * * <pre> * CFG: * start -> n1 -> n2 -> n -\ * \-> n3 -> n4 -> n5 -> exit * </pre> * results in this control dependence graph: * <pre> * CDG: * start -> n1 -> n2 * \ \-> n * | |-> n3 * | \-> n4 * |-> n5 * \-> exit * </pre> * * The outcome of node n1 can control if node n is executed or not, because the control * flow offers two alternatives at node n1: When we choose * the path through node n3, n is never executed. When we choose the path through * node n2, n is executed. * * Node n5 is not control dependent on n1, because it does not matter which path we choose, * we will always reach and thus execute n5. So n1 has no control over the execution of n5. * * @author Juergen Graf <juergen.graf@gmail.com> * */ public class CDG extends DirectedPseudograph<CFG.Node, CFG.Edge> { private static final long serialVersionUID = -3075242412849707485L; public static CDG build(CFG cfg) { final CDG cdg = new CDG(cfg); cdg.build(); return cdg; } private final CFG cfg; private CDG(final CFG cfg) { super(CFG.EDGE_FACTORY); this.cfg = cfg; } private void build() { final DirectedGraph<CFG.Node, CFG.Edge> reversedCfg = new EdgeReversedGraph<CFG.Node, CFG.Edge>(cfg); final DominanceFrontiers<CFG.Node, CFG.Edge> frontiers = DominanceFrontiers.compute(reversedCfg, cfg.getExit()); for (final CFG.Node node : cfg.vertexSet()) { addVertex(node); } addEdge(cfg.getEntry(), cfg.getExit()); for (final CFG.Node node : cfg.vertexSet()) { for (final CFG.Node domFrontier : frontiers.getDominanceFrontier(node)) { if (node != domFrontier) { // no self dependencies addEdge(domFrontier, node); } } } } public CFG.Node getEntry() { return cfg.getEntry(); } public CFG.Node getExit() { return cfg.getExit(); } public CFG.Edge addEdge(CFG.Node from, CFG.Node to) { return addEdge(from, to, Kind.CD); } public CFG.Edge addEdge(CFG.Node from, CFG.Node to, CFG.Edge.Kind kind) { final CFG.Edge edge = CFG.EDGE_FACTORY.createEdge(from, to, kind); return (addEdge(from, to, edge) ? edge : null); } public String toString() { return "CDG of " + cfg.getName() + "(" + vertexSet().size() + ", " + edgeSet().size() + ")" ; } }