1 19 20 25 26 27 package soot.tools; 28 29 import java.lang.reflect.Method ; 30 import java.util.*; 31 32 import soot.*; 33 import soot.baf.Baf; 34 import soot.toolkits.exceptions.*; 35 import soot.jimple.JimpleBody; 36 import soot.grimp.Grimp; 37 import soot.shimple.Shimple; 38 import soot.toolkits.graph.*; 39 import soot.options.Options; 40 import soot.util.dot.DotGraph; 41 import soot.util.cfgcmd.AltClassLoader; 42 import soot.util.cfgcmd.CFGGraphType; 43 import soot.util.cfgcmd.CFGIntermediateRep; 44 import soot.util.cfgcmd.CFGOptionMatcher; 45 import soot.util.cfgcmd.CFGToDotGraph; 46 import soot.util.*; 47 48 53 public class CFGViewer extends BodyTransformer { 54 55 private static final String packToJoin = "jtp"; 56 private static final String phaseSubname = "printcfg"; 57 private static final String phaseFullname = packToJoin + '.' + phaseSubname; 58 private static final String altClassPathOptionName = "alt-class-path"; 59 private static final String graphTypeOptionName = "graph-type"; 60 private static final String defaultGraph = "BriefUnitGraph"; 61 private static final String irOptionName = "ir"; 62 private static final String defaultIR = "jimple"; 63 private static final String multipageOptionName = "multipages"; 64 private static final String briefLabelOptionName = "brief"; 65 66 private CFGGraphType graphtype; 67 private CFGIntermediateRep ir; 68 private ThrowAnalysis throwAnalysis; 69 private CFGToDotGraph drawer; 70 private Map methodsToPrint; 75 76 protected void internalTransform(Body b, String phaseName, Map options) { 77 initialize(options); 78 SootMethod meth = b.getMethod(); 79 80 if ((methodsToPrint == null) || 81 (meth.getDeclaringClass().getName() == 82 methodsToPrint.get(meth.getName()))) { 83 Body body = ir.getBody((JimpleBody) b); 84 print_cfg(body); 85 } 86 } 87 88 89 public static void main(String [] args) { 90 CFGViewer viewer = new CFGViewer(); 91 Transform printTransform = new Transform(phaseFullname, viewer); 92 printTransform.setDeclaredOptions("enabled " + 93 altClassPathOptionName + ' ' + 94 graphTypeOptionName + ' ' + 95 irOptionName + ' ' + 96 multipageOptionName + ' ' + 97 briefLabelOptionName + ' '); 98 printTransform.setDefaultOptions("enabled " + 99 altClassPathOptionName + ": " + 100 graphTypeOptionName + ':' + defaultGraph + 101 ' ' + irOptionName + ':' + defaultIR + 102 ' ' + multipageOptionName + ":false " + 103 ' ' + briefLabelOptionName + ":false "); 104 PackManager.v().getPack("jtp").add(printTransform); 105 args = viewer.parse_options(args); 106 if (args.length == 0) { 107 usage(); 108 } else { 109 soot.Main.main(args); 110 } 111 } 112 113 114 private static void usage(){ 115 G.v().out.println( 116 "Usage:\n" + 117 " java soot.util.CFGViewer [soot options] [CFGViewer options] [class[:method]]...\n\n" + 118 " CFGViewer options:\n" + 119 " (When specifying the value for an '=' option, you only\n" + 120 " need to type enough characters to specify the choice\n" + 121 " unambiguously, and case is ignored.)\n" + 122 "\n" + 123 " --alt-classpath PATH :\n" + 124 " specifies the classpath from which to load classes\n" + 125 " that implement graph types whose names begin with 'Alt'.\n" + 126 " --graph={" + 127 CFGGraphType.help(0, 70, 128 " ".length()) + "} :\n" + 129 " show the specified type of graph.\n" + 130 " Defaults to " + defaultGraph + ".\n" + 131 " --ir={" + 132 CFGIntermediateRep.help(0, 70, 133 " ".length()) + "} :\n" + 134 " create the CFG from the specified intermediate\n" + 135 " representation. Defaults to " + defaultIR + ".\n" + 136 " --brief :\n" + 137 " label nodes with the unit or block index,\n" + 138 " instead of the text of their statements.\n" + 139 " --multipages :\n" + 140 " produce dot file output for multiple 8.5x11\" pages.\n" + 141 " By default, a single page is produced.\n" + 142 " --help :\n" + 143 " print this message.\n" + 144 "\n" + 145 " Particularly relevant soot options (see \"soot --help\" for details):\n" + 146 " --soot-class-path PATH\n" + 147 " --show-exception-dests\n" + 148 " --throw-analysis {pedantic|unit}\n" + 149 " --omit-excepting-unit-edges\n" + 150 " --trim-cfgs\n" 151 ); 152 } 153 154 160 private String [] parse_options(String [] args){ 161 List sootArgs = new ArrayList(args.length); 162 163 for (int i=0, n=args.length; i<n; i++) { 164 if (args[i].equals("--alt-classpath") || 165 args[i].equals("--alt-class-path")) { 166 sootArgs.add("-p"); 167 sootArgs.add(phaseFullname); 168 sootArgs.add(altClassPathOptionName + ':' + args[++i]); 169 } else if (args[i].startsWith("--graph=")) { 170 sootArgs.add("-p"); 171 sootArgs.add(phaseFullname); 172 sootArgs.add(graphTypeOptionName + ':' + args[i].substring("--graph=".length())); 173 } else if (args[i].startsWith("--ir=")) { 174 sootArgs.add("-p"); 175 sootArgs.add(phaseFullname); 176 sootArgs.add(irOptionName + ':' + args[i].substring("--ir=".length())); 177 } else if (args[i].equals("--brief")) { 178 sootArgs.add("-p"); 179 sootArgs.add(phaseFullname); 180 sootArgs.add(briefLabelOptionName + ":true"); 181 } else if (args[i].equals("--multipages")) { 182 sootArgs.add("-p"); 183 sootArgs.add(phaseFullname); 184 sootArgs.add(multipageOptionName + ":true"); 185 } else if (args[i].equals("--help")) { 186 return new String [0]; } else if (args[i].equals("--soot-class-path") || 190 args[i].equals("-soot-class-path") || 191 args[i].equals("--soot-classpath") || 192 args[i].equals("-soot-classpath")) { 193 sootArgs.add(args[i]); 195 sootArgs.add(args[++i]); 196 } else if (args[i].equals("-p") || 197 args[i].equals("--phase-option") || 198 args[i].equals("-phase-option")) { 199 sootArgs.add(args[i]); 201 sootArgs.add(args[++i]); 202 sootArgs.add(args[++i]); 203 } else { 204 int smpos = args[i].indexOf(':'); 205 if (smpos == -1) { 206 sootArgs.add(args[i]); 207 } else { 208 String clsname = args[i].substring(0, smpos); 209 sootArgs.add(clsname); 210 String methname = args[i].substring(smpos+1); 211 if (methodsToPrint == null) { 212 methodsToPrint = new HashMap(); 213 } 214 methodsToPrint.put(methname, clsname); 215 } 216 } 217 } 218 String [] sootArgsArray = new String [sootArgs.size()]; 219 return (String []) sootArgs.toArray(sootArgsArray); 220 } 221 222 private void initialize(Map options) { 223 if (drawer == null) { 224 drawer = new CFGToDotGraph(); 225 drawer.setBriefLabels(PhaseOptions.getBoolean(options, briefLabelOptionName)); 226 drawer.setOnePage(! PhaseOptions.getBoolean(options, multipageOptionName)); 227 drawer.setUnexceptionalControlFlowAttr("color", "black"); 228 drawer.setExceptionalControlFlowAttr("color", "red"); 229 drawer.setExceptionEdgeAttr("color", "lightgray"); 230 drawer.setShowExceptions(Options.v().show_exception_dests()); 231 ir = CFGIntermediateRep.getIR(PhaseOptions.getString(options, irOptionName)); 232 graphtype = CFGGraphType.getGraphType(PhaseOptions.getString(options, 233 graphTypeOptionName)); 234 235 AltClassLoader.v().setAltClassPath(PhaseOptions.getString(options, 236 altClassPathOptionName)); 237 AltClassLoader.v().setAltClasses(new String [] { 238 "soot.toolkits.graph.ArrayRefBlockGraph", 239 "soot.toolkits.graph.Block", 240 "soot.toolkits.graph.Block$AllMapTo", 241 "soot.toolkits.graph.BlockGraph", 242 "soot.toolkits.graph.BriefBlockGraph", 243 "soot.toolkits.graph.BriefUnitGraph", 244 "soot.toolkits.graph.CompleteBlockGraph", 245 "soot.toolkits.graph.CompleteUnitGraph", 246 "soot.toolkits.graph.TrapUnitGraph", 247 "soot.toolkits.graph.UnitGraph", 248 "soot.toolkits.graph.ZonedBlockGraph", 249 }); 250 } 251 } 252 253 protected void print_cfg(Body body) { 254 DirectedGraph graph = graphtype.buildGraph(body); 255 DotGraph canvas = graphtype.drawGraph(drawer, graph, body); 256 257 String methodname = body.getMethod().getSubSignature(); 258 String filename = soot.SourceLocator.v().getOutputDir(); 259 if (filename.length() > 0) { 260 filename = filename + java.io.File.separator; 261 } 262 filename = filename + 263 methodname.replace(java.io.File.separatorChar, '.') + 264 DotGraph.DOT_EXTENSION; 265 266 G.v().out.println("Generate dot file in "+filename); 267 canvas.plot(filename); 268 } 269 } 270 | Popular Tags |