我想像backtracegdb一样获得类似输出。但是我想ptrace()直接通过这样做。我的平台是Linux,x86;以及后来的x86_64。
backtrace
ptrace()
现在,我只想从堆栈中读取返回地址,而无需转换为符号名称。
因此,对于测试程序,-O0通过gcc-4.5以下方式进行编译:
-O0
gcc-4.5
int g() { kill(getpid(),SIGALRM); } int f() { int a; int b; a = g(); b = a; return a+b; } int e() { int c; c = f(); } main() { return e(); }
我将启动一个程序,并从一开始就连ptrace接到测试程序。然后,我将执行PTRACE_CONT并等待信号。当测试程序会做一次自杀;信号将被传送到我的程序。这时我想读取返回地址,它们就像(因为kill此刻函数处于活动状态):
ptrace
kill
0x00_some_address_in_g 0x00_some_address_in_f 0x00_some_address_in_e 0x00_some_address_in_main 0x00_some_address_in__libc_start_main
我怎样才能找到当前停止的测试过程的返回地址ptrace?会有帧循环吗?我什么时候应该停止这种循环?
PS:是的,这在思想上也很像backtrace(3)libc函数,但是我想通过ptrace从外部进行。
backtrace(3)
osgx发布的示例仅适用于使用框架指针的代码。x86_64GCC产生的带有优化的代码没有。至少在某些处理器上,内核vdso代码x86未使用帧指针。GCC 4.6(具有优化功能)也不在x86模式下使用帧指针。
x86_64
vdso
x86
所有上述所有因素使“通过帧指针进行堆栈爬网”极其不可靠。
您可以使用libunwind(支持本地(进程内)和全局(通过ptrace进行进程外)展开)。
libunwind
否则,您将不得不重新实现很大一部分libunwind。
通过ptrace使用获取回溯的示例libunwind。