Function Trace
函数跟踪
__cyg_profile_func_enter
和 __cyg_profile_func_exit
是用于函数调用追踪的特殊函数。当你使用 -finstrument-functions编译选项时,编译器会在每个函数的开始和结束处插入这两个函数. 这样,你可以实现函数调用的检测和分析。
这里是一个简单的例子,首先我们有一个用于跟踪函数的 func_trace.c
文件:
#include <stdio.h>
static FILE *fp_trace;
void __attribute__((constructor)) traceBegin(void) {
fp_trace = fopen("func_trace.out", "w");
}
void __attribute__((destructor)) traceEnd(void) {
if (fp_trace != NULL) {
fclose(fp_trace);
}
}
void __cyg_profile_func_enter(void *func, void *caller) {
if (fp_trace != NULL) {
fprintf(fp_trace, "entry %p %p\n", func, caller);
}
}
void __cyg_profile_func_exit(void *func, void *caller) {
if (fp_trace != NULL) {
fprintf(fp_trace, "exit %p %p\n", func, caller);
}
}
然后,我们编写一个简单的测试代码 main.c
:
#include <stdio.h>
int foo(void) {
return 2;
}
int bar(void) {
zoo();
return 1;
}
void zoo(void) {
foo();
}
int main(int argc, char **argv) {
bar();
}
接下来,将 main.c
与 func_trace.o
一起编译,并加上 -finstrument-functions
选项:
gcc main.c func_trace.o -finstrument-functions
运行 ./a.out
,就会产生 func_trace.out
文件,其中记录了函数调用的信息。你可以使用 addr2line
命令来查看函数名:
addr2line -f -e ./a.out $ADDRESS
这样,你就可以得到函数调用关系。如果想进一步处理这些跟踪数据,可以使用工具如 graphviz
来创建可视化的调用关系图。