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

View file

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