用 Graphviz 可视化函数调用

GNU 的入口和出口配置函数

这里,我们是在函数入口和出口将函数的地址记录下来,这里是记录到了文件中,该文件在什么时候打开呢?
gcc 的开发者也考虑过这个问题,它们为 main 函数的 constructor 函数和 destructor 函数提供了一些碰巧能够满足这个要求一些方法。
constructor
函数是在调用 main 函数之前调用的,而 destructor 函数则是在应用程序退出时调用的。
要创建 constructor 和 destructor 函数,则需要声明两个函数,然后对这两个函数应用 constructordestructor 函数属性。
constructor 函数中,会打开一个新的跟踪文件,分析数据的地址跟踪就是写入这个文件的;在 destructor 函数中,会关闭这个跟踪文件

这两个特殊函数的声明如下:

 
  1. /* Constructor and Destructor Prototypes */
  2. void main_constructor( void )
  3.     __attribute__ ((no_instrument_function, constructor));
  4. void main_destructor( void )
  5.     __attribute__ ((no_instrument_function, destructor));

在pvtrace中,定义如下:

 
  1. /* Output trace file pointer */
  2. static FILE *fp;
  3. void main_constructor( void )
  4. {
  5.   fp = fopen( "trace.txt""w" );
  6.   if (fp == NULL) exit(-1);
  7. }
  8. void main_deconstructor( void )
  9. {
  10.   fclose( fp );
  11. }

好了,将上面四个函数(都包含在pvtrace代码包中的instrument.c文件中)和要分析的源代码一起编译就行了;
运行编译后的程序就会在当前目录下生成 trace.txt 文件,文件内容类似于:
===== trace.txt =====
E0x8048538
E0x80484f4
E0x80484a8
X0x80484a8
X0x80484f4
X0x8048538
=====================

然后,使用pvtrace命令来分析该trace.txt, 分析的过程中涉及: 栈、符号两个概念,相关的文件为 stack.c symbols.c, 都比较简单,其中。
将地址转换为函数名使用的是GNU的 addr2line 命令; 整个分析过程的结果生成一个 dot文件,里面只使用到了几个简单的dot文件的语法。

最后,使用Graphviz 的dot命令将dot文件转换为图形。

参考: http://www.ibm.com/developerworks/cn/linux/l-graphvis/

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据