从另一个线程打印堆栈跟踪

发布于 2024-10-14 06:53:40 字数 95 浏览 1 评论 0原文

我知道我可以使用 backtrace() 或 [NSThread callStackSymbols] 获取当前线程的堆栈跟踪,但是如何获取不同线程的堆栈跟踪(假设它已被冻结)?

I know I can get the stack trace of the current thread using backtrace() or [NSThread callStackSymbols], but how would I get at the stack trace of a DIFFERENT thread (assuming it's been frozen)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天邊彩虹 2024-10-21 06:53:40

编辑:我原来的答案不会从任意线程打印。此后,我在崩溃处理程序项目中编写了正确的实现: https://github.com/kstenerud/KSCrash

具体来说,这些文件:

需要一些帮助来自:

您要做的是:

  • 创建一个新的机器上下文结构 (_STRUCT_MCONTEXT)
  • 使用 thread_get_state() 填充其堆栈状态
  • 获取程序计数器(第一个堆栈跟踪条目)和帧指针(其余所有)
  • 单步执行帧指针指向的堆栈帧并将所有指令地址存储在供以后使用的缓冲区。

请注意,在执行此操作之前应该暂停线程,否则可能会得到不可预测的结果。

堆栈帧充满了包含两个指针的结构:

  • 上一层的指针
  • 指向堆栈指令地址

因此,在遍历帧以填写堆栈跟踪时需要考虑到这一点。堆栈也有可能损坏,导致指针错误,从而导致程序崩溃。您可以通过使用 vm_read_overwrite() 复制内存来解决这个问题,它首先询问内核是否有权访问内存,这样就不会崩溃。

一旦获得了堆栈跟踪,您就可以像平常一样调用 backtrace() (崩溃处理程序必须是异步安全的,因此它实现了自己的 backtrace 方法,但在正常情况下 backtrace() 就可以了)。

EDIT: My original answer will not print from an arbitrary thread. I've since written a proper implementation in my crash handler project: https://github.com/kstenerud/KSCrash

Specifically, these files:

With some help from:

What you do is:

  • Make a new machine context structure (_STRUCT_MCONTEXT)
  • Fill in its stack state using thread_get_state()
  • Get the program counter (first stack trace entry) and frame pointer (all the rest)
  • Step through the stack frame pointed to by the frame pointer and store all instruction addresses in a buffer for later use.

Note that you should pause the thread before doing this or else you can get unpredictable results.

The stack frame is filled with structures containing two pointers:

  • Pointer to the next level up on the stack
  • instruction address

So you need to take that into account when walking the frame to fill out your stack trace. There's also the possibility of a corrupted stack, leading to a bad pointer, which will crash your program. You can get around this by copying memory using vm_read_overwrite(), which first asks the kernel if it has access to the memory, so it doesn't crash.

Once you have the stack trace, you can just call backtrace() on it like normal (The crash handler has to be async-safe so it implements its own backtrace method, but in normal cases backtrace() is fine).

向地狱狂奔 2024-10-21 06:53:40

这是从另一个线程获取调用堆栈的一些更安全的方法: 实现一些背景信息。它使用信号处理并在目标线程中生成信号处理程序。它还具有比您的解决方案更具跨平台性的优点,即它应该可以在您拥有 的任何地方工作>。

对于打印,您可以按照您自己的建议使用 backtrace_symbols 。但您可能对此处实现的扩展版本感兴趣。它使用 libbfd(来自 binutils;最新版本也主要适用于 MacOSX,请参阅此处了解可能不相关的小限制为您)读取调试信息并添加行号和其他信息(如果其他所有方法都失败,它也会回退到 dladdr;这就是 backtrace_symbols 正在做的事情) 。

Here is some safer way to get the callstack from another thread: Implementation and some background information. It uses signal handling and spawns a signal handler in the target thread. It has also the advantage that it is more cross-platform than your solution, i.e. it should work anywhere where you have <signal.h> and <execinfo.h>.

For the printing, you can use backtrace_symbols as you do in your own suggestion. But you might be interested in an extended version of that as implemented here. It uses libbfd (from binutils; the recent version also mostly works on MacOSX, see here for a small limitation which might not be relevant for you) to read the debugging information and to add line-number and other information (it also falls back to dladdr if all else fails; that is what backtrace_symbols is doing).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文