I'm writing some code to debug stackful coroutines that use Boost.Context's make_fcontext
and jump_fcontext
, and have run into a small problem.
Normally it is not possible to backtrace
past the entry of a stackful coroutine as it executes on its own stack. This means that I cannot determine from a debugger from where a coroutine was entered. This, however, is not the problem about which I am asking. I already solved this problem by adding some inline assembly and DWARF bytecode in the function I pass to 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 */)
This really does work and I can now backtrace
to the point in the caller where it starts or resumes the inner coroutine - but only sometimes.
It turns out that gdb has a "sanity check": if the stack pointer moves in the "wrong" direction between call frames, gdb assumes that the stack is corrupt and stops the trace with the message "Backtrace stopped: previous frame inner to this frame (corrupt stack?)
".
This gets triggered when my stacks are allocated in certain ways, but not in other ways. I even have a test with statically allocated stacks that triggers this failure when used in forward order but not when used in reverse order.
I even found the portion of gdb's source code that performs this check here: https://github.com/bminor/binutils-gdb/blob/master/gdb/frame.c#L737-L816
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"?
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"?
There currently is no way to do this. It would be a good idea, but probably would require a DWARF extension of some kind. So, it may be difficult to implement.
You can see the evidence of this in the gdb sources: GCC had a similar issue involving -fsplit-stack
, and this was worked around by simply coding the name of the offending function into gdb:
if (!morestack_name || strcmp (morestack_name, "__morestack") != 0)
A quick workaround for your personal use is to just comment out the early return here.