为什么不直接使用objdump
在您编译的代码上然后解析生成的程序集来构建您的图?
测试1.c文件:
extern void test2();
void test1()
{
test2();
}
测试2.c文件:
extern void test1();
void test2()
{
test1();
}
int main()
{
test2();
}
现在构建它:
gcc -g test1.c test2.c -o myprog
现在拆解
objdump -d myprog > myprog.asm
使用几个简单的正则表达式查找所有函数调用,同时记住您所在的上下文。反汇编示例向您展示了它应该是多么容易:
00401630 <_test1>:
401630: 55 push %ebp
401631: 89 e5 mov %esp,%ebp
401633: 83 ec 08 sub $0x8,%esp
401636: e8 05 00 00 00 call 401640 <_test2>
40163b: c9 leave
40163c: c3 ret
40163d: 90 nop
40163e: 90 nop
40163f: 90 nop
00401640 <_test2>:
401640: 55 push %ebp
401641: 89 e5 mov %esp,%ebp
401643: 83 ec 08 sub $0x8,%esp
401646: e8 e5 ff ff ff call 401630 <_test1>
40164b: c9 leave
40164c: c3 ret
然后使用 python 来后处理你的反汇编并构建一个 function=>calls 的字典:
import re
import collections
calldict = collections.defaultdict(set)
callre = re.compile(".*\scall\s+.*<(.*)>")
funcre = re.compile("[0-9a-f]+\s<(.*)>:")
current_function = ""
with open("myprog.asm") as f:
for l in f:
m = funcre.match(l)
if m:
current_function = m.group(1)
else:
m = callre.search(l)
if m:
called = m.group(1)
calldict[current_function].add(called)
我没有编写完整的图搜索,但您可以使用简单的代码检测“乒乓”递归,例如:
for function,called_set in calldict.items():
for called in called_set:
callset = calldict.get(called)
if callset and function in callset:
print(function,called)
这给了我:
_test2 _test1
_test1 _test2
这种符号/asm分析技术也用于呼叫捕捉器 http://www.skynet.ie/~caolan/Packages/callcatcher.html检测未使用的 C 函数(这里也可以通过检查不在任何集合中的键以及对编译器符号进行一些过滤来轻松完成)