Basic implementation CallTreeBuilder.

This commit is contained in:
Achim D. Brucker 2016-09-11 12:51:59 +01:00
parent 021574e2e2
commit 2ebdf9514c
1 changed files with 45 additions and 12 deletions

View File

@ -12,29 +12,62 @@ package eu.aniketos.dasca.crosslanguage.cg;
import com.ibm.wala.ipa.callgraph.CGNode
import eu.aniketos.dasca.crosslanguage.builder.MergedCallGraph
import scala.collection.JavaConversions._
import com.ibm.wala.classLoader.CallSiteReference
object CallTreeBuilder {
def buildCallForest(cg: MergedCallGraph, sources: List[CGNode], sinks: List[CGNode]): List[CallTree] = {
return sources.map { src => buildCallTree(cg, src, sinks) }.filter { x => null != x }
buildCallForest(cg, 0, sources, sinks)
}
def buildCallForest(cg: MergedCallGraph, bound: Integer, sources: List[CGNode], sinks: List[CGNode]): List[CallTree] = {
return sources.map { src => buildCallTree(cg, bound, src, sinks) }.filterNot { x => null == x }
}
def buildCallTree(cg: MergedCallGraph, root: CGNode, sinks: List[CGNode]): CallTree = {
build(cg, List[CGNode](), sinks, root)
buildCallTree(cg, 0, root, sinks)
}
private def build(cg: MergedCallGraph, visited: List[CGNode], sinks: List[CGNode], root: CGNode): CallTree = {
if (sinks.contains(root)) {
return new CallTree(root)
} else {
val targetNodes = cg.getAllPossibleTargetNodes(root).filterNot { n => visited.contains(n) }
if (targetNodes.isEmpty) {
return null
def buildCallTree(cg: MergedCallGraph, bound: Integer, root: CGNode, sinks: List[CGNode]): CallTree = {
build(cg, List[CGNode](), sinks, bound, 0, root)
}
private def build(cg: MergedCallGraph, visited: List[CGNode], sinks: List[CGNode], bound: Integer,
depth: Integer, root: CGNode): CallTree = {
if (bound > 0 && bound < depth) {
if (null == sinks) {
return new CallTree(root)
} else {
return null
}
}
// Base case
val it = root.iterateCallSites()
var m = null: CallSiteReference
var children = List[CGNode]()
while (it.hasNext()) {
m = it.next()
children = children.union(sinks.filter { x => x.getMethod.getName().equals(m.getDeclaredTarget().getName()) })
}
if (!children.isEmpty) {
return new CallTree(root, children.map { x => new CallTree(x) })
}
// Recursive case
val targetNodes = cg.getAllPossibleTargetNodes(root).filterNot { n => visited.contains(n) }
if (targetNodes.isEmpty) {
return null
} else {
val children = targetNodes.toList.map { x => build(cg, root :: (visited ++ targetNodes), sinks, bound, depth + 1, x) }
.filterNot { x => (null == x) }
if (children.isEmpty || null == children) {
return null
//return new CallTree(root, children)
} else {
val children = targetNodes.toList.map { x => build(cg, visited ++ targetNodes, sinks, x) }
.filterNot { x => (null == x) }
return new CallTree(root, children)
}
}
}
}