forked from soot-oss/soot
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMain.java
More file actions
318 lines (267 loc) · 10.7 KB
/
Main.java
File metadata and controls
318 lines (267 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
package soot;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 1997 - 2012 Raja Vallee-Rai and others
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
*/
import static java.net.URLEncoder.encode;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import soot.options.CGOptions;
import soot.options.Options;
import soot.toolkits.astmetrics.ClassData;
/**
* Main class for Soot; provides Soot's command-line user interface.
*/
public class Main {
public Main(Singletons.Global g) {
}
public static Main v() {
return G.v().soot_Main();
}
// TODO: the following string should be updated by the source control
// No it shouldn't. Prcs is horribly broken in this respect, and causes
// the code to not compile all the time.
public static final String versionString = Main.class.getPackage().getImplementationVersion() == null ? "trunk"
: Main.class.getPackage().getImplementationVersion();
private Date start;
private long startNano;
private long finishNano;
private void printVersion() {
System.out.println("Soot version " + versionString);
System.out.println("Copyright (C) 1997-2010 Raja Vallee-Rai and others.");
System.out.println("All rights reserved.");
System.out.println();
System.out.println("Contributions are copyright (C) 1997-2010 by their respective contributors.");
System.out.println("See the file 'credits' for a list of contributors.");
System.out.println("See individual source files for details.");
System.out.println();
System.out.println("Soot comes with ABSOLUTELY NO WARRANTY. Soot is free software,");
System.out.println("and you are welcome to redistribute it under certain conditions.");
System.out.println("See the accompanying file 'COPYING-LESSER.txt' for details.");
System.out.println("Visit the Soot website:");
System.out.println(" http://www.sable.mcgill.ca/soot/");
System.out.println("For a list of command line options, enter:");
System.out.println(" java soot.Main --help");
}
private void processCmdLine(String[] args) {
final Options opts = Options.v();
if (!opts.parse(args)) {
throw new OptionsParseException("Option parse error");
}
if (PackManager.v().onlyStandardPacks()) {
for (Pack pack : PackManager.v().allPacks()) {
opts.warnForeignPhase(pack.getPhaseName());
for (Transform tr : pack) {
opts.warnForeignPhase(tr.getPhaseName());
}
}
}
opts.warnNonexistentPhase();
if (opts.help()) {
System.out.println(opts.getUsage());
throw new CompilationDeathException(CompilationDeathException.COMPILATION_SUCCEEDED);
}
if (opts.phase_list()) {
System.out.println(opts.getPhaseList());
throw new CompilationDeathException(CompilationDeathException.COMPILATION_SUCCEEDED);
}
if (!opts.phase_help().isEmpty()) {
for (String phase : opts.phase_help()) {
System.out.println(opts.getPhaseHelp(phase));
}
throw new CompilationDeathException(CompilationDeathException.COMPILATION_SUCCEEDED);
}
if ((!opts.unfriendly_mode() && (args.length == 0)) || opts.version()) {
printVersion();
throw new CompilationDeathException(CompilationDeathException.COMPILATION_SUCCEEDED);
}
if (opts.on_the_fly()) {
opts.set_whole_program(true);
PhaseOptions.v().setPhaseOption("cg", "off");
}
postCmdLineCheck();
}
private void postCmdLineCheck() {
if (Options.v().classes().isEmpty() && Options.v().process_dir().isEmpty()) {
throw new CompilationDeathException(CompilationDeathException.COMPILATION_ABORTED, "No input classes specified!");
}
}
public String[] cmdLineArgs = new String[0];
/**
* Entry point for cmd line invocation of soot.
*/
public static void main(String[] args) {
try {
Main.v().run(args);
} catch (OptionsParseException e) {
// error message has already been printed
} catch (StackOverflowError e) {
System.err.println("Soot has run out of stack memory.");
System.err.println("To allocate more stack memory to Soot, use the -Xss switch to Java.");
System.err.println("For example (for 2MB): java -Xss2m soot.Main ...");
throw e;
} catch (OutOfMemoryError e) {
System.err.println("Soot has run out of the memory allocated to it by the Java VM.");
System.err.println("To allocate more memory to Soot, use the -Xmx switch to Java.");
System.err.println("For example (for 2GB): java -Xmx2g soot.Main ...");
throw e;
} catch (RuntimeException e) {
e.printStackTrace();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(bos));
String stackStraceString = bos.toString();
final String TRACKER_URL = "https://github.com/soot-oss/soot/issues/new?";
String body = "Steps to reproduce:\n1.) ...\n\n" + "Files used to reproduce: \n...\n\n" + "Soot version: " + "<pre>"
+ escape(versionString) + "</pre>\n\n" + "Command line:\n" + "<pre>" + escape(String.join(" ", args))
+ "</pre>\n\n" + "Max Memory:\n" + "<pre>" + escape((Runtime.getRuntime().maxMemory() / (1024 * 1024)) + "MB")
+ "</pre>\n\n" + "Stack trace:\n" + "<pre>" + escape(stackStraceString) + "</pre>";
String title = e.getClass().getName() + " when ...";
try {
StringBuilder sb = new StringBuilder();
sb.append("\n\nOuuups... something went wrong! Sorry about that.\n");
sb.append("Follow these steps to fix the problem:\n");
sb.append("1.) Are you sure you used the right command line?\n");
sb.append(" Click here to double-check:\n");
sb.append(" https://github.com/soot-oss/soot/wiki/Options-and-JavaDoc\n");
sb.append('\n');
sb.append("2.) Not sure whether it's a bug? Feel free to discuss\n");
sb.append(" the issue on the Soot mailing list:\n");
sb.append(" https://github.com/soot-oss/soot/wiki/Getting-help\n");
sb.append('\n');
sb.append("3.) Sure it's a bug? Click this link to report it.\n");
sb.append(" " + TRACKER_URL + "title=").append(encode(title, "UTF-8"));
sb.append("&body=").append(encode(body, "UTF-8")).append('\n');
sb.append(" Please be as precise as possible when giving us\n");
sb.append(" information on how to reproduce the problem. Thanks!");
System.err.println(sb);
// Exit with an exit code 1
System.exit(1);
} catch (UnsupportedEncodingException e1) {
// Exit with an exit code 1
System.exit(1);
}
}
}
private static CharSequence escape(CharSequence s) {
final int end = s.length();
int start = 0;
StringBuilder sb = new StringBuilder(32 + (end - start));
for (int i = start; i < end; i++) {
int c = s.charAt(i);
switch (c) {
case '<':
case '>':
case '"':
case '\'':
case '&':
sb.append(s, start, i);
sb.append("&#");
sb.append(c);
sb.append(';');
start = i + 1;
break;
}
}
return sb.append(s, start, end);
}
/**
* Entry point to the soot's compilation process.
*/
public void run(String[] args) {
cmdLineArgs = args;
start = new Date();
startNano = System.nanoTime();
try {
Timers.v().totalTimer.start();
processCmdLine(cmdLineArgs);
autoSetOptions();
System.out.println("Soot started on " + start);
Scene.v().loadNecessaryClasses();
/*
* By this all the java to jimple has occured so we just check ast-metrics flag
*
* If it is set......print the astMetrics.xml file and stop executing soot
*/
if (Options.v().ast_metrics()) {
try (OutputStream streamOut = new FileOutputStream("../astMetrics.xml")) {
PrintWriter writerOut = new PrintWriter(new OutputStreamWriter(streamOut));
writerOut.println("<?xml version='1.0'?>");
writerOut.println("<ASTMetrics>");
for (ClassData cData : G.v().ASTMetricsData) {
// each is a classData object
writerOut.println(cData);
}
writerOut.println("</ASTMetrics>");
writerOut.flush();
} catch (IOException e) {
throw new CompilationDeathException("Cannot output file astMetrics", e);
}
return;
}
PackManager.v().runPacks();
if (!Options.v().oaat()) {
PackManager.v().writeOutput();
}
Timers.v().totalTimer.end();
// Print out time stats.
if (Options.v().time()) {
Timers.v().printProfilingInformation();
}
} catch (CompilationDeathException e) {
Timers.v().totalTimer.end();
if (e.getStatus() != CompilationDeathException.COMPILATION_SUCCEEDED) {
throw e;
} else {
return;
}
}
finishNano = System.nanoTime();
System.out.println("Soot finished on " + new Date());
long runtime = (finishNano - startNano) / 1000000l;
System.out.println("Soot has run for " + (runtime / 60000) + " min. " + ((runtime % 60000) / 1000) + " sec.");
}
public void autoSetOptions() {
final Options opts = Options.v();
// when no-bodies-for-excluded is enabled, also enable phantom refs
if (opts.no_bodies_for_excluded()) {
opts.set_allow_phantom_refs(true);
}
// when reflection log is enabled, also enable phantom refs
CGOptions cgOptions = new CGOptions(PhaseOptions.v().getPhaseOptions("cg"));
String log = cgOptions.reflection_log();
if (log != null && !log.isEmpty()) {
opts.set_allow_phantom_refs(true);
}
// if phantom refs enabled, ignore wrong staticness in type assigner
if (opts.allow_phantom_refs()) {
opts.set_wrong_staticness(Options.wrong_staticness_fix);
}
if (opts.java_version() != Options.java_version_default) {
opts.set_derive_java_version(false);
}
}
}