一尘不染

如何仅使用ptrace(Linux,x86 / x86_64)获得“回溯”(如gdb)

linux

我想像backtracegdb一样获得类似输出。但是我想ptrace()直接通过这样做。我的平台是Linux,x86;以及后来的x86_64。

现在,我只想从堆栈中读取返回地址,而无需转换为符号名称。

因此,对于测试程序,-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此刻函数处于活动状态):

 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从外部进行。


阅读 382

收藏
2020-06-07

共1个答案

一尘不染

osgx发布的示例仅适用于使用框架指针的代码。x86_64GCC产生的带有优化的代码没有。至少在某些处理器上,内核vdso代码x86未使用帧指针。GCC
4.6(具有优化功能)也不在x86模式下使用帧指针。

所有上述所有因素使“通过帧指针进行堆栈爬网”极其不可靠。

您可以使用libunwind(支持本地(进程内)和全局(通过ptrace进行进程外)展开)。

否则,您将不得不重新实现很大一部分libunwind

通过ptrace使用获取回溯的示例libunwind

2020-06-07