zoukankan      html  css  js  c++  java
  • [转] 使用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
    ", 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
    test.c:5:"];
    "main" [label="main
    test.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软件有 egyptncc)。其基本原理是给 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):

    在分析源码的时候,把这些图形打印在手边,在上面做笔记,实在方便得很。

  • 相关阅读:
    前后端分离
    git的基本使用
    PHP中的接口
    Java里面的接口
    面向对象的接口
    python调用Shell脚本:os.system(cmd)或os.popen(cmd)()【转】
    得到系统删除程序里的FIREFOX
    NSMutableArray,NSArray (From DFdou's Blog)
    iPhone delegate 两界面传递数据(转)
    字符串乘积运算+连接
  • 原文地址:https://www.cnblogs.com/qiangxia/p/4378355.html
Copyright © 2011-2022 走看看