# gcc -rdynamic -g test.c -o test
#include <execinfo.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> void dump(int signo) { void *array[30]; size_t size; char **strings; size_t i; size = backtrace (array, 30); strings = backtrace_symbols (array, size); fprintf (stderr,"Obtained %zd stack frames.nm", size); for (i = 0; i <= size; i++) fprintf (stderr,"%s\n", strings[i]); free (strings); exit(0); } Debug_Printf_FrameInfos() { signal(SIGSEGV, dump); } void func_c() { * ((volatile char *) 0x0) = 0x999; } void func_b() { func_c(); } void func_a() { func_b(); } int main() { Debug_Printf_FrameInfos(); func_a(); return 0; }
# ./test Obtained 7 stack frames.nm./a.out [0x80484e3] [0xb7f70420] ./a.out [0x804859d] ./a.out [0x80485a7] ./a.out [0x80485c4] /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0) [0xb7e1e450] ./a.out [0x8048461] Segmentation fault |
如果编译似加了-rdynamic选项 的话,将打印如下信息
# ./test Obtained 7 stack frames.nm./test(dump+0x1f) [0x80487c3] [0xb7fbb420] ./test(func_b+0x8) [0x804887d] ./test(func_a+0x8) [0x8048887] ./test(main+0x1b) [0x80488a4] /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0) [0xb7e69450] ./test [0x8048741] |
打印信息比没加-rdynamic的程序多出了一个函数名称+偏移地址..(func_b+0×8)
objdump -d ./test > tmp.txt
在tmp.txt 中查找0×80485ad的地址,你会发现如下信息:
08048595 :
8048595: 55 push %ebp
8048596: 89 e5 mov %esp,%ebp
8048598: e8 eb ff ff ff call 8048588
804859d: 5d pop %ebp
804859e: c3
其中 804859d 是调用( call 8048588 )c函数后的地址,虽然并没有直接定位到C函数,
通过汇编代码,基本可以推出是在C函数出现问题了。(pop指令不会导致段错误的)