gpt4 book ai didi

c++ - 如何获得调用堆栈回溯? (深度嵌入,无库支持)

转载 作者:IT老高 更新时间:2023-10-28 21:51:29 28 4
gpt4 key购买 nike

我希望我的异常处理程序和调试函数能够打印调用堆栈回溯,基本上就像 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);
}

这基本上可以工作,但生成的跟踪并不总是完整的。例如,如果我这样做

int func3() { print_backtrace_here(); return 0; }
int func2() { return func3(); }
int func1() { return func2(); }
int main() { return func1(); }

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

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

代码是用 -fomit-frame-pointer 编译的,但是我的平台(裸机 ARM Cortex M3)定义了一个无论如何都不使用帧指针的 ABI。 (该系统的早期版本在 ARM7 上使用旧的 APCS ABI,带有强制堆栈帧和帧指针,以及类似 here 的回溯,效果很好)。

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

所以,我的问题是:在使用 GCC 的嵌入式系统中,是否有一种“标准”、被接受的方法来获得可靠的回溯?

我不介意在必要时必须弄乱链接器脚本和 crt0 代码,但我不想让工具链本身有任何机会。

谢谢!

最佳答案

为此,您需要 -funwind-tables-fasynchronous-unwind-tables在某些目标中,为了 _Unwind_Backtrace 正常工作,这是必需的!

关于c++ - 如何获得调用堆栈回溯? (深度嵌入,无库支持),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3398664/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com