-
Notifications
You must be signed in to change notification settings - Fork 221
/
AnalysisOptions.java
405 lines (341 loc) · 12.8 KB
/
AnalysisOptions.java
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
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.ipa.callgraph;
import com.ibm.wala.analysis.reflection.ReflectionContextInterpreter;
import com.ibm.wala.analysis.reflection.ReflectionContextSelector;
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
import com.ibm.wala.ipa.callgraph.propagation.ReflectionHandler;
import com.ibm.wala.ssa.SSAOptions;
/**
* Basic interface for options that control call graph generation.
*
* TODO: This class should be refactored into an abstract base class and language-specific subclasses.
*/
public class AnalysisOptions {
/**
* An object that represents the analysis scope
*/
private AnalysisScope analysisScope;
/**
* An object that identifies the entrypoints for the call graph
*/
private Iterable<? extends Entrypoint> entrypoints;
/**
* Policy that determines types allocated at new statements.
*/
private ClassTargetSelector classTargetSelector;
/**
* Policy that determines methods called at call sites.
*/
private MethodTargetSelector methodTargetSelector;
/**
* A tuning parameter; how may new equations must be added before doing a new topological sort?
*/
private int minEquationsForTopSort = 100;
/**
* A tuning parameter; by what percentage must the number of equations grow before we perform a topological sort?
*/
private double topologicalGrowthFactor = 0.5;
/**
* A tuning parameter: how many evaluations are allowed to take place between topological re-orderings. The idea is that many
* evaluations may be a sign of a bad ordering, even when few new equations are being added.
*/
private int maxEvalBetweenTopo = 1000000000;
/**
* options for handling reflection during call graph construction
*/
public static enum ReflectionOptions {
FULL("full", Integer.MAX_VALUE, false, false), NO_FLOW_TO_CASTS("no_flow_to_casts", 0, false, false), NO_METHOD_INVOKE(
"no_method_invoke", Integer.MAX_VALUE, true, false), NO_FLOW_TO_CASTS_NO_METHOD_INVOKE("no_flow_to_casts_no_method_invoke",
0, true, false), ONE_FLOW_TO_CASTS_NO_METHOD_INVOKE("one_flow_to_casts_no_method_invoke", 1, true, false), NO_STRING_CONSTANTS(
"no_string_constants", Integer.MAX_VALUE, false, true), NONE("none", 0, true, true);
private final String name;
/**
* how many times should flows from newInstance() calls to casts be analyzed?
*/
private final int numFlowToCastIterations;
/**
* should calls to Method.invoke() be ignored?
*/
private final boolean ignoreMethodInvoke;
/**
* should calls to reflective methods with String constant arguments be ignored?
*/
private final boolean ignoreStringConstants;
private ReflectionOptions(String name, int numFlowToCastIterations, boolean ignoreMethodInvoke, boolean ignoreInterpretCalls) {
this.name = name;
this.numFlowToCastIterations = numFlowToCastIterations;
this.ignoreMethodInvoke = ignoreMethodInvoke;
this.ignoreStringConstants = ignoreInterpretCalls;
}
public String getName() {
return name;
}
public int getNumFlowToCastIterations() {
return numFlowToCastIterations;
}
public boolean isIgnoreMethodInvoke() {
return ignoreMethodInvoke;
}
public boolean isIgnoreStringConstants() {
return ignoreStringConstants;
}
}
/**
* Should call graph construction attempt to handle reflection via detection of flows to casts, analysis of string constant
* parameters to reflective methods, etc.?
*
* @see ReflectionHandler
* @see ReflectionContextInterpreter
* @see ReflectionContextSelector
*/
private ReflectionOptions reflectionOptions = ReflectionOptions.FULL;
/**
* Should call graph construction handle possible invocations of static initializer methods?
*/
private boolean handleStaticInit = true;
/**
* Options governing SSA construction
*/
private SSAOptions ssaOptions = new SSAOptions();
/**
* Use distinct instance keys for distinct string constants?
*
* TODO: Probably, this option should moved somewhere into the creation of instance keys. However, those factories are created
* within the various builders right now, and this is the most convenient place for an engine user to set an option which the
* creation of instance keys later picks up.
*/
private boolean useConstantSpecificKeys = false;
/**
* Should analysis of lexical scoping consider call stacks?
*
* TODO: this option does not apply to all languages. We could have a separation into core engine options and language-specific
* options.
*
* (be careful with multithreaded languages, as threading can break the stack discipline this option may assume)
*/
private boolean useStacksForLexicalScoping = false;
/**
* Should global variables be considered lexically-scoped from the root node?
*
* TODO: this option does not apply to all languages. We could have a separation into core engine options and language-specific
* options.
*
* (be careful with multithreaded languages, as threading can break the stack discipline this option may assume)
*/
private boolean useLexicalScopingForGlobals = false;
/**
* Should analysis try to understand the results of string constants flowing to a + operator? Note that this option does not apply
* to Java bytecode analysis, since the + operators have been compiled away for that. It is used for the Java CAst front end.
*/
private boolean traceStringConstants = false;
/**
* This numerical value indicates the maximum number of nodes that any {@link CallGraph} build with this {@link AnalysisOptions}
* object is allowed to have. During {@link CallGraph} construction, once <code>maxNumberOfNodes</code> {@link CGNode} objects
* have been added to the {@link CallGraph}, no more {@link CGNode} objects will be added. By default,
* <code>maxNumberOfNodes</code> is set to <code>-1</code>, which indicates that no restrictions are in place. See also
* {@link ExplicitCallGraph}.
*/
private long maxNumberOfNodes = -1;
// SJF: I'm not sure these factories and caches belong here.
// TODO: figure out how to clean this up.
public AnalysisOptions() {
}
public AnalysisOptions(AnalysisScope scope, Iterable<? extends Entrypoint> e) {
this.analysisScope = scope;
this.entrypoints = e;
}
public AnalysisScope getAnalysisScope() {
return analysisScope;
}
public void setAnalysisScope(AnalysisScope analysisScope) {
this.analysisScope = analysisScope;
}
/**
* TODO: this really should go away. The entrypoints don't belong here.
*/
public Iterable<? extends Entrypoint> getEntrypoints() {
return entrypoints;
}
public void setEntrypoints(Iterable<? extends Entrypoint> entrypoints) {
this.entrypoints = entrypoints;
}
public long getMaxNumberOfNodes() {
return maxNumberOfNodes;
}
public void setMaxNumberOfNodes(long maxNumberOfNodes) {
this.maxNumberOfNodes = maxNumberOfNodes;
}
/**
* @return Policy that determines methods called at call sites.
*/
public MethodTargetSelector getMethodTargetSelector() {
return methodTargetSelector;
}
/**
* @return Policy that determines types allocated at new statements.
*/
public ClassTargetSelector getClassTargetSelector() {
return classTargetSelector;
}
/**
* install a method target selector
*
* @param x an object which controls the policy for selecting the target at a call site
*/
public void setSelector(MethodTargetSelector x) {
methodTargetSelector = x;
}
/**
* install a class target selector
*
* @param x an object which controls the policy for selecting the allocated object at a new site
*/
public void setSelector(ClassTargetSelector x) {
classTargetSelector = x;
}
/**
* @return the mininum number of equations that the pointer analysis system must contain before the solver will try to
* topologically sore
*/
public int getMinEquationsForTopSort() {
return minEquationsForTopSort;
}
/**
* @param i the mininum number of equations that the pointer analysis system must contain before the solver will try to
* topologically sore
*/
public void setMinEquationsForTopSort(int i) {
minEquationsForTopSort = i;
}
/**
* @return the maximum number of evaluations that the pointer analysis solver will perform before topologically resorting the
* system
*/
public int getMaxEvalBetweenTopo() {
return maxEvalBetweenTopo;
}
/**
* @return a fraction x s.t. the solver will resort the system when it grows by a factor of x
*/
public double getTopologicalGrowthFactor() {
return topologicalGrowthFactor;
}
/**
* @param i the maximum number of evaluations that the pointer analysis solver will perform before topologically resorting the
* system
*/
public void setMaxEvalBetweenTopo(int i) {
maxEvalBetweenTopo = i;
}
/**
* @param d a fraction x s.t. the solver will resort the system when it grows by a factor of x
*/
public void setTopologicalGrowthFactor(double d) {
topologicalGrowthFactor = d;
}
/**
* @return options governing SSA construction
*/
public SSAOptions getSSAOptions() {
return ssaOptions;
}
/**
* @param ssaOptions options governing SSA construction
*/
public void setSSAOptions(SSAOptions ssaOptions) {
this.ssaOptions = ssaOptions;
}
/**
* Use distinct instance keys for distinct string constants?
*/
public boolean getUseConstantSpecificKeys() {
return useConstantSpecificKeys;
}
/**
* Use distinct instance keys for distinct string constants?
*/
public void setUseConstantSpecificKeys(boolean useConstantSpecificKeys) {
this.useConstantSpecificKeys = useConstantSpecificKeys;
}
/**
* Should analysis of lexical scoping consider call stacks?
*/
public boolean getUseStacksForLexicalScoping() {
return useStacksForLexicalScoping;
}
/**
* Should analysis of lexical scoping consider call stacks?
*/
public void setUseStacksForLexicalScoping(boolean v) {
useStacksForLexicalScoping = v;
}
/**
* Should global variables be considered lexically-scoped from the root node?
*/
public boolean getUseLexicalScopingForGlobals() {
return useLexicalScopingForGlobals;
}
/**
* Should global variables be considered lexically-scoped from the root node?
*/
public void setUseLexicalScopingForGlobals(boolean v) {
useLexicalScopingForGlobals = v;
}
/**
* Should analysis try to understand the results of string constants flowing to a + operator? Note that this option does not apply
* to Java bytecode analysis, since the + operators have been compiled away for that. It is used for the Java CAst front end.
*/
public void setTraceStringConstants(boolean v) {
traceStringConstants = v;
}
/**
* Should analysis try to understand the results of string constants flowing to a + operator? Note that this option does not apply
* to Java bytecode analysis, since the + operators have been compiled away for that. It is used for the Java CAst front end.
*/
public boolean getTraceStringConstants() {
return traceStringConstants;
}
/**
* Should call graph construction attempt to handle reflection via detection of flows to casts, analysis of string constant
* parameters to reflective methods, etc.?
*
* @see ReflectionHandler
* @see ReflectionContextInterpreter
* @see ReflectionContextSelector
*/
public ReflectionOptions getReflectionOptions() {
return reflectionOptions;
}
/**
* Should call graph construction attempt to handle reflection via detection of flows to casts, analysis of string constant
* parameters to reflective methods, etc.?
*
* @see ReflectionHandler
* @see ReflectionContextInterpreter
* @see ReflectionContextSelector
*/
public void setReflectionOptions(ReflectionOptions reflectionOptions) {
this.reflectionOptions = reflectionOptions;
}
/**
* Should call graph construction handle possible invocations of static initializer methods?
*/
public boolean getHandleStaticInit() {
return handleStaticInit;
}
/**
* Should call graph construction handle possible invocations of static initializer methods?
*/
public void setHandleStaticInit(boolean handleStaticInit) {
this.handleStaticInit = handleStaticInit;
}
}