CodeViz是《Understanding The Linux Virtual Memory Manager》的作者?Mel Gorman?写的一款分析C/C++源代码中函数调用关系的open source工具(类似的open source软件有?egypt、ncc)。其基本原理是给 GCC 打个补丁(如果你的gcc版本不符合它的要求还得先下载正确的gcc版本),让它在编译每个源文件时 dump 出其中函数的 call graph,然后用 Perl 脚本收集并整理调用关系,转交给Graphviz绘制图形(Graphviz属于后端,CodeViz属于前端)。
CodeViz 原本是作者用来分析 Linux virtual memory 的源码时写的一个小工具,现在已经基本支持 C++ 语言,最新的 1.0.9 版能在 Windows + Cygwin 下顺利地编译使用。
二、Graphviz + CodeViz编译安装
下载CodeVize源码包:http://www.csn.ul.ie/~mel/projects/codeviz/
解压:tar xvf codeviz-1.0.12.tar.gz (目前最新版是1.0.12)
进入解压后的目录:cd codeviz-1.0.12/
CodeViz 使用了一个 patch 版本的 GCC 编译器,而且不同的 CodeViz 版本使用的GCC 版本也不同,可以下载 CodeViz 的源码包后查看 Makefile 文件来确定要使用的 GCC 版
本,codeviz-1.0.12 使用 GCC-4.6.2。实际上安装 CodeViz 时安装脚本make会检查当前的GCC版本如果不符合则会自动下载对应的 GCC并打 patch,但由于GCC较大如果网速不好且在虚拟机中的话容易下载失败或系统错误什么的,因此这里我们还是分步安装比较好,先安装gcc再回来安装 CodeViz。
?
(1)安装 GCC
下载gcc-4.6.2.tar.gz到 cd codeviz-1.0.12目录下的compilers里。
下载地址:ftp://ftp.gnu.org/pub/gnu/gcc/gcc-4.6.2/gcc-4.6.2.tar.gz
CodeViz 的安装脚本 compilers/install_gcc-4.6.2.sh 会自动检测 compilers 目录下是否有 gcc 的源码包,若没有则自动下载并打 patch。这里前面已经下载,直接移到该目录即可,则剩下的就是解压安装了。install_gcc-3.4.6.sh 会解压缩 gcc打 patch,并将其安装到指定目录,若是没有指定目录,则缺省使用$HOME/gcc-graph,通常指定安装在/usr/
local/gcc-graph(这时需要 root 权限)。
安装: ./install_gcc-4.6.2.sh
注意:这里可能安装时有些错误,具体错误及解决方案见后面。
(2)安装 CodeViz
./configure && make install-codeviz
注1:不需要 make ,因为make的作用就是检测是否有gcc若没有则下载源码包,所以这里只要安装 codeviz 即可。具体查看 Makefile 文件。
注意:这里为什么不是通常用的make install,因为这里make install的作用是先安装gcc再安装codeviz,而前面已经安装了 gcc,所以这里只需要安装 codeviz ,即make install-codeviz脚本,该脚本也就是将genfull 和 gengraph 复制到/usr/local/bin 目录下。
目前为止,CodeViz 安装完成了。
GraphViz 支持生成不同风格的调用图,但是一些需要安装额外的支持工具或者库程序,有兴趣的朋友可以到官网上查找相关资料。这里重点讲述 CodeViz 的使用方法,具体的图像风格控制不再详述。
CodeViz 使用两个脚本来生成调用图,一个是 genfull,该脚本可以生成项目的完整调用图,因此调用图可能很大很复杂,缺省使用 cdepn 文件来创建调用图;另一个是gengraph,该脚本可以对给定一组函数生成一个小的调用图,还可以生成对应的postscript 文件。安装时这两个脚本被复制到/usr/local/bin 目录下,所以可以直接使用而不需要指定路径。其基本步骤如下:
下面以编译一个简单的test.c文件为例进行说明:
1. 使用刚刚安装的gcc-4.6.2来编译当前目录下所有.c文件,gcc/g++为编译的每个 C/C++文件生成.cdepn 文件。只要编译(参数?-c)就行,无需链接。
即为:$ ~/gcc-graph/bin/gcc test.c
2.调用genful会在当前目录生成一个full.graph文件,该脚本可以生成项目的完整调用图信息文件,记录了所有函数在源码中的位置和它们之间的调用关系。 因此调用图信息文件可能很大很复杂,,缺省使用 cdepn 文件来创建调用图信息文件。
即为:$ genfull
?
3. 使用gengraph可以对给定一组函数生成一个小的调用图,显示函数调用关系。
即为:$ gengraph
自己编写个简单的程序,看下效果再说~~~
?
?
?
按照上面的三个步骤依次进行如下图所示:

当然大家使用CodeViz都不是用来玩的,而是用于真正的项目中,四中简单的使用根本不够,下面来点稍微高深点的。
首先使用刚刚安装的gcc编译我们的.c文件(PS:这里一定要指定刚刚安装gcc的 地方,否则用的是系统gcc而非我们安装的gcc),然后genfull创建full.graph文件,可以使用genfull --help或者genfull --man来查看如何使用。最简单的方式是在项目的顶级目录以无参数方式运行。由于项目的完全调用信息非常庞大,所以通常只是简单的生成项目的 full.graph,然后在后面使用genfull获取需要的调用信息。若是需要完整信息则将full.graph由dot处理然后查看来生成的 postscript文件。(dot是GraphViz中的一个工具,具体使用没有深究过,感兴趣的读者可以自行查阅~~~)。到test.c所在目录运 行genfull看到生成了full.graph文件,大家可以用cat查看下。接下来使用gengraph生成函数调用图,可以使用gengraph --help或gengraph --man来查看如何使用。对于我而言,目前只关注下面几个选项就够了,即:
-f:指定顶级函数,即入口函数,如main等(当然不限定是main了);
-o:指定输出的postfile文件名,不指定的话就是函数名了,如上面的main;
--output-type:指定输出类型,例如png、gif、html和ps,缺省是ps,如上面的main.ps;
-d:指定最大调用层数;
-s:仅仅显示指定的函数,而不对其调用进行展开;
-i:忽略指定的函数
-t:忽略Linux特有的内核函数集;
-k:保留由-s忽略的内部细节形成的中间文件,为sub.graph
gengraph --output-type "png" -f main
在一个复杂的项目中,full.graph并不十分完美。例如,kernel中的模块 有许多同名函数,这时genfull不能??分它们,有两种方法可以解决,其中第一种方法太复杂易错不推荐使用,这里就介绍下第二种方法,即使用 genfull的-s选项,-s指定了检测哪些子目录。例如