Я пишу некоторый код для отладки стековых сопрограмм, использующих Boost.Context make_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: "Доверяй мне, я знаю, что я"я делаю "?