设为首页 加入收藏

TOP

GCC 函数调用探测功能(一)
2015-02-02 14:23:17 来源: 作者: 【 】 浏览:12
Tags:GCC 函数 调用 探测 功能

----------------------------------------
gcc 函数调用探测功能
gcc -finstrument-functions 使用,
man gcc 是很好的帮助。
----------------------------------------


收集一个函数调用的踪迹,一种方法是通过在函数的入口处和出口处插入一个打印语句来检测。这个过程非常繁琐,而且很容易出错,通常需要对源代码进行大量的修改。
幸运的是,GNU 编译器工具链(也称为 gcc)提供了一种自动检测应用程序中的各个函数的方法。
gcc 加上该选项 -finstrument-functions
在检测函数入口,会调用: void __cyg_profile_func_enter( void *func_address, void *call_site )
在检测函数出口,会调用:void __cyg_profile_func_exit ( void *func_address, void *call_site )
__cyg 开头,是Cygnus 的贡献.
在执行应用程序时,就可以收集调用者地址和被调用着地址,如果加上 -g 选项,增加调试信息,则用addr2line -f 可以找到地址对应的函数名称。
看看汇编会使你更清楚。


代码不需要修改,仅通过修改编译选项,使其具有了函数调用探测功能。
为灵活期间,少量修改代码,加入对感兴趣的调用探测,这无疑是很好的想法。


下面给出自己整理的一个例子.
------------------------------------------------------------
debug 代码
------------------------------------------------------------
[/pts/1@linuxidc ~/test]$ cat instrument.h
#ifndef INSTRUMENT_H
#define INSTRUMENT_H
void enable_instrument( void ) __attribute__ ((no_instrument_function));
void disable_instrument( void ) __attribute__ ((no_instrument_function));
void main_destructor( void ) __attribute__ ((no_instrument_function, destructor));
void __cyg_profile_func_enter( void *, void *) __attribute__ ((no_instrument_function));
void __cyg_profile_func_exit( void *, void *) __attribute__ ((no_instrument_function));
#endif?
[/pts/1@linuxidc ~/test]$ cat instrument.c
#include
#include "instrument.h"


#define INSTRUMENT_FILE_PATH "instrument.log"


static FILE *instrument_fd = NULL;
static int _flag = 0;


#define open_instrument_file()? \
? ? (instrument_fd = fopen(INSTRUMENT_FILE_PATH, "w"))


#define close_instrument_file()? \
? ? do{? \
? ? if (NULL != instrument_fd)? \
? ? {? \
? ? fclose(instrument_fd);? \
? ? instrument_fd = NULL; \
? ? }? \
? ? }while(0)?


//首次打印会打开文件
#define instrument_print(args, fmt...) \
? ? do{? \
? ? if (0 == _flag) \
? ? {? \
? ? break;? \
? ? }? \
? ? if (NULL == instrument_fd && NULL == open_instrument_file())? \
? ? {\
? ? printf("Err: Can not open output file.\n");? \
? ? break;? \
? ? }\
? ? fprintf(instrument_fd, args, ##fmt);? \
? ? ? ? fflush(instrument_fd);? \
? ? }while(0);


//enable, disable 配对使用,在关注的函数上添加
void enable_instrument( void )
{
? ? _flag = 1;
}
void disable_instrument( void )
{
? ? _flag = 0;
}
// 一般是用不到该函数了
void main_destructor( void )
{
? ? close_instrument_file();
}
void __cyg_profile_func_enter( void *func_addr, void *call_site )
{
? ? instrument_print("Enter\n%p\n%p\n", call_site, func_addr);
}
void __cyg_profile_func_exit( void *func_addr, void *call_site )
{
? ? instrument_print("Exit\n%p\n%p\n", call_site, func_addr);
}


------------------------------------------------------------
测试代码
------------------------------------------------------------
[/pts/1@linuxidc ~/test]$ cat test.c
#include
#include "instrument.h"


int addmul(int i, int j);
int mul(int i, int j);
int main(int argc, char *argv[])
{
? ? enable_instrument();
? ? int i=addmul(3,5);
? ? printf("result is %d\n",i);
? ? disable_instrument();
? ? return 0;
}



int addmul(int i, int j)
{
? ? int k1,k2;
? ? k1=i+j;
? ? k2=mul(i,j);
? ? return k1+k2;
}


int mul(int i, int j)
{
? ? return i * j;
}


------------------------------------------------------------
Makefile
------------------------------------------------------------
[/pts/1@linuxidc ~/test]$ cat Makefile
CFLAGS=-finstrument-functions
all:
? ? gcc -c -g -finstrument-functions -o? test.o test.c
? ? gcc -c -g -finstrument-functions? -o? in

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Linux C时间函数 time_t struct tm 下一篇看开源代码利器—用Graphviz + Co..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: