C代码阅读工具---calltrer
2011-12-16 20:36
246 查看
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: calltree [calltree_options] [cpp_options] file1..filen
Options:
-b Print
a vertial Bar at each tab stop.
-r Invert
the structure of the tree.
-f Flattened
(cumulative) tree.
-g Print
file names past procedure names.
-m Call
structure for main only.
-p Use
C Preprocessor (default).
-np Don't
use C Preprocessor.
-u List
all functions not called via 'main'.
-e List
all functions not called.
-x List
all external functions.
-xvcg Format
output for xvcg.
-dot Format
output for graphviz.
-v Be
verbose.
-help Print
this help.
-version Print
version number.
igorefile=file Don't
list functions found in 'file'.
listfile=file List
only functions found in 'file'.
list=name Produce
call graph only for function 'name'.
depth=# Set
the maximum printed nesting depth to #.
s=# Set
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这个选项后,那么函数调用只显示两层调用关系,这样会对代码整体有个大概了解,阅读起来相对容易一些。
main [named/main.c:808]:
| UNEXPECTED_ERROR
| cleanup [named/main.c:699]
| | destroy_managers
[named/main.c:528]
| | dlz_drivers_clear
| | dns_name_destroy
| | isc_log_write
| | ns_builtin_deinit
[named/builtin.c:305]
| | ns_log_shutdown
bin/named/log.c:231]
| | ns_server_destroy
[named/server.c:3639]
| dns_result_register
| dst_result_register
| isc_app_finish
| isc_app_run
那当我们通过depth选项后对程序main函数有一个整体把握后,想对其中main函数调用的某一个特定函数进行更细的分析,那么我们就用到了list=name选项。
list=name选项:例如我们通过查看上面的main函数调用关系图后,先更细的看看isc_app_run函数内部的调用关系,那么我们就会
isc_app_run [lib/isc/unix/app.c:430]:
| ISC_LIST_HEAD
| ISC_LIST_NEXT
| ISC_LIST_UNLINK
| LOCK [lib/isc/mem.c:41]
| REQUIRE
| UNEXPECTED_ERROR
| UNLOCK [lib/isc/mem.c:43]
| | ISC_LINK
| evloop [lib/isc/unix/app.c:300]
| | TIME_NOW
| | isc__socketmgr_dispatch
[lib/isc/unix/socket.c:3827]
| | isc__socketmgr_getfdsets
[lib/isc/unix/socket.c:3816]
| | isc__taskmgr_dispatch
[lib/isc/task.c:1251]
| | isc__taskmgr_ready
[lib/isc/task.c:1244]
| | isc__timermgr_dispatch
lib/isc/timer.c:923]
| | isc__timermgr_nextevent
[lib/isc/timer.c:915]
| | isc_time_microdiff
[lib/isc/unix/time.c:305]
| | select
| exit
| handle_signal [lib/isc/unix/app.c:102]
| | UNEXPECTED_ERROR
| | isc__strerror
[lib/isc/unix/strerror.c:47]
| | isc_msgcat_get
| | memset
| | sigaction
| | sigfillset
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选项后并画图,得出的图形太大,一般的图形工具无法展现,所以该功能变成无效。
3、希望实现数据结构之间的包含关系。
参考:http://www.linuxsir.org/bbs/thread246389.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: calltree [calltree_options] [cpp_options] file1..filen
Options:
-b Print
a vertial Bar at each tab stop.
-r Invert
the structure of the tree.
-f Flattened
(cumulative) tree.
-g Print
file names past procedure names.
-m Call
structure for main only.
-p Use
C Preprocessor (default).
-np Don't
use C Preprocessor.
-u List
all functions not called via 'main'.
-e List
all functions not called.
-x List
all external functions.
-xvcg Format
output for xvcg.
-dot Format
output for graphviz.
-v Be
verbose.
-help Print
this help.
-version Print
version number.
igorefile=file Don't
list functions found in 'file'.
listfile=file List
only functions found in 'file'.
list=name Produce
call graph only for function 'name'.
depth=# Set
the maximum printed nesting depth to #.
s=# Set
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这个选项后,那么函数调用只显示两层调用关系,这样会对代码整体有个大概了解,阅读起来相对容易一些。
main [named/main.c:808]:
| UNEXPECTED_ERROR
| cleanup [named/main.c:699]
| | destroy_managers
[named/main.c:528]
| | dlz_drivers_clear
| | dns_name_destroy
| | isc_log_write
| | ns_builtin_deinit
[named/builtin.c:305]
| | ns_log_shutdown
bin/named/log.c:231]
| | ns_server_destroy
[named/server.c:3639]
| dns_result_register
| dst_result_register
| isc_app_finish
| isc_app_run
那当我们通过depth选项后对程序main函数有一个整体把握后,想对其中main函数调用的某一个特定函数进行更细的分析,那么我们就用到了list=name选项。
list=name选项:例如我们通过查看上面的main函数调用关系图后,先更细的看看isc_app_run函数内部的调用关系,那么我们就会
isc_app_run [lib/isc/unix/app.c:430]:
| ISC_LIST_HEAD
| ISC_LIST_NEXT
| ISC_LIST_UNLINK
| LOCK [lib/isc/mem.c:41]
| REQUIRE
| UNEXPECTED_ERROR
| UNLOCK [lib/isc/mem.c:43]
| | ISC_LINK
| evloop [lib/isc/unix/app.c:300]
| | TIME_NOW
| | isc__socketmgr_dispatch
[lib/isc/unix/socket.c:3827]
| | isc__socketmgr_getfdsets
[lib/isc/unix/socket.c:3816]
| | isc__taskmgr_dispatch
[lib/isc/task.c:1251]
| | isc__taskmgr_ready
[lib/isc/task.c:1244]
| | isc__timermgr_dispatch
lib/isc/timer.c:923]
| | isc__timermgr_nextevent
[lib/isc/timer.c:915]
| | isc_time_microdiff
[lib/isc/unix/time.c:305]
| | select
| exit
| handle_signal [lib/isc/unix/app.c:102]
| | UNEXPECTED_ERROR
| | isc__strerror
[lib/isc/unix/strerror.c:47]
| | isc_msgcat_get
| | memset
| | sigaction
| | sigfillset
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选项后并画图,得出的图形太大,一般的图形工具无法展现,所以该功能变成无效。
3、希望实现数据结构之间的包含关系。
参考:http://www.linuxsir.org/bbs/thread246389.html
相关文章推荐
- 【转载】C代码阅读工具(1)---calltrer
- 【Linux开发技术之工具使用】配置VIM下编程和代码阅读环境
- MAC将Vim配置为类Sourceinsight代码阅读工具
- 代码阅读工具使用入门
- 【代码阅读的方法与实践】第10章 代码阅读工具
- kscope --- Linux下代码阅读工具
- 效率工具:代码阅读软件 Scientific Toolworks Understand
- 代码阅读分析工具Understand 2.0试用
- 代码阅读工具
- 阅读代码分析工具Understand 2.0试用
- 代码阅读工具:Source Navigator和Source Insight
- 代码阅读工具
- 代码阅读工具强大的代码阅读工具Understand
- Linux下的代码阅读和查找工具
- 阅读linux内核代码的工具-- Source Insight
- 阅读代码工具
- vim下方便代码阅读的工具ctags
- 代码阅读工具:OpenGrok
- (转)【Linux开发技术之工具使用】配置VIM下编程和代码阅读环境
- 阅读linux内核代码的工具-- Source Insight