Я хочу, чтобы мои обработчики исключений и функции отладки могли печатать обратные трассировки стека вызовов, в основном так же, как библиотечная функция backtrace () в glibc. К сожалению, моя библиотека C (Newlib) не обеспечивает такой вызов.
У меня есть что-то вроде этого:
#include <unwind.h> // GCC's 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(); }
обратная трассировка показывает только func3 () и main (). (Это, конечно, игрушечный пример, но я проверил разборку и подтвердил, что все эти функции здесь полностью, а не оптимизированы или встроены.)
Обновление: Я пробовал этот код обратной трассировки на старой системе ARM7, но с теми же (или, по крайней мере, как можно более эквивалентными) параметрами компилятора и сценарием компоновщика, и он печатает правильную полную обратную трассировку (т.е. func1 и func2 не пропущены) и даже возвращаются из основного в код инициализации загрузки. Так что, вероятно, проблема не в скрипте компоновщика или в параметрах компилятора (Кроме того, из разборки было подтверждено, что в этом тесте ARM7 также не используется указатель кадра).
Код скомпилирован с -fomit-frame-pointer, но моя платформа (чистый металл ARM Cortex M3) определяет ABI, который в любом случае не использует указатель кадра. (В предыдущей версии этой системы использовался старый интерфейс ABCS APCS на ARM7 с кадрами с принудительным стеком и указателем кадра, а также след возврата, такой как здесь , который работал отлично).
Вся система компилируется с -fexception, что обеспечивает включение необходимых метаданных, используемых _Unwind, в файл ELF. (_Unwind предназначен для обработки исключений, я думаю).
Итак, мой вопрос:
Существует ли "стандартный", принятый способ получения надежных обратных трассировок во встроенных системах с использованием GCC?
Я не против возиться со скриптами компоновщика и кодом crt0, если это необходимо, но я не хочу иметь никаких шансов для самой цепочки инструментов.
Спасибо!