from: http://blog.sina.com.cn/s/blog_502c8cc4010115m5.html
最近在看一个开源代码bind过程中,该代码是由纯C语言编写的,函数间调用关系特别的复杂。想对整体代码有一个大概的了解,这样就需要了解代码中主要的相关函数间调用关系,发现一个开源的小工具calltree,在linux下能够将代码中函数调用关系生成调用树,并可以选择生成dot语言文件,通过dot工具生成调用关系图。下面介绍一下calltree工具:
calltree基本命令:calltree
-gb -np –m *.c
calltree所有的命令可以通过 calltree
–help查看,如下图:
[root@localhost i686-linux-cc]# ./calltree -help
Usage:
Options:
a vertial Bar at each tab stop.
the structure of the tree.
(cumulative) tree.
file names past procedure names.
structure for main only.
C Preprocessor (default).
use C Preprocessor.
all functions not called via 'main'.
all functions not called.
all external functions.
output for xvcg.
output for graphviz.
verbose.
this help.
version number.
list functions found in 'file'.
only functions found in 'file'.
call graph only for function 'name'.
the maximum printed nesting depth to #.
indentation to #.
ignorefile=, listfile= and depth= may be abbreviated by first letter.
list= may be abbreviated by lf=.
注:该地方不明白为什么使用l表示listfil,而lf用于作为list的缩写。
下面我们主要介绍几个常用的选项:
-b 就是那个竖线了,很直观地显示缩进层次。
-g 打印内部函数的所属文件名及行号,外部函数所属文件名和行号也是可打印的,详man
-np 不要调用c预处理器,这样打印出的界面不会很杂乱,但也可能会产生错误哦,如果我们只看函数的调用关系的话,不会有大问题。
-m 告诉程序从main开始。
下面我们结合bind来说一下另外几个可能会用到的选项:
depth=#选项:当我们使用calltree
-gb -np –m *.c,然后会发现函数特别多,就只在named目录下所有的.c文件,一共就几百个函数相互调用,这样我们阅读起来会非常的费劲,而我们只想了解main函数主要调用了哪几个相关的函数时,我们就需要用到depth选项。
例如:
./calltree -gb -np -m bind9/bin/named/*.[c.h] depth=2 > codecalltree.txt
> codecalltree.txt 主要是因为函数调用关系较多,直接显示在终端上将无法查看,所以需要将内容导出到文本文件。
我们使用depth这个选项后,那么函数调用只显示两层调用关系,这样会对代码整体有个大概了解,阅读起来相对容易一些。
|
|
|
[named/main.c:528]
|
|
|
|
[named/builtin.c:305]
|
bin/named/log.c:231]
|
[named/server.c:3639]
|
|
|
|
那当我们通过depth选项后对程序main函数有一个整体把握后,想对其中main函数调用的某一个特定函数进行更细的分析,那么我们就用到了list=name选项。
list=name选项:例如我们通过查看上面的main函数调用关系图后,先更细的看看isc_app_run函数内部的调用关系,那么我们就会
isc_app_run [lib/isc/unix/app.c:430]:
|
|
|
|
|
|
|
|
|
|
|
[lib/isc/unix/socket.c:3827]
|
[lib/isc/unix/socket.c:3816]
|
[lib/isc/task.c:1251]
|
[lib/isc/task.c:1244]
|
lib/isc/timer.c:923]
|
[lib/isc/timer.c:915]
|
[lib/isc/unix/time.c:305]
|
|
|
|
|
[lib/isc/unix/strerror.c:47]
|
|
|
|
dot选项:最后再介绍一个-dot选项,该选项可以将函数调用关系二维图形化。
例如:
./calltree -gb -np –m ./bind9/bin/named/*.c -dot > named_calltree.dot
生成的dot文件后,使用graphviz工具将dot文件转成图片并保存。
http://www.graphviz.org/pub/graphviz/stable/windows/graphviz-2.28.0.msi
不足之处:
1、获取的函数没有带上函数参数,不能将函数参数体现出来
2、函数数量太多时,使用dot选项后并画图,得出的图形太大,一般的图形工具无法展现,所以该功能变成无效。
参考:http://www.linuxsir.org/bbs/thread246389.html