This commit is contained in:
Claudio Maggioni 2023-11-18 17:49:53 +01:00
parent 621a95e291
commit 300a6099b7
3 changed files with 23 additions and 17 deletions

View file

@ -54,14 +54,16 @@ public final class CallGraphBuilder implements ClassAnalyzer {
if (opCode == Opcodes.INVOKESTATIC || opCode == Opcodes.INVOKESPECIAL) {
// target is static, no fancy search needed
callSite.addPossibleTargetClass(clazz); // Cave Johnson, we're done here
} else if (opCode == Opcodes.INVOKEDYNAMIC) {
} else if (opCode == Opcodes.INVOKEVIRTUAL) {
final Deque<ClassType> subClasses = new ArrayDeque<>();
subClasses.add(clazz);
// BFS over class and subclasses and add them all as possible targets
while (!subClasses.isEmpty()) {
final ClassType subClazz = subClasses.pop();
if (!subClazz.isAbstract()) {
callSite.addPossibleTargetClass(subClazz);
}
subClasses.addAll(subClazz.getSubTypes());
}
} else { // opCode == Opcodes.INVOKEINTERFACE

View file

@ -48,31 +48,25 @@ public class DotGraph {
}
private void scanMethods() {
final Deque<DotMethodNode> methodQueue = new ArrayDeque<>(methodNodes.getAll());
while (!methodQueue.isEmpty()) {
final DotMethodNode methodNode = methodQueue.pop();
final Method m = methodNode.getMethodLike().getMethod();
for (final DotMethodNode fromMethodNode : methodNodes.getAll()) {
final Method m = fromMethodNode.getMethodLike().getMethod();
if (m == null) continue; // we care about actual methods only, not callsites
for (final CallSite c : m.getCallSites()) {
final DotMethodNode toMethodNode = methodNodes.addIfNew(new DotMethodNode(new CallSiteAdapter(c)));
otherEdges.add(new InvokeEdge(methodNode, toMethodNode, c.getOpcode(), true));
otherEdges.add(new InvokeEdge(fromMethodNode, toMethodNode, c.getOpcode(), true));
for (final ClassType p : c.getPossibleTargetClasses()) {
if (p.getInternalName().endsWith("Math")) {
System.out.println("aaa");
}
final DotMethodNode pm = methodNodes.addIfNew(new DotMethodNode(new PossibleTargetAdapter(c, p)));
final DotClassNode pc = classNodes.addIfNew(new DotClassNode(p));
final DotMethodNode toPossibleMethodNode = methodNodes.addIfNew(new DotMethodNode(new PossibleTargetAdapter(c, p)));
otherEdges.add(new InvokeEdge(fromMethodNode, toPossibleMethodNode, c.getOpcode(), false));
// if the target is a new node, the class of that node might not have been analyzed,
// thus class to method edges might not have been added
classToMethodEdges.add(new ClassToMethodEdge(pc, pm));
// thus class to method edges might not have been added. We re-add the class to method edge, and
// duplicates are handled by the Set collection.
final DotClassNode toPossibleClassNode = classNodes.addIfNew(new DotClassNode(p));
classToMethodEdges.add(new ClassToMethodEdge(toPossibleClassNode, toPossibleMethodNode));
}
otherEdges.add(new InvokeEdge(methodNode, toMethodNode, c.getOpcode(), false));
}
}
}

View file

@ -57,4 +57,14 @@ public class InvokeEdge implements DotEdge {
public DotMethodNode getTo() {
return to;
}
@Override
public String toString() {
return "InvokeEdge{" +
"from=" + from.getMethodLike().prettyName() +
", to=" + to.getMethodLike().prettyName() +
", invokeOpCode=" + invokeOpCode +
", isDeclared=" + isDeclared +
'}';
}
}