我正在编写一些代码来调试使用Boost.Context的make_fcontext
和jump_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“相信我,我知道我在做什么”吗?
答案 0 :(得分:1)
现在这是我的实际问题:我该如何解决?
我可以写一些汇编咒语来告诉GDB“信任 我,我知道我在做什么”?
目前无法执行此操作。这将是一个好主意,但可能需要某种DWARF扩展。因此,可能难以实施。
您可以在gdb的源代码中看到这一点的证据:GCC有一个涉及-fsplit-stack
的类似问题,可以通过将有问题的函数的名称简单地编码到gdb中来解决:
if (!morestack_name || strcmp (morestack_name, "__morestack") != 0)
一种供个人使用的快速解决方法是仅注释掉early return here。