堆栈式协程+ gdb =“此框架内部的先前框架(损坏的堆栈)?”

时间:2018-09-26 13:24:06

标签: c++ gdb coroutine dwarf fibers

我正在编写一些代码来调试使用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具有“健全性检查”:如果堆栈指针在调用帧之间沿“错误”方向移动,则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“相信我,我知道我在做什么”吗?

1 个答案:

答案 0 :(得分:1)

  

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

     

我可以写一些汇编咒语来告诉GDB“信任   我,我知道我在做什么”?

目前无法执行此操作。这将是一个好主意,但可能需要某种DWARF扩展。因此,可能难以实施。

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

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

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