生成调用图的好算法?

时间:2011-03-06 05:20:14

标签: java algorithm design-patterns call-graph

我正在编写一些代码来生成特定中间表示的调用图,而不通过静态扫描IR代码来执行它。 IR代码本身并不太复杂,我对函数调用序列的外观有很好的理解,所以我需要做的就是跟踪调用。我目前正在以明显的方式这样做:

  • 跟踪我们的位置
  • 如果遇到函数调用,请转到该位置,执行并返回
  • 虽然分支在调用者和被调用者之间设置了边缘

我对我所处的位置感到满意,但我想确保我不是在这里重新发明轮子并面对角落的情况。我想知道是否有任何可接受的良好算法(和/或设计模式)可以有效地执行此操作?

更新 IR代码是来自类似家庭的Java语言的字节码反汇编,看起来像Jasmine specification

2 个答案:

答案 0 :(得分:4)

从学术角度来看,这里有一些注意事项:

  • 你关心保守/正确吗?例如,假设您正在分析的代码包含通过函数指针调用。如果你只是生成文档,那么没有必要处理这个问题。如果您正在进行可能出错的代码优化,则需要假设“通过指针调用”意味着“可以是任何东西。”

  • 注意特殊的执行路径。您的IR可能会或可能不会从您那里抽象出来,但请记住,许多操作都会抛出语言级异常以及硬件中断。同样,这取决于您稍后要对调用图执行的操作。

  • 考虑如何处理周期(例如递归,相互递归)。这可能会影响您在以后编写遍历图表的代码的方式(即,它们需要某种“访问”设置以避免永远遍历循环)。

干杯。

3月6日更新

根据添加到原始帖子的额外信息:

  • 注意虚拟方法调用。请记住,一般来说,执行哪种方法是不可知的。您可能必须假设调用将转到特定类的任何子类。标准示例有点像这样:假设您有一个ArrayList<A>,并且您有class B extends A。基于随机数生成器,您将向列表中添加AB的实例。现在,您为列表中的所有x.foo()调用x,其中foo()A中的虚拟方法,并在B中覆盖。因此,通过查看源代码,无法知道循环是否在运行时调用A.fooB.foo或两者。

答案 1 :(得分:2)

我不知道算法,但pycallgraph做得不错。值得查看the source。它不长,应该有助于检查现有的设计模式。