Linux C语言函数调用栈打印
2023-12-15 15:37:44
代码
//main.c
extern void func_a();
int main (int argc, char *argv[])
{
func_a();
return 0;
}
//a.c
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
void print_trace (void){
void *array[10];
size_t size;
char **strings;
size_t i;
size = backtrace(array, 10);
strings = backtrace_symbols(array, size);
if (NULL == strings){
perror("backtrace_synbols failed:");
}
else{
printf ("Obtained %zd stack frames.\n", size);
for (i = 0; i < size; i++)
printf ("%s\n", strings[i]);
free (strings);
strings = NULL;
}
}
extern void func_b();
void func_a(){
func_b();
}
//b.c
extern void print_trace (void);
void func_c(){
print_trace();
}
void func_b(){
func_c();
}
编译
gcc -c a.c -fpic
gcc -c b.c -fpic
gcc -shared a.o -o liba.so
gcc -shared b.o -o libb.so
gcc main.c -L ./ -la -lb -o test
Makefile
CFLAGS:= -fpic -Os
all: test
# export LD_LIBRARY_PATH=/data1/liuxiaolian5/work/backtraceTest:$LD_LIBRARY_PATH
test: main.c liba.so libb.so
gcc -L ./ -la -lb -o test main.c
liba.so: a.o
gcc -shared -o liba.so a.o
libb.so: b.o
gcc -shared -o libb.so b.o
a.o: a.c
gcc $(CFLAGS) -c a.c
b.o: b.c
gcc $(CFLAGS) -c b.c
clean: FORCE
rm -rf *.o
rm -rf *.so
rm -rf test
FORCE:
运行
export LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
./test
结果
./test
Obtained 8 stack frames.
/data1/liuxiaolian5/work/backtraceTest/liba.so(print_trace+0x19) [0x7fc23225317e]
/data1/liuxiaolian5/work/backtraceTest/libb.so(func_c+0x9) [0x7fc23224e11e]
/data1/liuxiaolian5/work/backtraceTest/libb.so(func_b+0xe) [0x7fc23224e12f]
/data1/liuxiaolian5/work/backtraceTest/liba.so(func_a+0xe) [0x7fc232253225]
./test() [0x40113b]
/usr/lib64/libc.so.6(+0x2d210) [0x7fc232069210]
/usr/lib64/libc.so.6(__libc_start_main+0x7c) [0x7fc2320692bc]
./test() [0x401065]
问题
strip 动态库或者可执行文件不会丢失函数名称,但是加入 -O优化选项之后丢失backtrace
$ ./test
Obtained 5 stack frames.
# 0: /data1/liuxiaolian5/work/backtraceTest/liba.so(print_trace+0x1a) [0x7fe17dee017f]
# 1: ./test() [0x40113b]
# 2: /usr/lib64/libc.so.6(+0x2d210) [0x7fe17dcf6210]
# 3: /usr/lib64/libc.so.6(__libc_start_main+0x7c) [0x7fe17dcf62bc]
# 4: ./test() [0x401065]
注意事项
- backtrace的实现依赖于栈指针(fp寄存器),在gcc编译过程中任何非零的优化等级(-On参数)或加入了栈指针优化参数-fomit-frame-pointer后多将不能正确得到程序栈信息;
- backtrace_symbols的实现需要符号名称的支持,在gcc编译过程中需要加入-rdynamic参数;
内联函数没有栈帧,它在编译过程中被展开在调用的位置; - 尾调用优化(Tail-call Optimization)将复用当前函数栈,而不再生成新的函数栈,这将导致栈信息不能正确被获取。
文章来源:https://blog.csdn.net/qq_46136275/article/details/134885680
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!