小编hug*_*gov的帖子

如何获得调用堆栈回溯?(深入嵌入,没有库支持)

我希望我的异常处理程序和调试函数能够打印调用堆栈回溯,基本上就像glibc中的backtrace()库函数一样.不幸的是,我的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);
}
Run Code Online (Sandbox Code Playgroud)

这基本上有效,但结果痕迹并不总是完整的.例如,如果我这样做

int func3() { print_backtrace_here(); return 0; }
int func2() { return func3(); }
int func1() { return func2(); }
int main()  { return func1(); }
Run Code Online (Sandbox Code Playgroud)

backtrace只显示func3()和main().(这是一个玩具示例,但我已经检查了反汇编并确认这些功能全部都在这里,并没有优化或内联.)

更新:我在旧的ARM7系统上尝试了这个回溯代码但是使用相同(或至少,尽可能等同)的编译器选项和链接描述文件,它打印出正确的完整回溯(即func1和func2不会丢失)和实际上它甚至会将过去的主要内容转移到启动初始化代码中.所以可能问题不在于链接器脚本或编译器选项.(另外,通过反汇编确认在此ARM7测试中也没有使用帧指针).

代码使用-fomit-frame-pointer编译,但我的平台(裸机ARM Cortex M3)定义了一个不使用帧指针的ABI.(该系统的先前版本在ARM7上使用旧的APCS ABI,具有强制堆栈帧和帧指针,以及类似于此处的回溯,它完美地工作).

整个系统使用-fexception进行编译,这确保了_Unwind使用的必要元数据包含在ELF文件中.(_Unwind是为我认为的异常处理而设计的).

所以,我的问题是: 在使用GCC的嵌入式系统中,是否存在"标准",可接受的可靠回溯方式? …

c c++ gcc arm newlib

20
推荐指数
3
解决办法
1万
查看次数

标签 统计

arm ×1

c ×1

c++ ×1

gcc ×1

newlib ×1