I'm trying to implement an analysis (extends DefaultOneStepAnalysis) to construct call graph in CHA algorithms. There are three parts of my code:
1) method "doAnalyze" to return the "BasicReport"
2) method "analyze" to find call edges for each method in the given project
3) class "AnalysisContext" to store the context and methods using in the analysis.
In 3), I use method "callBySignature" to find out cbsMethods of a method same as in "CHACallGraphExtractor" but it doesn't return expected result. While I use the original OPAL's way to get cbsMethods in Extractor, the result is a set of methods.
Could you please help me to confirm where the problem is and how to solve it? Thank you very much.
Regards, Jiang
----Main Part of my code-------------------------------------------------
object CHACGAnalysis extends DefaultOneStepAnalysis {
... ...
override def doAnalyze(
project: Project[URL],
parameters: Seq[String] = List.empty,
isInterrupted: () ⇒ Boolean
): BasicReport = {
... ...
for {
classFile <- project.allProjectClassFiles
method <- classFile.methods
} {
analyze(project, methodToCellCompleter, classFile, method))
}
... ...
}
def analyze(
project: Project[URL],
methodToCellCompleter: Map[(String,Method), CellCompleter[K, Set[Method]]],
classFile: ClassFile,
method: Method
): Unit = {
… …
val context = new AnalysisContext(project, classFile, method)
method.body.get.foreach((pc, instruction) ⇒
instruction.opcode match {
... ...
case INVOKEINTERFACE.opcode ⇒
val INVOKEINTERFACE(declaringClass, name, descriptor) = instruction
context.addCallEdge_VirtualCall(pc, declaringClass, name, descriptor, true,cell1)
... ...
}
… …
}
protected[this] class AnalysisContext(
val project: SomeProject,
val classFile: ClassFile,
val method: Method
) {
val classHierarchy = project.classHierarchy
val cbsIndex = project.get(CallBySignatureResolutionKey)
val statistics = project.get(IntStatisticsKey)
val instantiableClasses = project.get(InstantiableClassesKey)
val cache = new CallGraphCache[MethodSignature, scala.collection.Set[Method]](project)
private[AnalysisContext] def callBySignature(
declaringClassType: ObjectType,
name: String,
descriptor: MethodDescriptor
): Set[Method] = {
val cbsMethods = cbsIndex.findMethods(
name,
descriptor,
declaringClassType
)
cbsMethods
}
def addCallEdge_VirtualCall(
pc: PC,
declaringClassType: ObjectType,
name: String,
descriptor: MethodDescriptor,
isInterfaceInvocation: Boolean = false,
cell1: CellCompleter[K, Set[Method]]
): Unit = {
val cbsCalls =
if (isInterfaceInvocation) {
callBySignature(declaringClassType, name, descriptor)
}
else
Set.empty[Method]
… …
}
… …
}
Finally, I have found the problem is due to "AnalysisMode" After I resetting AnalysisMode into "CPA“ the question is solved.
I think I should always keep in mind what "AnalysisMode" should be used before I design the algorithm.
Thank you for your concern Jiang