public class CallResolver extends java.lang.Object implements AttributeVisitor, ClassVisitor, InstructionVisitor
All method invocation instructions that appear in the bytecode are inspected, and their actual
target method is calculated. Java has several invocation instructions, performing virtual,
static, dynamic, interface and special calls. While most of these instructions have a constant
operand specifying a method name, the actual method that will be called at runtime depends on
multiple factors. Sometimes, e.g. when using virtual calls, the invocation target depends on the
specific type of the first parameter on the stack, the so-called this
pointer.
This call analyzer performs a lookup process that adheres to the Java Virtual Machine
specification. Being a static analysis, 100% precision cannot be guaranteed, as the specific type
of variables at a specific program point is not always known in advance. But using the PartialEvaluator
in combination with intraprocedural possible type analysis of MultiTypedReferenceValue
objects, the resulting call graph should be a superset of the actual
calls happening at runtime. This makes it a complete but potentially unsound analysis.
In addition to resolving the call target, this analyzer also reconstructs the corresponding
arguments and the return value. All of the collected information is wrapped in a Call
object and passed to subscribed CallVisitor
s.
Modifier and Type | Class and Description |
---|---|
static class |
CallResolver.Builder |
Constructor and Description |
---|
CallResolver(ClassPool programClassPool,
ClassPool libraryClassPool,
CallGraph callGraph,
boolean clearCallValuesAfterVisit,
boolean useDominatorAnalysis,
boolean evaluateAllCode,
boolean includeSubClasses,
int maxPartialEvaluations,
java.util.function.Supplier<java.lang.Boolean> shouldAnalyzeNextCodeAttribute,
boolean skipIncompleteCalls,
ValueFactory arrayValueFactory,
boolean ignoreExceptions,
ExecutingInvocationUnit.Builder executingInvocationUnitBuilder,
boolean selectiveParameterReconstruction,
java.util.Set<MethodSignature> interestingMethods,
java.util.Set<java.util.function.Predicate<Call>> interestingCallPredicates,
CallVisitor... visitors)
Create a new call resolver.
|
Modifier and Type | Method and Description |
---|---|
static java.lang.String |
getDescriptor(java.lang.reflect.Method m)
Get the Descriptor of a
Method . |
static MethodSignature |
quickResolve(Instruction instruction,
ProgramClass clazz)
Lightweight utility method to resolve the target of an invocation instruction on demand,
without having to run a full scale analysis.
|
void |
visitAnyAttribute(Clazz clazz,
Attribute attribute)
Visits any Attribute instance.
|
void |
visitAnyClass(Clazz clazz)
Visits any Clazz instance.
|
void |
visitAnyInstruction(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
Instruction instruction)
Visits any Instruction instance.
|
void |
visitCodeAttribute(Clazz clazz,
Method method,
CodeAttribute codeAttribute) |
void |
visitConstantInstruction(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
ConstantInstruction constantInstruction) |
void |
visitProgramClass(ProgramClass programClass) |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
visitAnnotationDefaultAttribute, visitAnyAnnotationsAttribute, visitAnyParameterAnnotationsAttribute, visitAnyTypeAnnotationsAttribute, visitBootstrapMethodsAttribute, visitConstantValueAttribute, visitDeprecatedAttribute, visitDeprecatedAttribute, visitDeprecatedAttribute, visitDeprecatedAttribute, visitEnclosingMethodAttribute, visitExceptionsAttribute, visitInnerClassesAttribute, visitLineNumberTableAttribute, visitLocalVariableTableAttribute, visitLocalVariableTypeTableAttribute, visitMethodParametersAttribute, visitModuleAttribute, visitModuleMainClassAttribute, visitModulePackagesAttribute, visitNestHostAttribute, visitNestMembersAttribute, visitPermittedSubclassesAttribute, visitRecordAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleParameterAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleParameterAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitSignatureAttribute, visitSignatureAttribute, visitSignatureAttribute, visitSignatureAttribute, visitSignatureAttribute, visitSourceDebugExtensionAttribute, visitSourceDirAttribute, visitSourceFileAttribute, visitStackMapAttribute, visitStackMapTableAttribute, visitSyntheticAttribute, visitSyntheticAttribute, visitSyntheticAttribute, visitSyntheticAttribute, visitUnknownAttribute
visitLibraryClass
visitAnySwitchInstruction, visitBranchInstruction, visitLookUpSwitchInstruction, visitSimpleInstruction, visitTableSwitchInstruction, visitVariableInstruction
public CallResolver(ClassPool programClassPool, ClassPool libraryClassPool, CallGraph callGraph, boolean clearCallValuesAfterVisit, boolean useDominatorAnalysis, boolean evaluateAllCode, boolean includeSubClasses, int maxPartialEvaluations, java.util.function.Supplier<java.lang.Boolean> shouldAnalyzeNextCodeAttribute, boolean skipIncompleteCalls, ValueFactory arrayValueFactory, boolean ignoreExceptions, ExecutingInvocationUnit.Builder executingInvocationUnitBuilder, boolean selectiveParameterReconstruction, java.util.Set<MethodSignature> interestingMethods, java.util.Set<java.util.function.Predicate<Call>> interestingCallPredicates, CallVisitor... visitors)
programClassPool
- ClassPool
containing the classes whose calls should be
analyzed.libraryClassPool
- Auxiliary ClassPool
containing framework classes. Their calls
are not resolved, but the class structure information (i.e. contained methods) is needed
when resolving calls whose target lies in such a library class.callGraph
- The CallGraph
to fill with all discovered Call
s.clearCallValuesAfterVisit
- If true, Call.clearValues()
will be called after
CallVisitor.visitCall(Call)
. This makes it possible to analyze arguments and the
return value of calls while still adding them to a CallGraph
afterwards, as call
graph analysis itself usually only requires the call locations and their targets, not the
arguments or return value.useDominatorAnalysis
- If true, a dominator analysis is carried out using the DominatorCalculator
for each method, in order to be able to fill the Call.controlFlowDependent
flag.evaluateAllCode
- See PartialEvaluator.Builder#setEvaluateAllCode(boolean)
.includeSubClasses
- If true, virtual calls on class fields, parameters and return values
of other methods will take all possible subclasses into account. This is necessary for a
more complete call graph, because the runtime type of these objects is not controlled by
the current method. E.g. a method that declares its return type to be of type A might also
return an object of type B in case B extends A. The same is true for class fields and
parameters, so in order to really find all potential calls, this circumstance needs to be
modeled. For objects of declared type Object
this will be skipped, as the
fact that every single Java class is a subclass of object would lead to an immense blow-up
of the call graph.maxPartialEvaluations
- See PartialEvaluator.Builder#stopAnalysisAfterNEvaluations(int)
.shouldAnalyzeNextCodeAttribute
- If returns true, the next code attribute will be
analyzed. Otherwise, the code attribute will be skipped.skipIncompleteCalls
- If true, any discovered call that would return true for Call.hasIncompleteTarget()
will be discarded and not be forwarded to CallVisitor.visitCall(Call)
.visitors
- CallVisitor
s that are interested in the results of this analysis.public static MethodSignature quickResolve(Instruction instruction, ProgramClass clazz)
instruction
- The invocation instruction to analyze.clazz
- The ProgramClass
containing this instruction.MethodSignature
containing as much information about the invocation target as
we can confidently know without needing more in-depth analysis.public void visitAnyClass(Clazz clazz)
ClassVisitor
visitAnyClass
in interface ClassVisitor
public void visitProgramClass(ProgramClass programClass)
visitProgramClass
in interface ClassVisitor
public void visitAnyAttribute(Clazz clazz, Attribute attribute)
AttributeVisitor
visitAnyAttribute
in interface AttributeVisitor
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
visitCodeAttribute
in interface AttributeVisitor
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
InstructionVisitor
visitAnyInstruction
in interface InstructionVisitor
public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
visitConstantInstruction
in interface InstructionVisitor
public static java.lang.String getDescriptor(java.lang.reflect.Method m)
Method
.