绘制函数调用图(call graph)(2):cflow + graphviz

您所在的位置:网站首页 运动会的画该怎么画 绘制函数调用图(call graph)(2):cflow + graphviz

绘制函数调用图(call graph)(2):cflow + graphviz

2024-07-09 18:35| 来源: 网络整理| 查看: 265

专栏导读

本专栏第一篇文章「专栏开篇」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解。

前言

cflow是一款静态分析C语言代码的工具,通过它可以生成函数调用关系。

官网:https://www.gnu.org/software/cflow/下载:http://ftp.gnu.org/gnu/cflow/手册:https://www.gnu.org/software/cflow/manual/index.html

如果你英文可以,上面的手册就是很好的使用教程,本文只是简单的介绍下如何使用cflow,旨在让新手快速入门cflow而已。

安装cflow

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

# sudo apt-get install cflow # # cflow --version cflow (GNU cflow) 1.4 Copyright (C) 2005, 2006, 2009, 2010, 2011 2009 Sergey Poznyakoff License GPLv3+: GNU GPL version 3 or later . This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Sergey Poznyakoff.

通过以下命令查看使用说明:

# cflow --help

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

# sudo apt-get install gawk 使用cflow分析函数调用关系

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

/* whoami.c - a simple implementation of whoami utility */ #include #include #include #include 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() : fprintf() who_am_i() : getpwuid() geteuid() getenv() fprintf() printf()

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

# cflow -m who_am_i whoami.c who_am_i() : getpwuid() geteuid() getenv() fprintf() printf()

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

cflow工具:输出文本格式的函数调用关系;tree2dotx脚本:将文本格式转化为dot格式;graphviz工具:将dot格式转化为图片格式; 从文本文件转为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 从dot文件转为图片文件

安装graphviz:

# sudo apt-get install graphviz

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

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

最终生成的图像如下所示:

这里写图片描述

可以看出,连系统函数printf都显示出来了,这往往不是我们所关心的,有没有什么办法可以忽略这些系统函数呢?我还没找到方法,有知道的诚盼您的留言指教。

其他补充 问: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 查看帮助,我没找到有这方面的选项。 总结

做个简单的总结:

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


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3