package jqian.sootex.dependency.pdg; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import soot.SootField; import soot.SootMethod; import soot.Type; import soot.toolkits.graph.DirectedGraph; import jqian.sootex.CFGProvider; import jqian.sootex.HammockCFGProvider; import jqian.sootex.dependency.pdg.builder.SDGBuilder; import jqian.sootex.du.DUBuilder; import jqian.sootex.location.HeapAbstraction; import jqian.sootex.ptsto.IPtsToQuery; import jqian.sootex.sideeffect.ISideEffectAnalysis; import jqian.sootex.util.SootUtils; import jqian.sootex.util.graph.GraphHelper; import jqian.util.dot.DotViewer; import jqian.util.dot.GrappaGraph; import jqian.util.graph.Graph; import jqian.util.jgraphx.GraphViewer; import att.grappa.Edge; import att.grappa.GrappaConstants; import att.grappa.Node; /** * */ public class DependenceGraphHelper { public static class LabelProvider { public String getLabel(DependenceNode node) { return node.toString(); } public String getName(DependenceNode node) { if (node instanceof JavaStmtNode || node instanceof JimpleStmtNode) { return node.getNumber() + ":" + node.toString(); } return node.toString(); } } private static String getReasonString(DataDependenceEdge dataDep) { Object reason = dataDep.getReason(); if (reason != null) { String label = ""; if (reason instanceof SootField) { label = SootUtils.getShortFieldString((SootField) reason); } else if (reason instanceof Type) { label = reason.toString() + "[x]"; } else { label = reason.toString(); } if (label.length() > 20) label = label.substring(0, 20) + "..."; return label; } return null; } public static GrappaGraph toGrappaGraph(PDG pdg) { return toGrappaGraph(pdg, null); } public static GrappaGraph toGrappaGraph(PDG pdg, Collection<DependenceNode> highlightedNodes) { LabelProvider fetcher = new LabelProvider(); return toGrappaGraph(pdg, null, highlightedNodes, null, fetcher); } public static GrappaGraph toGrappaGraph(PDG pdg, Collection<DependenceNode> highlightedNodes, LabelProvider fetcher) { return toGrappaGraph(pdg, null, highlightedNodes, null, fetcher); } /** * @param highlightedNodes This set can be null */ protected static GrappaGraph toGrappaGraph(PDG pdg, GrappaGraph depGraph, Collection<DependenceNode> highlightedNodes, Map<DependenceNode,Node> dep2grappa, LabelProvider lableFetcher) { if (depGraph == null) { depGraph = new GrappaGraph("Dependence Graph"); depGraph.setMenuable(true); depGraph.setEditable(true); depGraph.setAttribute("fontsize", "8"); //depGraph.setNodeAttribute("style","rounded");//"ellipse"); // depGraph.setAttribute("fontstyle","bold"); // depGraph.setNodeAttribute("shape","box");//"ellipse"); // depGraph.setNodeAttribute("style","filled"); // depGraph.setNodeAttribute("color","beige");//"darkgreen" // depGraph.setNodeAttribute("tip","A Node"); //"An Edge" // depGraph.setEdgeAttribute("instances","1"); } Map<DependenceNode,Node> depNode2GrappaNode = new HashMap<DependenceNode,Node>(pdg.getNodes().size() * 2 + 1, 0.7f); // map each dependence graph node to grappa grah node for (DependenceNode depNode : pdg.getNodes()) { String name = lableFetcher.getName(depNode); String label = lableFetcher.getLabel(depNode); Node grappaNode = new Node(depGraph, name); grappaNode.setAttribute(GrappaConstants.LABEL_ATTR, label); //grappaNode.setAttribute("shape","box");//"ellipse"); //grappaNode.setAttribute("labelfontsize","10"); if (depNode instanceof FormalNode || depNode instanceof ActualNode) { //grappaNode.setAttribute(GrappaConstants.STYLE_ATTR, "filled"); grappaNode.setAttribute(GrappaConstants.STYLE_ATTR, "filled"); grappaNode.setAttribute(GrappaConstants.FILLCOLOR_ATTR, "gray"); if (dep2grappa != null) dep2grappa.put(depNode, grappaNode); } else if (depNode instanceof EntryNode || depNode instanceof CallNode) { if (dep2grappa != null) dep2grappa.put(depNode, grappaNode); } else if (depNode instanceof JavaStmtNode) { if (dep2grappa != null && ((JavaStmtNode) depNode).isCallSite()) dep2grappa.put(depNode, grappaNode); } if (highlightedNodes != null && highlightedNodes.contains(depNode)) { grappaNode.setAttribute(GrappaConstants.STYLE_ATTR, "filled"); grappaNode.setAttribute(GrappaConstants.FILLCOLOR_ATTR, "yellow"); } grappaNode.setAttribute(GrappaConstants.FONTSIZE_ATTR, "8"); depNode2GrappaNode.put(depNode, grappaNode); } // map each dependence edge to grappa graph edge for (DependenceNode depNode : pdg.getNodes()) { Node grappaFrom = (Node) depNode2GrappaNode.get(depNode); Collection<?> edges = pdg.edgesOutOf(depNode); if (edges != null) { for (Iterator<?> egIt = edges.iterator(); egIt.hasNext();) { DependenceEdge edge = (DependenceEdge) egIt.next(); DependenceNode to = edge.getTo(); Node grappaTo = (Node) depNode2GrappaNode.get(to); Edge grappaEdge = new Edge(depGraph,grappaFrom, grappaTo); setGrappaEdgeProperty(edge, grappaEdge); depGraph.addEdge(grappaEdge); } } } return depGraph; } static void setGrappaEdgeProperty(DependenceEdge edge, Edge grappaEdge) { if (edge instanceof CtrlDependenceEdge) { grappaEdge.setAttribute(GrappaConstants.STYLE_ATTR, "bold"); } else if (edge instanceof DataDependenceEdge) { DataDependenceEdge dataDep = (DataDependenceEdge) edge; String label = getReasonString(dataDep); if (label != null) { grappaEdge.setAttribute(GrappaConstants.FONTSIZE_ATTR, "9"); grappaEdge.setAttribute(GrappaConstants.LABEL_ATTR, label); } if (edge instanceof SummaryEdge) { grappaEdge.setAttribute(GrappaConstants.STYLE_ATTR, "dotted"); } } } public static GrappaGraph toGrappaGraph(SDG sdg) { return toGrappaGraph(sdg, null); } public static GrappaGraph toGrappaGraph(SDG sdg, Collection<DependenceNode> highlightedNodes) { LabelProvider fetcher = new LabelProvider(); return toGrappaGraph(sdg, highlightedNodes, fetcher); } public static GrappaGraph toGrappaGraph(SDG sdg, Collection<DependenceNode> highlighted, LabelProvider labelFetcher) { GrappaGraph sdgGraph = new GrappaGraph("SDG"); sdgGraph.setMenuable(true); sdgGraph.setEditable(true); sdgGraph.setAttribute("fontsize", "8"); //sdgGraph.setNodeAttribute("shape","box");//"ellipse"); Map<DependenceNode,Node> dep2grappa = new HashMap<DependenceNode,Node>(); for (PDG pdg: sdg.getPDGs()) { toGrappaGraph(pdg, sdgGraph, highlighted, dep2grappa, labelFetcher); } for (Map.Entry<DependenceNode, Collection<DependenceEdge>> entry : sdg.getExtraEdges()) { DependenceNode node = entry.getKey(); Node to = (Node) dep2grappa.get(node); Collection<DependenceEdge> inEdges = entry.getValue(); for (DependenceEdge e : inEdges) { DependenceNode fromNode = e.getFrom(); Node from = (Node) dep2grappa.get(fromNode); Edge grappaEdge = new Edge(sdgGraph, from, to); setGrappaEdgeProperty(e, grappaEdge); sdgGraph.addEdge(grappaEdge); } } return sdgGraph; } public static void dotSlice(DependenceGraph sdg, Set<DependenceNode> slice, String dotToolPath, String dotfile, boolean displayed){ GrappaGraph sliceGraph = null; if(sdg instanceof PDG){ sliceGraph = DependenceGraphHelper.toGrappaGraph((PDG)sdg, slice); } else if(sdg instanceof SDG){ sliceGraph = DependenceGraphHelper.toGrappaGraph((SDG)sdg, slice); } sliceGraph.saveToDot(dotfile); DotViewer dotView = new DotViewer(dotToolPath,dotfile); dotView.dotIt(); if(displayed){ dotView.view(); } } public static void dotDependenceGraph(DependenceGraph depGraph, String dotToolPath, String dotfile, boolean displayed){ GrappaGraph graph = null; if(depGraph instanceof PDG){ graph = DependenceGraphHelper.toGrappaGraph((PDG)depGraph); } else if(depGraph instanceof SDG){ graph = DependenceGraphHelper.toGrappaGraph((SDG)depGraph); } graph.saveToDot(dotfile); DotViewer dotView = new DotViewer(dotToolPath,dotfile); dotView.dotIt(); if(displayed){ dotView.view(); } } public static void showDependenceGraphByJGraph(DependenceGraph depGraph, String title){ DirectedGraph<DependenceNode> dgraph = depGraph.toDirectedGraph(); Graph graph = GraphHelper.toDisplayGraph(dgraph, title); GraphViewer frame = new GraphViewer(graph); frame.setSize(1000, 700); frame.setVisible(true); } public static SDG constructSDG(IPtsToQuery ptsto, HeapAbstraction heapAbstraction, ISideEffectAnalysis se, SootMethod entry, DepGraphOptions opts, boolean verbose, int javaLibDepth){ Collection<SootMethod> entries = new ArrayList<SootMethod>(1); entries.add(entry); // build def-use analysis CFGProvider cfgProvider = new HammockCFGProvider(); DUBuilder rdb = new DUBuilder(cfgProvider, ptsto, heapAbstraction, se, false); SDGBuilder sdgBuilder = new SDGBuilder(entries, opts, cfgProvider, ptsto, heapAbstraction, rdb.getGlobalDUQuery(), se, verbose, javaLibDepth); // initialize SDG builder sdgBuilder.preBuild(); sdgBuilder.buildAll(); sdgBuilder.postBuild(); SDG sdg = sdgBuilder.getSDG(); sdg.buildSummaryEdges(entry); sdg.connectPDGs(); // clean unnecessary info in points-to analysis SootUtils.cleanPAG(); // force clean, the following statements just notice that these should be released // they are redundant here se = null; rdb = null; sdgBuilder = null; return sdg; } }