From 2ebdf9514ce40dfb3a839f20874cb64ac5c51771 Mon Sep 17 00:00:00 2001 From: "Achim D. Brucker" Date: Sun, 11 Sep 2016 12:51:59 +0100 Subject: [PATCH] Basic implementation CallTreeBuilder. --- .../crosslanguage/cg/CallTreeBuilder.scala | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/src/eu.aniketos.dasca.crosslanguage/src/main/scala/eu/aniketos/dasca/crosslanguage/cg/CallTreeBuilder.scala b/src/eu.aniketos.dasca.crosslanguage/src/main/scala/eu/aniketos/dasca/crosslanguage/cg/CallTreeBuilder.scala index cd78b3b..574318c 100644 --- a/src/eu.aniketos.dasca.crosslanguage/src/main/scala/eu/aniketos/dasca/crosslanguage/cg/CallTreeBuilder.scala +++ b/src/eu.aniketos.dasca.crosslanguage/src/main/scala/eu/aniketos/dasca/crosslanguage/cg/CallTreeBuilder.scala @@ -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) } - } } }