KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > tools > CFGViewer


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2002 Sable Research Group
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */

19
20 /*
21  * Modified by the Sable Research Group and others 2002-2003.
22  * See the 'credits' file distributed with Soot for the complete list of
23  * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
24  */

25
26
27 package soot.tools;
28
29 import java.lang.reflect.Method JavaDoc;
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 /**
49  * A utility class for generating dot graph file for a control flow graph
50  *
51  * @author Feng Qian
52  */

53 public class CFGViewer extends BodyTransformer {
54
55   private static final String JavaDoc packToJoin = "jtp";
56   private static final String JavaDoc phaseSubname = "printcfg";
57   private static final String JavaDoc phaseFullname = packToJoin + '.' + phaseSubname;
58   private static final String JavaDoc altClassPathOptionName = "alt-class-path";
59   private static final String JavaDoc graphTypeOptionName = "graph-type";
60   private static final String JavaDoc defaultGraph = "BriefUnitGraph";
61   private static final String JavaDoc irOptionName = "ir";
62   private static final String JavaDoc defaultIR = "jimple";
63   private static final String JavaDoc multipageOptionName = "multipages";
64   private static final String JavaDoc briefLabelOptionName = "brief";
65
66   private CFGGraphType graphtype;
67   private CFGIntermediateRep ir;
68   private ThrowAnalysis throwAnalysis;
69   private CFGToDotGraph drawer;
70   private Map methodsToPrint; // If the user specifies particular
71
// methods to print, this is a map
72
// from method name to the class
73
// name declaring the method.
74

75
76   protected void internalTransform(Body b, String JavaDoc 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 JavaDoc[] 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   /**
155    * Parse the command line arguments specific to CFGViewer,
156    * and convert them into phase options for jtp.printcfg.
157    *
158    * @return an array of arguments to pass on to Soot.Main.main().
159    */

160   private String JavaDoc[] parse_options(String JavaDoc[] 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 JavaDoc[0]; // This is a cheesy method to inveigle
187
// our caller into printing the help
188
// and exiting.
189
} 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     // Pass classpaths without treating ":" as a method specifier.
194
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     // Pass phase options without treating ":" as a method specifier.
200
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 JavaDoc clsname = args[i].substring(0, smpos);
209       sootArgs.add(clsname);
210       String JavaDoc 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 JavaDoc[] sootArgsArray = new String JavaDoc[sootArgs.size()];
219     return (String JavaDoc[]) 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 JavaDoc[] {
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 JavaDoc methodname = body.getMethod().getSubSignature();
258     String JavaDoc 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