Я хочу, чтобы мои обработчики исключений и функции отладки могли печатать обратные трассировки стека вызовов, в основном так же, как функция библиотеки backtrace() в glibc. К сожалению, моя библиотека C (Newlib) не предоставляет такой вызов.
У меня есть что-то вроде этого:
#include <unwind.h> // GCC internal unwinder, part of libgcc
_Unwind_Reason_Code trace_fcn(_Unwind_Context *ctx, void *d)
{
int *depth = (int*)d;
printf("\t#%d: program counter at %08x\n", *depth, _Unwind_GetIP(ctx));
(*depth)++;
return _URC_NO_REASON;
}
void print_backtrace_here()
{
int depth = 0;
_Unwind_Backtrace(&trace_fcn, &depth);
}
который в основном работает, но полученные следы не всегда полны. Например, если я делаю
int func3() { print_backtrace_here(); return 0; }
int func2() { return func3(); }
int func1() { return func2(); }
int main() { return func1(); }
backtrace показывает только функции func3() и main(). (Это пример игрушки, но я проверил разборку и подтвердил, что эти функции здесь полностью, а не оптимизированы или встроены.)
Обновление:. Я пробовал этот код backtrace в старой системе ARM7, но с теми же (или, по крайней мере, как можно более эквивалентными) параметрами компилятора и компоновщиком script, и он печатает правильный, полный backtrace (т.е. func1 и func2 не пропущены), и даже в этом случае он даже возвращает предыдущий код в код инициализации загрузки. По-видимому, проблема связана не с компоновщиком script или с параметрами компилятора. (Кроме того, подтверждено из разборки, что в этом тесте ARM7 не используется указатель фрейма).
Код компилируется с помощью -fomit-frame-pointer, но моя платформа (bare metal ARM Cortex M3) определяет ABI, который в любом случае не использует указатель кадра. (В предыдущей версии этой системы использовался старый APCS ABI на ARM7 с принудительными кадрами стека и указателем кадра, а backtrace как здесь, который отлично работал).
Вся система скомпилирована с -fexception, которая обеспечивает необходимые метаданные, используемые _Unwind, в файл ELF. (_Unwind предназначен для обработки исключений, я думаю).
Итак, мой вопрос: Существует ли "стандартный", приемлемый способ получения надежных обратных трасс во встроенных системах с использованием GCC?
Я не возражаю, если вам придётся возиться со скриптами-компоновщиками и кодом crt0, но не хочу, чтобы у вас были какие-либо шансы на саму программу.
Спасибо!