本文介绍了如何获得“回溯” (如gdb)只使用ptrace(linux,x86 / x86_64)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想像gdb那样得到 backtrace 类似的输出。但我想直接通过 ptrace()来实现。我的平台是Linux,x86;和后来的x86_64。

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



因此,对于测试程序,由 gcc-4.5 编译 -O0 模式:

  int g(){
kill(getpid(),SIGALRM);
}
int f(){
int a;
int b;
a = g();
b = a;
返回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:是的,这也非常类似于在想法中,但我想通过ptrace在外部执行此操作。

解决方案

osgx发布的示例仅适用于使用帧指针的代码。 GCC使用优化生成的代码 x86_64 没有。至少在一些处理器上, x86 上的内核 vdso 代码不使用帧指针。 GCC 4.6(带优化)不会在 x86 模式下使用帧指针。



以上所有组合

你可以使用 libunwind (它同时支持本地(正在处理)和(通过ptrace进行的进程外)展开)。



或者您必须重新实现 libunwind 的很大一部分。



通过 ptrace 使用 libunwind 获取回溯。


I want to get a backtrace-like output as gdb does. But I want to do this via ptrace() directly. My platform is Linux, x86; and, later x86_64.

Now I want only to read return addresses from the stack, without conversion into symbol names.

So, for test program, compiled in -O0 mode by 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();
  }

I will start a my program and connect with ptrace to test program at very beginning. Then, I will do PTRACE_CONT and will wait for signal. When test program will do a self-kill; the signal will be delivered to my program. At this moment I want to read return addresses, they will be like (because kill function is active at the moment):

 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

How can I find return addresses of currently stopped test process with ptrace? There will be a loop over frames? When should I stop such loop?

PS: yes, this is also very like backtrace(3) libc function in idea, but I want to do this externally via ptrace.

解决方案

The example posted by osgx will work only with code that uses frame pointers. x86_64 code produced by GCC with optimizations doesn't. The kernel vdso code on x86 doesn't use frame pointers on at least some processors. GCC 4.6 (with optimization) doesn't use frame pointers in x86 mode either.

All of the above combine to make the "stack crawl via frame pointers" exceedingly unreliable.

You can use libunwind (which supports both local (in-process) and global (out-of-process via ptrace) unwinding).

Or you'll have to re-implement very large portion of libunwind.

Example of getting backtrace via ptrace using libunwind.

这篇关于如何获得“回溯” (如gdb)只使用ptrace(linux,x86 / x86_64)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-16 09:08