[转] 使用CodeViz生成C/C++函数调用关系图
运行环境:虚拟机下的Ubuntu 11.04
结合Graphviz工具,使用CodeViz可以生成直观和漂亮的C/C++程序函数之间的调用关系图。
1、安装graphviz
在安装CodeViz之前,必须先安装它所依赖的工具dot,否则将无法完成./configure操作并提示以下错误信息:
checking for dot...not found
FATAL: The program dot was not in your path. This is probably available for your distribution
with the graphviz package. Install this before running configure again
既可以从http://www.graphviz.org/Download_linux_ubuntu.php 上下载最新版本的graphviz安装程序手动安装,也可以使用以下命令自动安装:
$ sudo apt-get install graphviz graphviz-dev graphviz-doc
程序简要说明:
graphviz - rich set of graph drawing tools
graphviz-dev - transitional package for graphviz-dev rename
graphviz-doc - additional documentation for graphviz
安装相关库:
$ sudo apt-get install libgv-*
相关库简要说明:
libgv-guile - Guile bindings for graphviz
libgv-lua - Lua bindings for graphviz
libgv-ocaml - OCaml bindings for graphviz
libgv-perl - Perl bindings for graphviz
libgv-php5 - Php5 bindings for graphviz
libgv-python - Python bindings for graphviz
libgv-ruby - Ruby bindings for graphviz
libgv-tcl - Tcl bindings for graphviz
2、安装CodeViz
从http://www.skynet.ie/~mel/projects/codeviz/ 上下载CodeViz安装包codeviz-1.0.10.tar.gz以及从ftp://ftp.gnu.org/pub/gnu/gcc/gcc-3.4.6 上下载GCC源码包gcc-3.4.6.tar.gz,并把它们拷贝到Ubuntu下的同一目录下。
然后解压CodeViz安装包,并把gcc-3.4.6.tar.gz拷贝到codeviz-1.0.10/compiler目录下:
$ tar zvxf codeviz-1.0.10.tar.gz
$ cd codeviz-1.0.10/
$ cp ../gcc-3.4.6.tar.gz compilers/ //也可以略过这一步,让ncftp(Ubuntu默认未安装)在make执行过程中自动下载gcc-3.4.6.tar.gz
$ ./configure
Patched GCC默认安装在/usr/local/gccgraph目录下。
安装GCC时,需要安装下面的库
apt-get install libgmp10-dev libmpfr-dev libmpc-dev
在执行make之前,先通过以下命令创建一个链接文件asm:
$ sudo ln -sf /usr/include/asm-generic/ /usr/include/asm
否则,在make执行过程中会出现在/usr/include/linux/errno.h文件中找不到asm/errno.h文件的错误信息并中止编译。
接下来执行make和make install命令即可在/usr/local/gccgraph目录下创建打过补丁的GCC编译器以及在/usr/local/bin目录下创建两个perl脚本程序genfull和gengraph。
$ make
$ sudo make install
3、CodeViz的使用举例
例子源代码如下:
/* test.c */ #include <stdio.h>
#include <stdlib.h>
#include <string.h> void func(char *p)
{
p = (char *)malloc(20);
} int main(void)
{
char *str = NULL; func(str); strcpy(str, "hello world"); printf("string is %s\n", str); return 0;
}
使用刚生成的编译器编译test.c,会相应地生成一个test.c.cdepn文件。
$ /usr/local/gccgraph/bin/gcc test.c
test.c.cdepn文件信息:
F {func} {test.c:6}
C {func} {test.c:7} {malloc}
F {main} {test.c:11}
C {main} {test.c:18} {printf}
C {main} {test.c:16} {strcpy}
C {main} {test.c:14} {func}
然后执行genfull脚本生成full.graph。
$ genfull
full.graph文件信息:
digraph fullgraph {
node [ fontname=Helvetica, fontsize=12 ];
"func" [label="func\ntest.c:5:"];
"main" [label="main\ntest.c:10:"];
"func" -> "malloc" [label="test.c:7"];
"main" -> "func" [label="test.c:14"];
"main" -> "strcpy" [label="test.c:16"];
"main" -> "printf" [label="test.c:18"];
}
最后执行gengraph生成函数关系调用图。
$ gengraph -f main --output-type "png"

-f指定最顶层的函数,--output-type指定图片的输出格式。
至于genfull和gengraph的详细使用说明请参考man手册,使用以下命令查看:
$ sudo apt-get install perl-doc //须先安装perl-doc
$ genfull --man
$ gengraph --man 另外参考:
http://blog.csdn.net/solstice/article/details/486788
CodeViz是《Understanding The Linux Virtual Memory Manager》(at Amazon,下载地址在页尾)的作者 Mel Gorman 写的一款分析C/C++源代码中函数调用关系的open source工具(类似的open source软件有 egypt、ncc)。其基本原理是给 GCC 打个补丁,让它在编译时每个源文件时 dump 出其中函数的 call graph,然后用 Perl 脚本收集并整理调用关系,转交给Graphviz绘制图形。
CodeViz 原本是作者用来分析 Linux virtual memory 的源码时写的一个小工具,现在已经基本支持 C++ 语言,最新的 1.0.9 版能在 Windows + Cygwin 下顺利地编译使用:)。需要注意的是:1) 下载 GCC 3.4.1 的源码 gcc-3.4.1.tar.gz 放到 codeviz-1.0.9/compilers,2) 安装 patch 程序(属于Utils类),3) 从 http://www.graphviz.org 下载并安装 Graphviz 2.6。
我用 CodeViz 分析《嵌入式实时操作系统 uC/OS-II (第二版)》中的第一个范例程序,步骤如下:
1. 想办法让 gcc 能编译uC/OS 2.52和范例程序的源码,每个C源文件生成对于的.c.cdepn文件。只要编译(参数 -c)就行,无需连接。
2. 调用genfull生成full.graph,这个文件记录了所有函数在源码中的位置和它们之间的调用关系。
3. 使用gengraph生成我关心的函数的调用关系。
首先分析main():
1. gengraph --output-type gif -f main
分析main()的call graph,得到的图如下,看不出要领:
2. gengraph --output-type gif -f main -s OSInit
暂时不关心OSInit()的内部实现细节(参数 -s),让它显示为一个节点。得到的图如下,有点乱,不过好多了:
3. gengraph --output-type gif -f main -s OSInit -i "OSCPUSaveSR;OSCPURestoreSR"
基本上每个函数都会有进入/退出临界区的代码,忽略之(参数 -i)。得到的图如下,基本清楚了:
4. gengraph --output-type gif -f main -s "OSInit;OSSemCreate" -i "OSCPUSaveSR;OSCPURestoreSR" -k
OSSemCreate()的内部细节似乎也不用关心,不过保留中间文件sub.graph(参数 -k),得到的图如下,
5. dot -Tgif -o main.gif sub.graph
修改sub.graph,使图形符合函数调用顺序,最后得到的图如下,有了这个都不用看代码了:)
接着分析OSTimeDly()的被调用关系:
gengraph --output-type gif -r -f OSTimeDly
看看哪些函数调用了OSTimeDly(),参数 -r ,Task()和TaskStart()都是用户编写的函数:

最后看看Task()直接调用了哪些函数:
gengraph --output-type gif -d 1 -f Task
只看从Task出发的第一层调用(参数 -d 1):

在分析源码的时候,把这些图形打印在手边,在上面做笔记,实在方便得很。
[转] 使用CodeViz生成C/C++函数调用关系图的更多相关文章
- 利用graphviz软件和pycallgraph库自动生成Python代码函数调用关系图
参考博文:https://blog.csdn.net/qq_36408085/article/details/82952846 https://blog.csdn.net/fondax/article ...
- 看开源代码利器—用Graphviz + CodeViz生成C/C++函数调用图(call graph)
一.Graphviz + CodeViz简单介绍 CodeViz是<Understanding The Linux Virtual Memory Manager>的作者 Mel Gorma ...
- 用callgraph生成的函数调用关系图
Wu Zhangjin 创作于 2015/04/05 评论打赏 By Falcon of TinyLab.org 2015/04/03 1 故事缘由 源码分析是程序员离不开的话题.无论是研究开源项目, ...
- 用callgraph生成的两张函数调用关系图
参考这里,感觉很Cool吧. Linux-0.11函数调用关系图: QEMU函数调用关系图:
- 分析函数调用关系图(call graph)的几种方法
绘制函数调用关系图对理解大型程序大有帮助.我想大家都有过一边读源码(并在头脑中维护一个调用栈),一边在纸上画函数调用关系,然后整理成图的经历.如果运气好一点,借助调试器的单步跟踪功能和call sta ...
- 用CodeViz绘制函数调用关系图(call graph)
CodeViz是<Understanding The Linux Virtual Memory Manager>(at Amazon,下载地址在页尾)的作者 Mel Gorman 写的一款 ...
- c语言分析函数调用关系图(call graph)的几种方法
一.基于 Doxygen或 lxr 的API形式的文档系统. 二.基于CodeViz, CodeViz是<Understanding The Linux Virtual Memory Manag ...
- python函数调用关系图(python call graph)
由于要重构项目的部分代码,要整理好主要的函数调用关系,不想自己看代码慢慢画出结构,想找出一种通用的,节省人力的方法得出函数间的调用关系图,于是发现以下几个工具.(内网没装好graphviz,还没真正用 ...
- 使用egypt+graphviz生成函数调用关系图示例
总结: make (-fdump-rtl-expand) 去除编译优化,比如-O3 egypt test.c.128r.expand >test.dot 可以手动打开dot文件去除一些孤立 ...
随机推荐
- FC8下备份linux系统
linux系统可以使用tar来备份.<br><br> 我在FC8上装好了totem, mplayer, audacious, 并搞定了wifi后,我觉得该备份一下FC8系统.& ...
- yii2 日志(log)的配置与使用
原文地址: http://blog.csdn.net/gao_yu_long/article/details/51732181
- instancetype 与 id for Objective-C
instancetype.id.NSObject的区别 - simalone 1.instancetype只能用于方法的返回类型,而id用处和NSObject *类似. 2.instancetyp ...
- 正则表达式:根据逗号解析CSV并忽略引号内的逗号
需求:解析CSV文件并忽略引号内的逗号 解决方案: public static void main(String[] args) { String s = "a,b,c,\"1,0 ...
- Maven实战二
简述: 现需要 在Eclipse中配置Maven插件 安装maven应用,配置Maven环境变量 建立Maven管理的工程 用Maven导入Gson包, 编写简易Json输出程序 步骤: 1. 首先到 ...
- mysql数据库操作语句大全
一 . 常用mysql命令行命令 1 .启动MYSQL服务 net start mysql 停止MYSQL服务 net stop mysql 2 . netstat –na | findstr 3 ...
- Ehcache中配置详解
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLoc ...
- bzoj3339 bzoj3585
两题本质是一样,只不过3585要离散化这种不修改,不强制的问题,显然先考虑离线算法这道题的思路和bzoj1878非常像考虑到如果只是求每个前缀的mex,我们是很容易扫一遍就得出来的我们设为这个位置的m ...
- Linux Shell编程(5)——shell特殊字符(下)
{}代码块[花括号]. 这个结构也是一组命令代码块,事实上,它是匿名的函数.然而与一个函数所不同的,在代码块里的变量仍然能被脚本后面的代码访问. bash$ { local a; a=123 ...
- 树(最小乘积生成树,克鲁斯卡尔算法):BOI timeismoney
The NetLine company wants to offer broadband internet to N towns. For this, it suffices to construct ...