MCPcopy Create free account
hub / github.com/LFYSec/MScan / CHABuilder

Class CHABuilder

src/main/java/pascal/taie/analysis/graph/callgraph/CHABuilder.java:48–118  ·  view source on GitHub ↗

Builds call graph via class hierarchy analysis.

Source from the content-addressed store, hash-verified

46 * Builds call graph via class hierarchy analysis.
47 */
48class CHABuilder implements CGBuilder<Invoke, JMethod> {
49
50 private static final Logger logger = LogManager.getLogger(CHABuilder.class);
51
52 private ClassHierarchy hierarchy;
53
54 /**
55 * Cache resolve results for interface/virtual invocations.
56 */
57 private TwoKeyMap<JClass, MemberRef, Set<JMethod>> resolveTable;
58
59 @Override
60 public CallGraph<Invoke, JMethod> build() {
61 return buildCallGraph(World.get().getMainMethod());
62 }
63
64 private CallGraph<Invoke, JMethod> buildCallGraph(JMethod entry) {
65 hierarchy = World.get().getClassHierarchy();
66 resolveTable = Maps.newTwoKeyMap();
67 DefaultCallGraph callGraph = new DefaultCallGraph();
68 callGraph.addEntryMethod(entry);
69 Queue<JMethod> workList = new ArrayDeque<>();
70 workList.add(entry);
71 while (!workList.isEmpty()) {
72 JMethod method = workList.poll();
73 callGraph.addReachableMethod(method);
74 callGraph.callSitesIn(method).forEach(invoke -> {
75 Set<JMethod> callees = resolveCalleesOf(invoke);
76 callees.forEach(callee -> {
77 if (!callGraph.contains(callee)) {
78 workList.add(callee);
79 }
80 callGraph.addEdge(new Edge<>(
81 CallGraphs.getCallKind(invoke), invoke, callee));
82 });
83 });
84 }
85 return callGraph;
86 }
87
88 /**
89 * Resolves callees of a call site via class hierarchy analysis.
90 */
91 private Set<JMethod> resolveCalleesOf(Invoke callSite) {
92 CallKind kind = CallGraphs.getCallKind(callSite);
93 return switch (kind) {
94 case INTERFACE, VIRTUAL -> {
95 MethodRef methodRef = callSite.getMethodRef();
96 JClass cls = methodRef.getDeclaringClass();
97 Set<JMethod> callees = resolveTable.get(cls, methodRef);
98 if (callees == null) {
99 callees = hierarchy.getAllSubclassesOf(cls)
100 .stream()
101 .filter(Predicate.not(JClass::isAbstract))
102 .map(c -> hierarchy.dispatch(c, methodRef))
103 .filter(Objects::nonNull) // filter out null callees
104 .collect(Collectors.toUnmodifiableSet());
105 resolveTable.put(cls, methodRef, callees);

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected