codeviz安装使用说明

codeviz 简介

一个简单高效的函数调用路径图生成工具,有了它,可以大大节省程序路径分析时间,尤其是复杂大型的系统程序

安装步骤

1. GraphViz install

由于codeviz地使用依赖GraphViz中的dot ,所以需要先安装GraphViz
sudo apt-get install graphviz

2. 获取codeviz源码

很多源都失效了,还好下面这个还在
https://github.com/petersenna/codeviz

3. codeviz Installing

解压后,参考readme

cd codeviz
cp ./lib/* -rv /usr/lib/   (Or your preferred perl library path)
cp ./bin/* /usr/local/bin

4. 脚本

genfull —— 使用它生成项目的完整调用图。这将是相当大的,可能应该削减到gengraph大小。有许多collection方法可用,但默认方法是cdepn。运行genfull --man获取完整的man页面。不要费心自己把输出 full.graph 到 dot 中,因为它不太可能在合理的时间内绘制。
gengraph —— 这将为给定的一组函数生成一个小的子图和postscript文件。运行gengraph --man了解详细信息。

5. 为 genfull 生成 cdepn 文件

如果您感兴趣的源文件的full.graph已经创建,您可以跳过本节。查看./graphs目录来看是否有你需要的full.graph。
cobjdump和cppobjdump(分别适用于C和c++)将生成足够的调用图,但是缺少一些信息。例如,一个函数声明的源文件未知,宏和内联函数将完全丢失。理想情况下,应该使用cdepn方法,但是它需要gcc和g++的一个补丁版本才能工作。这些补丁和一些脚本可以在compilers/目录中找到。
gcc和g++的补丁版本为编译的每个c和c++文件输出.cdepn文件。这个.cdepn文件包含诸如函数何时被调用、函数在何处声明等信息。CodeViz的早期版本支持多个gcc版本,但是这个版本只支持gcc7.4.0.
首先,必须下载源tar。对于那些有比阅读gcc安装文档更好的事情要做的人,只需执行以下操作:

cd compilers
ncftpget ftp://ftp.gnu.org/pub/gnu/gcc/gcc-7.4.0/gcc-7.4.0.tar.gz
./install_gcc-7.4.0.sh <optional install path>

这个脚本将解压缩gcc,打补丁并将其安装到提供的路径。如果没有指定路径,则将安装到 $HOME/gcc-graph。我通常使用命令 ./install_gcc-7.4.0.sh /usr/local/gcc-graph
将它安装到/usr/local/gcc-graph

如果您真的想手工修补,只需阅读脚本中的每个步骤。不过有一个步骤需要注意。
现在,我们假定gcc和g++的补丁版本现在在$HOME/gcc-graph/中。大多数项目将使用变量CC来决定使用哪个版本的gcc。使用补丁程序最方便的方法是使用类似于
make CC=$HOME/gcc-graph/bin/gcc CXX=$HOME/gcc-graph/bin/g++。
或者,调整您的path,gcc-graph将出现在正常gcc之前。在编译每个源文件时,将创建相应的cdepn文件。
在构建Linux内核的情况下,命令将是

make CC=\$HOME/gcc-graph/bin/gcc bzImage
make CC=\$HOME/gcc-graph/bin/gcc modules

如果Makefile正确地使用CC或CXX宏来指示要使用的编译器,那么类似的方法也适用于其他项目。如果它是您自己类型的一个Makefile,或者它没有使用适当的宏,那么您可能必须自己编辑Makefile,或者调整你的path以将gcc-graph放在首位。例如,使用bash,可以执行操作
PATH=$HOME/gcc-graph/bin:$PATH。
构建时,观察编译器输出,以确保正在创建.cdepn文件。

6. 为 genfull 生成 nccout 文件

使用一个补丁版本的gcc的另一种方法是使用ncc(http://freshmeat.net/projects/ncc),这是专门为代码浏览设计的一个C编译器。它自带了自己的导航工具,非常值得一看。
CodeViz使用cncc collection方法支持ncc(就像cdepn用于gcc一样),并且只支持C。ncc collection方法的真正重要之处在于它可以遍历函数指针。如果你下载并安装了ncc,如果是C代码、并且函数指针很常见,则使用cncc collection方法。
一旦安装了ncc,在构建Linux内核的情况下,命令将是:

make -i CC='ncc -ncoo -ncfabs' bzImage
make -i CC='ncc -ncoo -ncfabs' modules
find . -name \\*.nccout | xargs cat > code.map.nccout

7. 生成 full.graph

下载部分的tar提供了一些full.graph文件。如果没有你想要的一个full.graph文件,请继续阅读。
为了创建一个full.graph,使用脚本genfull。运行genfull --help查看所有选项,但最简单的方法是在顶层源目录中不带参数运行这个脚本,编译之后,一个full.graph文件将在顶级源目录中创建。
虽然有可能放置full.graph到dot中并查看postscript文件,建议您不要尝试。完整的图非常大,不太可能在合理的时间内绘制。应该使用gengraph程序来创建更小的图。

8. 关于 full.graph 可能存在的问题

在更复杂的代码中,这个full.graph可能并不完美。例如,如果模块之间有重复的函数名,或者编译了多个二进制文件,那么genfull就不会对它们进行区分,这可能会导致命名冲突。如果你认为这是一个问题,你可以采取两个步骤:
首先,将cdepn生成的图与cobjdump生成的图进行比较。由于cobjdump正在分析一个二进制文件,所以这个图不太可能是错的,它只是没有关于内联函数或宏的信息。对于linux内核,这个测试应该是这样的:

genfull -g cobjdump -o full.graph-objdump
genfull -g cdepn -o full.graph-cdepn
gengraph -t -d 5 -g full.graph-objdump  -f kswapd -o kswapd-objdump.ps
gengraph -t -d 5 -g full.graph-cdepn -f kswapd -o kswapd-cdepn.ps

这将生成的两个full.graph和两个函数kswapd()调用图,可以进行比较,以确保cdepn图是准确的。类似的方法也可以用于其他项目。
可能出现的第二个问题是函数名在模块之间重复。在这种情况下,最好的做法是使用-s开关到genfull来限制检查树的哪些分支。例如,在linux内核中,mm/和drivers/char/drm中都有一个alloc_pages()函数。如果只检查VM,那么命名冲突将是一个问题,genfull可以被调用为:

 genfull -s "mm include/linux drivers/block arch/i386"。

这将涵盖大多数感兴趣的函数。在其他项目中,这将是不同库相互冲突的一种情况。例如,对于avifile,没有参数的genfull会造成可怕的混乱。因此,必须使用-s开关为项目的每个部分生成一个full.graph。例如,player将被绘制:每个库都是单独绘制的。

genfull -s "player" -o full.graph-player。

9. 生成调用图

脚本gengraph基于full.graph文件为一个指定的函数生成一个调用图。gengraph --man将提供您所需的所有信息。需要注意的最重要的选项是-g,它决定使用什么collection方法。脚本完成后,将提供一个postscript文件,可以使用任何postscript查看器查看该文件。默认情况下,输出文件名将会是 functionname.ps
如果生成一个图需要很长时间,通常最好使用-d先将深度限制在合理的范围内。我们以绘制内核2.4.20的alloc_pages()函数调用图为例。

  • gengraph -f alloc_pages
    结果:花了太长时间,按下ctrl-c键 结束,必须对深度有所限制,以便了解发生了什么。
  • gengraph -d 10 -f alloc_pages
    结果:输出图比较大,主要是内核库存函数无关紧要。使用-t选项省略通常不感兴趣的函数。对于其他项目,编辑gengraph脚本并转到“subgenerate_trimlist”行,这个函数有一个函数列表,使用-t选项来“修剪”
  • gengraph -t -d 10 -f alloc_pages
    结果:输出图仍然是巨大的,但是浏览一下这个图就会发现,调用“shrink_cache()”会在它下面生成一个巨大的图,看起来与页面分配没有直接关系。让我们只显示那个函数,而不是用-s选项遍历它
  • gengraph -t -d 10 -s “shrink_cache” -f alloc_pages
    结果:大大减小了图大小。剩下的图的大部分包含两个函数“try_to_free_pages_zone()”和“_free_pages_ok”。我们会
    不遍历try_to_free_pages_zone(),并将使用-i选项完全忽略_free_pages_ok()
  • gengraph -t -d 10 -s “shrink_cache try_to_free_pages_zone” -i “__free_pages_ok” -f alloc_pages
    结果:完美,显示了一个很好的图,它清楚地显示了与页面分配相关的重要函数。稍后,可以单独绘制这个图中没有遍历的分支。
    底线是,第一个图通常太大,需要削减。如何结合使用代码的经验和常识来缩减它。我发现,通常先将深度限制为4,然后开始忽略当前显然不感兴趣的函数,然后再遍历它们,这样做很有帮助。

10. 基于正则表达式生成图

支持基于正则表达式选择要绘图、显示和忽略的函数。表达式的格式与perl相同,只是没有//'s。例如,要生成一个在内核中看起来像alloc函数的图,这是可行的:
gengraph -t -d 4 --func-re “^.?.?alloc(_page)?$” -i “pmd_alloc” -o allocs.ps
注意,使用–func-re时,使用-o开关或dot将无法创建抱怨输出文件名错误的图,这一点非常重要。

11. 后期处理选项

genfull和gengraph都支持使用后期处理步骤。目前,支持两个。第一个是单个函数的堆栈使用情况。这是x86特有的,因为它依赖于对象文件,而不管使用什么collection方法。这主要有利于Linux内核,因为普通应用程序可以扩展它们的堆栈,并且不需要像以前那样担心堆栈的使用。第二个模块显示了函数对之间gengraph的累积使用情况。这对于显示系统调用和较低层函数之间的使用情况,以确定堆栈使用过多的位置非常方便。
有关使用后期处理选项的更多信息,请参阅genfull和gengraph的手册页。

12. 守护进程/客户支持

对于大型输入图,生成调用图的最长操作是读取输入文件。相比之下,要在authors机器上生成一个小图形,读取输入图形需要4秒,生成输出文件需要0.1秒。要解决这个问题,如果指定了-q(–daemon)开关,gengraph可以作为守护进程运行。如果你想知道它在做什么,就用-v。
gengraph -q -g /usr/src/linux-2.4.20-clean/full.graph
当它返回时,守护进程正在运行。要使用守护进程生成图形,请运行:
gengraph -q -t -d 2 -f alloc_pages
注意-q开关的使用,它表示gengraph应该作为客户机运行到守护进程实例。如果您感到无聊,请比较正常gengraph与作为客户机使用时的运行时间差异:-)。要停止守护进程,请执行以下操作:
echo QUIT > /tmp/codeviz.pipe
守护进程将关闭并清理。

参考原文:https://blog.csdn.net/qq_23599965/article/details/88851423#1__2

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值