堆栈协程 + gdb = "previous frame inner to this frame (corrupt stack)?"

Stackful coroutines + gdb = "previous frame inner to this frame (corrupt stack)?"

我正在编写一些代码来调试使用 Boost.Context 的 make_fcontextjump_fcontext 的堆栈协程,并将 运行 变成一个小问题。

通常不可能 backtrace 越过堆栈协程的入口,因为它在自己的堆栈上执行。这意味着我无法通过调试器确定协程的输入位置。然而,这不是我要问的问题。我已经通过在传递给 make_fcontext:

的函数中添加一些内联汇编和 DWARF 字节码解决了这个问题
__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 有一个 "sanity check":如果堆栈指针在调用帧之间向 "wrong" 方向移动,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 "trust me, I know what I'm doing"?

Now here's my actual question: How can I fix this?

Is there some assembly incantation I can write that tells GDB "trust me, I know what I'm doing"?

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

您可以在 gdb 源代码中看到这方面的证据:GCC 有一个涉及 -fsplit-stack 的类似问题,只需将有问题的函数的名称编码到 gdb 中即可解决此问题:

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

您个人使用的一个快速解决方法是注释掉 early return here