我正在编写一些代码来生成特定中间表示的调用图,而不通过静态扫描IR代码来执行它。 IR代码本身并不太复杂,我对函数调用序列的外观有很好的理解,所以我需要做的就是跟踪调用。我目前正在以明显的方式这样做:
我对我所处的位置感到满意,但我想确保我不是在这里重新发明轮子并面对角落的情况。我想知道是否有任何可接受的良好算法(和/或设计模式)可以有效地执行此操作?
更新 IR代码是来自类似家庭的Java语言的字节码反汇编,看起来像Jasmine specification。
答案 0 :(得分:4)
从学术角度来看,这里有一些注意事项:
你关心保守/正确吗?例如,假设您正在分析的代码包含通过函数指针调用。如果你只是生成文档,那么没有必要处理这个问题。如果您正在进行可能出错的代码优化,则需要假设“通过指针调用”意味着“可以是任何东西。”
注意特殊的执行路径。您的IR可能会或可能不会从您那里抽象出来,但请记住,许多操作都会抛出语言级异常以及硬件中断。同样,这取决于您稍后要对调用图执行的操作。
考虑如何处理周期(例如递归,相互递归)。这可能会影响您在以后编写遍历图表的代码的方式(即,它们需要某种“访问”设置以避免永远遍历循环)。
干杯。
3月6日更新:
根据添加到原始帖子的额外信息:
ArrayList<A>
,并且您有class B extends A
。基于随机数生成器,您将向列表中添加A
和B
的实例。现在,您为列表中的所有x.foo()
调用x
,其中foo()
是A
中的虚拟方法,并在B
中覆盖。因此,通过查看源代码,无法知道循环是否在运行时调用A.foo
,B.foo
或两者。答案 1 :(得分:2)
我不知道算法,但pycallgraph做得不错。值得查看the source。它不长,应该有助于检查现有的设计模式。