静态分析C语言生成函数调用关系的利器——cflow
除了《静态分析C语言生成函数调用关系的利器——calltree》一文中介绍的calltree,我们还可以借助cflow辅助我们阅读理解代码。(转载请指明出于breaksoftware的csdn博客)
cflow的说明和安装
cflow是一款静态分析C语言代码的工具,通过它可以生成函数的调用关系。和calltree不一样,cflow有独立的网页介绍它(https://www.gnu.org/software/cflow/#TOCdocumentation)。而且在Ubuntu系统上,我们可以不用去编译cflow的源码,而直接使用下面命令获取
apt-get install cflow
cflow的使用
安装完毕,我们可以使用下面指令看到cflow的参数说明
cflow --help
我们可以得到如下提示
Usage: cflow [OPTION...] [FILE]...
generate a program flowgraph
General options:
-d, --depth=NUMBER Set the depth at which the flowgraph is cut off
-f, --format=NAME Use given output format NAME. Valid names are
`gnu' (default) and `posix'
-i, --include=CLASSES Include specified classes of symbols (see below).
Prepend CLASSES with ^ or - to exclude them from
the output
-o, --output=FILE Set output file name (default -, meaning stdout)
-r, --reverse * Print reverse call tree
-x, --xref Produce cross-reference listing only
Symbols classes for --include argument
_ symbols whose names begin with an underscore
s static symbols
t typedefs (for cross-references only)
x all data symbols, both external and static
Parser control:
-a, --ansi * Accept only sources in ANSI C
-D, --define=NAME[=DEFN] Predefine NAME as a macro
-I, --include-dir=DIR Add the directory DIR to the list of directories
to be searched for header files.
-m, --main=NAME Assume main function to be called NAME
-p, --pushdown=NUMBER Set initial token stack size to NUMBER
--preprocess[=COMMAND], --cpp[=COMMAND]
* Run the specified preprocessor command
-s, --symbol=SYMBOL:[=]TYPE Register SYMBOL with given TYPE, or define an
alias (if := is used). Valid types are: keyword
(or kw), modifier, qualifier, identifier, type,
wrapper. Any unambiguous abbreviation of the above
is also accepted
-S, --use-indentation * Rely on indentation
-U, --undefine=NAME Cancel any previous definition of NAME
Output control:
-b, --brief * Brief output
--emacs * Additionally format output for use with GNU
Emacs
-l, --print-level * Print nesting level along with the call tree
--level-indent=ELEMENT Control graph appearance
-n, --number * Print line numbers
--omit-arguments * Do not print argument lists in function
declarations
--omit-symbol-names * Do not print symbol names in declaration strings
-T, --tree * Draw ASCII art tree
Informational options:
--debug[=NUMBER] Set debugging level
-v, --verbose * Verbose error diagnostics
-?, --help give this help list
--usage give a short usage message
-V, --version print program version
Mandatory or optional arguments to long options are also mandatory or optional
for any corresponding short options.
* The effect of each option marked with an asterisk is reversed if the option's
long name is prefixed with `no-'. For example, --no-cpp cancels --cpp.
Report bugs to <bug-cflow@gnu.org>.
我只列出我觉得有意思的几个参数:
-T输出函数调用树状图
-m指定需要分析的函数名
-n输出函数所在行号
-r输出调用的反向关系图
--cpp预处理,这个还是很重要的
文本输出
最简单的使用方法是以ASCII文本的方式输出结果,比如
cflow -T -m main -n timer.c
其结果是一个包含文件名和函数所在代码行号的调用关系图
+-main() <int main (void) at timer.c:13>
+-ev_timer_init()
+-timeout_cb() <void timeout_cb (EV_P_ ev_timer *w, int revents) at timer.c:7>
| +-puts()
| -ev_break()
+-ev_timer_start()
-ev_run()
然而,对于有一定代码量的项目,我们不会使用ASCII文本的方式去查看函数调用关系,因为调用是相当复杂的,而文本图并不适合人去理解。于是我们希望能cflow能产出一个可供其他软件转换成图片的格式的文件。可惜cflow并不支持,好在网上有开发者做了一个工具,可将其结果转换成dot格式。
转成dot文件
我们可以使用下面方法获取转换工具
wget -c https://github.com/tinyclub/linux-0.11-lab/raw/master/tools/tree2dotx
下载完tree2dotx后,可对其做个软链便于使用
cd /usr/bin
ln -s 【Your Path】/tree2dotx tree2dotx
具体的转换方法是
cflow -T -m main -n timer.c > main.txt
cat main.txt | tree2dotx > main.dot
dot文件生成图片
我们需要借助graphviz(没有安装的可以使用apt-get install graphviz先安装)生成图片,指令是
dot -Tgif main.dot -o main.gif
- 2761: [JLOI2011]不重复数字(哈希表)
- 1297: [SCOI2009]迷路
- Javascript DOM操作实例
- 2431: [HAOI2009]逆序对数列
- JavaScript实例---表格隔行变色以及移入鼠标高亮
- 1022: [SHOI2008]小约翰的游戏John
- Javascript数组
- 1588: [HNOI2002]营业额统计
- [git]撤销的相关命令:reset、revert、checkout
- Thrift教程初级篇——thrift安装环境变量配置第一个实例
- 1083: [SCOI2005]繁忙的都市
- 1015: [JSOI2008]星球大战starwar
- Tyvj P1813 [JSOI2008]海战训练
- 1820: [JSOI2010]Express Service 快递服务
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【每周一库】 see - An HTTP server for hosting static files
- 【Rust日报】2020-07-17 无船同志新博客:Shipping Const Generics in 2020
- SpringCloud--Config Server配置中心学习总结
- 【Rust日报】2020-07-18 提升ARM64 Linux平台支持到Tier-1
- SpringCloud+MyBatis(oracle)逆向工程自动生成代码
- JDK1.8的几个简单Lambda表达式
- 腾讯云直播开发日记 (一) 直播播放和观看
- Docker六脉神剑(二) 使用Docker构建lnmp开发环境
- redis主从配置+集群搭建
- 【Ceph RGW】找一个用Go写的s3cmd
- 技术分享 | 如何优雅地在 Windows 上从 MySQL 5.6 升级到 5.7
- SpringCloud分布式配置中心
- Sharding-Proxy的基本功能使用
- React-Redux 对Todolist修改
- 快排解决寻找数组中的第K个最大元素