26
26
import com .google .common .cache .LoadingCache ;
27
27
28
28
import heros .DontSynchronize ;
29
- import heros .InterproceduralCFG ;
30
29
import heros .SynchronizedBy ;
31
30
import heros .ThreadSafe ;
32
31
import heros .solver .IDESolver ;
39
38
import org .slf4j .Logger ;
40
39
import org .slf4j .LoggerFactory ;
41
40
41
+ import soot .FastHierarchy ;
42
42
import soot .MethodOrMethodContext ;
43
+ import soot .RefType ;
43
44
import soot .Scene ;
44
45
import soot .SootMethod ;
46
+ import soot .Type ;
45
47
import soot .Unit ;
48
+ import soot .jimple .InstanceInvokeExpr ;
49
+ import soot .jimple .InvokeExpr ;
46
50
import soot .jimple .Stmt ;
47
51
import soot .jimple .toolkits .callgraph .CallGraph ;
48
52
import soot .jimple .toolkits .callgraph .Edge ;
@@ -62,7 +66,23 @@ public class JimpleBasedInterproceduralCFG extends AbstractJimpleBasedICFG {
62
66
63
67
protected boolean includeReflectiveCalls = false ;
64
68
protected boolean includePhantomCallees = false ;
65
- protected boolean fallbackToImmediateCallees = true ;
69
+
70
+ public enum Fallback {
71
+ /**
72
+ * Do utilize any callee.
73
+ */
74
+ NONE ,
75
+ /**
76
+ * Use the immediate callee if the callgraph does not contain any edges for the respective call site.
77
+ */
78
+ IMMEDIATE_CALLEES ,
79
+ /**
80
+ * Assume Class-Hierarchy Analysis style that all subclasses are possible.
81
+ */
82
+ CHA
83
+ }
84
+
85
+ protected Fallback fallback = Fallback .NONE ;
66
86
67
87
// retains only callers that are explicit call sites or Thread.start()
68
88
public class EdgeFilter extends Filter {
@@ -108,10 +128,20 @@ public Collection<SootMethod> load(Unit u) throws Exception {
108
128
res .trimToSize ();
109
129
return res ;
110
130
} else {
111
- if (fallbackToImmediateCallees && u instanceof Stmt ) {
131
+ if (fallback != Fallback . NONE && u instanceof Stmt ) {
112
132
Stmt s = (Stmt ) u ;
113
133
if (s .containsInvokeExpr ()) {
114
- SootMethod immediate = s .getInvokeExpr ().getMethod ();
134
+ InvokeExpr invExpr = s .getInvokeExpr ();
135
+ SootMethod immediate = invExpr .getMethod ();
136
+ if (fallback == Fallback .CHA && invExpr instanceof InstanceInvokeExpr ) {
137
+ InstanceInvokeExpr instinv = (InstanceInvokeExpr ) invExpr ;
138
+ FastHierarchy fh = Scene .v ().getOrMakeFastHierarchy ();
139
+ Type t = instinv .getBase ().getType ();
140
+ if (t instanceof RefType ) {
141
+ RefType rt = (RefType ) t ;
142
+ return fh .resolveAbstractDispatch (rt .getSootClass (), instinv .getMethodRef ());
143
+ }
144
+ }
115
145
if (includePhantomCallees || immediate .hasActiveBody ()) {
116
146
return Collections .singleton (immediate );
117
147
}
@@ -191,15 +221,12 @@ public void setIncludePhantomCallees(boolean includePhantomCallees) {
191
221
}
192
222
193
223
/**
194
- * Sets whether methods that operate on the callgraph shall return the immediate callee of a call site if the callgraph has
195
- * no outgoing edges
224
+ * Sets the fallback mode. The fallback is used when the call graph reports no outgoing edges.
196
225
*
197
- * @param fallbackToImmediateCallees
198
- * True to return the immediate callee if the callgraph does not contain any edges for the respective call site,
199
- * false to return an empty set in such cases
226
+ * @param fallbackMode the fallback mode to use
200
227
*/
201
- public void setFallbackToImmediateCallees ( boolean fallbackToImmediateCallees ) {
202
- this .fallbackToImmediateCallees = fallbackToImmediateCallees ;
228
+ public void setFallbackMode ( Fallback fallbackMode ) {
229
+ this .fallback = fallbackMode ;
203
230
}
204
231
205
232
protected EdgeFilter createEdgeFilter () {
0 commit comments