利用graphviz以及gcc finstrument-functions特性打印进程的动态运行的函数调用关系图

来源:互联网 发布:淘宝店铺广告图 编辑:程序博客网 时间:2024/05/22 04:47

利用graphviz以及gcc finstrument-functions特性打印进程的动态运行的函数调用关系图

简介: 花一些时间遍历一下源代码,可以向您展现所有的函数调用过程;但是如果函数指针非常复杂,或者代码太长且晦涩难懂,
 那么这个过程就可能更加困难了。本文将向您介绍如何使用开源软件和一些定制的代码来构建一个动态的图形函数调用生成器。
注意:本文严重参考了此文:
 http://www.ibm.com/developerworks/cn/linux/l-graphvis/


// 实现准备
1) 准备dot绘图工具. ubuntu通过如下命令获取:sudo apt-get install graphviz
2) 准备pvtrace工具 和 instrument.c(gcc finstrument-functions特性用到的函数的实现)
   可从ibm的网站下载:http://www.ibm.com/developerworks/cn/linux/l-graphvis/
   下载后可编译生成pvtrace.
   注意:
   原始的pvtrace代码不支持c++filt, 对代码稍加修改即可:
   ./symbols.c:74:  sprintf( line, "addr2line -e %s -f -s 0x%x", imageName, address );
   替换为:
 75   // awk脚本去掉函数的()以及参数, 仅保留函数名, 比如把 fun(int a) 替换为 fun, 否则生成的graph.dot无法绘图
 76   sprintf( line, "addr2line -e %s -f -s 0x%x | c++filt | awk -F'(' '{print $1}'", imageName, address );

3) 准备addr2line c++filt两个小工具.
   addr2line把一个符号地址转换为源文件以及行号+函数名.
   c++filt把c++改编后的函数名还原为人类易读的函数名. 比如: c++filt _Z5fun_1v => fun_1()
3) 准备一个测试代码test.c
   编译命令放在了Makefile

Makefile如下:
all:intrument.o
 g++ -g -finstrument-functions test.cpp instrument.o -o test
 ./test
 pvtrace test
 dot -Tjpg graph.dot -o graph.jpg
 ls

intrument.o:
 gcc -g -finstrument-functions -c instrument.c -o instrument.o

test.cpp源码如下:
nemo@ubuntu:[pvtrace_test]$ cat test.cpp
#include <stdio.h>

#define MAX_NUM 10000000
int g_count = 10;
void fun_1()
{
    int i=0;
    int g=0;
    for(; i<MAX_NUM; ++i)
    {
        g += i*i;
    }
}

void fun_2()
{
    int i=0;
    int g=0;
    for(; i<MAX_NUM*4; ++i)
    {
        g += i*i;
    }
}

void fun_3()
{
    if (g_count < 0)
    {
        return;
    }

    g_count--;

    fun_1();
    fun_2();
    fun_3();
}
void (*fun)() ;
int main()
{
    printf("hello world\n");

 void (*fun)() ;
 fun = fun_3;
    fun();

    return 0;
}


    
// 第一步检查一下原始的材料, 4个文件 一个test.cpp, 一个instrument.c,
nemo@ubuntu:[pvtrace_test]$ ls
instrument.c  Makefile  pvtrace  test.cpp

nemo@ubuntu:[pvtrace_test]$ make all
g++ -g -finstrument-functions test.cpp instrument.c -o test
nemo@ubuntu:[pvtrace_test]$ ls
instrument.c  Makefile  pvtrace  test  test.cpp

// 执行完后多了trace.txt
nemo@ubuntu:[pvtrace_test]$ ./test
hello world
nemo@ubuntu:[pvtrace_test]$ ls
instrument.c  Makefile  pvtrace  test  test.cpp  trace.txt

// 执行pvtrace生成.dot文件
nemo@ubuntu:[pvtrace_test]$ pvtrace test
nemo@ubuntu:[pvtrace_test]$ ls
graph.dot  instrument.c  Makefile  pvtrace  test  test.cpp  trace.txt

// 利用dot命令生成jpg图
nemo@ubuntu:[pvtrace_test]$ dot -Tjpg graph.dot -o graph.jpg
nemo@ubuntu:[pvtrace_test]$ ls
graph.dot  graph.jpg  instrument.c  Makefile  pvtrace  test  test.cpp  trace.txt

参考:
 1)用 Graphviz 可视化函数调用
 http://www.ibm.com/developerworks/cn/linux/l-graphvis/
 2)linux源代码分析和阅读工具比较
 http://my.oschina.net/alphajay/blog/70050
 3)利用Graphviz 画结构图
 http://www.cnblogs.com/sld666666/archive/2010/06/25/1765510.html


附1: 上面测试程序运行后的函数调用图:

附2:本文的原始实验材料下载:
http://pan.baidu.com/share/link?shareid=172196&uk=3959729623

原创粉丝点击