3

我正在编写一些代码来调试使用 Boost.Contextmake_fcontext和的堆栈协程jump_fcontext,并且遇到了一个小问题。

通常不可能backtrace越过堆栈协程的入口,因为它在自己的堆栈上执行。这意味着我无法从调试器中确定协程是从哪里输入的。然而,这不是我要问的问题。我已经通过在传递给的函数中添加一些内联汇编和 DWARF 字节码解决了这个问题make_fcontext

__asm__ volatile (
  "mov %[caller_fcontext_t] %[somewhere]\n\t"
  ".cfi_escape /* DWARF bytecode to load caller_fcontext_t from "
  "             * somewhere and use it to load all the registers saved "
  "             * there by jump_fcontest */"
  "call %[another_function]"
  : /* stuff */ : /* stuff */ : /* stuff */)

这确实有效,我现在backtrace可以在调用者中启动或恢复内部协程的点 - 但只是有时。

事实证明,gdb 有一个“健全性检查”:如果堆栈指针在调用帧之间以“错误”的方向移动,gdb 假定堆栈已损坏并使用消息“ Backtrace stopped: previous frame inner to this frame (corrupt stack?)”停止跟踪。

当我的堆栈以某种方式分配时,这会触发,但不会以其他方式。我什至对静态分配的堆栈进行了测试,当以正向使用时会触发此故障,但在反向使用时不会触发此故障。

我什至在这里找到了执行此检查的 gdb 源代码部分:https ://github.com/bminor/binutils-gdb/blob/master/gdb/frame.c#L737-L816

现在这是我的实际问题:我该如何解决这个问题?

是否有一些我可以写的汇编咒语告诉 GDB“相信我,我知道我在做什么”?

4

1 回答 1

2

现在这是我的实际问题:我该如何解决这个问题?

是否有一些我可以写的汇编咒语告诉 GDB“相信我,我知道我在做什么”?

目前没有办法做到这一点。这将是一个好主意,但可能需要某种 DWARF 扩展。所以,实施起来可能比较困难。

您可以在 gdb 源代码中看到这方面的证据:GCC 有一个类似的问题涉及-fsplit-stack,并且通过简单地将有问题的函数的名称编码到 gdb 中来解决这个问题:

  if (!morestack_name || strcmp (morestack_name, "__morestack") != 0)

供您个人使用的快速解决方法是在此处注释掉提前返回

于 2018-09-26T16:14:44.350 回答