Замена функции dump_stack() во freertos

#gdb #freertos #backtrace

#gdb #freertos #обратная трассировка

Вопрос:

У меня есть FreeRTOS, работающий на процессоре ARM, и у меня нет dump_stack(), доступного для меня… Я пытаюсь проверить цепочку вызовов и сильно пропускаю dump_stack()… Я немного погуглил и нашел что-то близкое к тому, что искал, используя утилиту GCC(/ GDB) _Unwind_Backtrace(), но она печатает только адрес stack_frame . Он не обеспечивает сопоставление значимым символам (например, именам функций). Любая помощь действительно ценится.

 #include <stdio.h>
#include <unwind.h>
#include <stdint.h>


static _Unwind_Reason_Code unwind_backtrace_callback(struct     _Unwind_Context* context, void* arg)
{

    uintptr_t pc = _Unwind_GetIP(context);
    if (pc) {
        printf("unwind got pc ...0x%xn", pc);
    }

    return _URC_NO_REASON;
}

ssize_t unwind_backtrace()
{
    _Unwind_Reason_Code rc = _Unwind_Backtrace(unwind_backtrace_callback, 0);
    return rc == _URC_END_OF_STACK ? 0 : -1;
}

void func_1()
{
    int ret = unwind_backtrace();
    printf("unwind_backtrace return ...%dn", ret);
}

void func_2()
{
   func_1();
}


int main()
{
    func_2();
    return 0;
}

Result:
unwind got pc ...0x40076b
unwind got pc ...0x400796
unwind got pc ...0x4007bd
unwind got pc ...0x400819
unwind got pc ...0x67314b15
unwind got pc ...0x400649
unwind_backtrace return ...0
 

Ответ №1:

Все IDE, которые я использую (а я использую много), показывают мне трассировку стека в окне — но только для текущей выполняемой задачи. Если я хочу видеть трассировку для всех задач, мне нужен полностью потокоустойчивый плагин FreeRTOS типа, предоставляемого Segger, IAR и Code Confidence .

Комментарии:

1. Привет, Ричард, спасибо за ответ. На самом деле я использую комбинацию Linux-Cscope-Ctags для записи / просмотра кода прошивки и кросс-компиляции по цепочке GCC / ARM. Теперь загрузил двоичный файл в устройство (у меня нет устройства JTAG) и хочу проверить цепочку вызовов в какой-либо функции.

Ответ №2:

Он не обеспечивает сопоставление значимому символу

«Стандартный» способ выполнить это сопоставление — использовать addr2line . Что-то вроде:

 addr2line -fe a.out 0x40076b 0x400796 0x4007bd ...
 

Обновить:

Я хочу конвертировать на лету…

Ну, тогда вы должны были попросить об этом.

Это простой вопрос написания кода. Вам нужно написать код, который будет сопоставлять диапазоны адресов с именами символов (точно так же, как addr2line это делается).

На платформе ELF это на самом деле довольно просто: прочитайте Elf32_Sym s из .symtab раздела, чтобы построить адрес для сопоставления символов, и найдите свои адреса в этой карте. Вам также нужно будет прочитать соответствующие имена символов из .strtab раздела ( Elf32_Sym.st_name это смещение в .strtab ).

Комментарии:

1. спасибо за предложение «addr2line». Это делается для преобразования шестнадцатеричных символов в имя ФУНКЦИИ в автономном режиме. Я хочу конвертировать на лету….