使用 cflow 绘制函数的调用图

1. 简介

cflow是一款静态分析C语言代码的工具,通过它可以生成函数调用关系。
该工具能够生成两种图:直接图和反向图。直接图以main函数(main)开始,递归地显示它调用的所有函数。相反,反向图是一组子图,以相反的顺序为每个函数的调用者绘制图表。由于它们的树状外观,图也可以称为树。
除了这两种输出模式之外,cflow还能够生成输入文件中遇到的所有符号的一个交叉引用列表。
该工具还提供了对输出中出现的符号的详细控制,允许省略用户不感兴趣的符号。输出图的确切外观也是可配置的。
官网:https://www.gnu.org/software/cflow/
下载:http://ftp.gnu.org/gnu/cflow/
手册:https://www.gnu.org/software/cflow/manual/index.html
如果你英文可以,上面的手册就是很好的使用教程,本文只是简单的介绍下如何使用cflow,旨在让新手快速入门cflow而已。

2. 安装cflow

在linux下安装cflow很简单,如下是我在Ubuntu下的安装命令:

# sudo apt-get install cflow
# cflow --version
cflow (GNU cflow) 1.4

由于cflow依赖gawk,你的环境有可能是mawk,所以还得安装下gawk:

# sudo apt-get install gawk

3. 使用cflow分析函数调用关系,生成文本文件

举个简单的例子,以下是源文件whoami.c内容(源码来自官网手册):

/* whoami.c - a simple implementation of whoami utility */
#include <pwd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

int who_am_i(void)
{
    struct passwd *pw;
    char *user = NULL;

    pw = getpwuid (geteuid ());
    if (pw)
        user = pw->pw_name;
    else if ((user = getenv ("USER")) == NULL)
    {
        fprintf (stderr, "I don't know!\n");
        return 1;
    }
    printf ("%s\n", user);
    return 0;
}

int main(int argc, char **argv)
{
    if (argc > 1)
    {
        fprintf (stderr, "usage: whoami\n");
        return 1;
    }
    return who_am_i ();
}

运行cflow将生成以下输出:

# cflow whoami.c 
main() <int main (int argc, char **argv) at whoami.c:24>:
    fprintf()
    who_am_i() <int who_am_i (void) at whoami.c:7>:
        getpwuid()
        geteuid()
        getenv()
        fprintf()
        printf()

尖括号中显示函数签名及其定义的位置。通常cflow打印完整的函数签名,可使用--omit-symbol-names选项省略函数名,使用--omit-arguments省略参数列表。如果你同时使用了这两种--omit-选项,上面的签名将会变成:

main() <int () at whoami.c:24>:

cflow默认是分析main函数,可以通过-m--main选项分析其他函数:

# cflow -m who_am_i whoami.c 
who_am_i() <int who_am_i (void) at whoami.c:7>:
    getpwuid()
    geteuid()
    getenv()
    fprintf()
    printf()

要为程序中的所有顶级函数生成调用图,请使用--all-A选项,这些图将放在main图的后面(如果存在的话),并按函数名字典顺序排列。当--all使用两次时,将显示所有全局函数的图(无论是否为顶级函数)。
要禁用对main函数的特殊处理,请使用--no-main选项。

cflow只能以ASCII文本的形式输出函数调用关系,不能输出图片格式,对于大型项目的代码来说,庞杂的文本输出简直“惨不忍睹,无法直视”。需要其他工具的辅助,才能将本文格式转化为可读性更强的图片格式,大致步骤如下:

  1. cflow工具:输出文本格式的函数调用关系;
  2. tree2dotx脚本:将文本格式转化为dot格式;
  3. graphviz工具:将dot格式转化为图片格式;

4. 从文本文件转为dot文件

将cflow输出的文本文件转化为dot格式的工具有tree2dotx,是否有其他工具,有待研究。通过以下命令下载tree2dotx脚本:

# wget -c https://github.com/tinyclub/linux-0.11-lab/raw/master/tools/tree2dotx -O /usr/bin/tree2dotx
# chmod +x /usr/bin/tree2dotx

将cflow输出的文本文件转化为dot格式:

# cflow whoami.c | tree2dotx > out.dot

5. 从dot文件转为图片文件

安装graphviz

# sudo apt-get install graphviz

将dot格式转化为图片格式:

# dot -Tgif out.dot -o out.gif

最终生成的图像如下所示:
在这里插入图片描述

6. 一些问题

  • cflow能同时分析一个源文件中多个函数的call graph吗?
    答:cflow默认只分析main函数的call graph,如果main不存在,将分析该文件的所有函数。可以通过 -m 选项分析指定的函数,如果指定的函数不存在,也会分析该文件的所有函数。可以利用这个特点,通过 -m 指定一个空的函数名,让cflow分析所有函数的call graph,如:
    # cflow -m= file1.c
    
  • cflow可以同时分析多个源文件吗?
    答:可以,使用如下两种命令都可以:
    # cflow -m= file1.c file2.c
    # cflow -m= *.c
    
    需要注意的是,如果多个源文件出现同名函数,cflow会警告,并且只分析其中一个main函数。
  • cflow可以分析整个目录(包括子目录)的源文件吗?
    答: 通过 cflow –help 查看帮助,我没找到有这方面的选项。

7. 总结

  1. 使用cflow工具,分析源码,得到文本格式的函数调用关系;
  2. 使用tree2dotx脚本,将文本格式转化为dot格式;
  3. 使用graphviz工具,可视化函数调用,将dot格式转化为图片格式;

作者:许振坪
来源:CSDN
原文:https://blog.csdn.net/benkaoya/article/details/79751000
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值