Backtrace 栈回溯
3 Mar 2025
Read time: 4 minute(s)
Luban-Lite 提供 Backtrace 及解析功能,便于开发者准确定位软件调试中出现的系统崩溃问题,例如内存访问越界。在系统创建线程时,会分配栈内存空间,通过分析运行时栈内存的结构,逐层解析函数调用的历史记录,从而定位出软件异常的问题点。
本节适用于以下芯片系列:
- D21x
- D13x
- D12x
- G73x
栈回溯功能的相关工具均已包含在最新 SDK 中,确保已更新至最新的 SDK。
注: 在 Luban-Lite 中,Backtrace 及解析功能仅用于调试 RT-Thread 的多线程,无法用于调试
BootLoader。
Backtrace 配置方法
在 menuconfig 中开启 Backtrace debug
功能,并修改编译链接脚本以支持栈回溯,以便在发生系统异常时打印出函数调用地址。详细配置流程如下所示:
注: 为避免量产软件的性能受影响,确保在量产软件中关闭 backtrace。
- 在 SDK 的 menuconfig 功能配置界面,选择项目的 RT-Thread 配置页,并打开 Backtrace
调试功能:
Drivers options ---> Drivers debug [*] Enable Backtrace debug
- 保存并退出配置界面。
- 修改编译链接脚本以支持栈回溯:
- 在项目对应芯片目录中打开编译链接脚本,例如 D12x/bsp/artinchip/sys/d21x/rtconfig.py。
- 将 BACKTRACE = False 修改为 BACKTRACE = True:
... # BACKTRACE = True BACKTRACE = False ...
- 保存文件并关闭编辑器。
实例分析
以下是一个制造非法内存访问的示例代码,用于演示如何生成和解析栈回溯信息:
- 在 SDK 中加入下列代码进行编译、烧录:注:
如需使用栈回溯,务必保证镜像和生成的 elf 文件对应,即编译一次、烧录一次、分析一次。
此段代码尝试写入一个空指针地址,导致存储访问故障。
int stack_protector_test(int argc, char **argv) { int * p = NULL; p = (int *)0x80000000; *p = 0x12345678; value = *p; printf("addr:%p value:0x%08X\r ", p, value); return 0; } MSH_CMD_EXPORT(stack_protector_test test stack protector test test test test)
-
系统运行后,执行下列命令,并观察串口终端输出的错误信息和堆栈回溯:
stack_protector_test
串口终端的系统输出示例如下所示:CPU Exception: NO.7 x1: 4002bf64 x2: 30066270 x3: 30042d8c x4: deadbeef x5: 80007880 x6: 300662b4 x7: deadbeef x8: 00000014 x9: 30064212 x10: 00000001 x11: 80000000 x12: 12345678 x13: 00000000 x14: 30064226 x15: 80000000 x16: 30064226 x17: fffffffd x18: 400461ae x19: 400bddf8 x20: 40155fb8 x21: 400bdf30 x22: 0000007f x23: 30044d04 x24: 20636961 x25: 400c45d4 x26: 300641c2 x27: 30064212 x28: 00000022 x29: 0000005c x30: 0000000a x31: deadbeef mcause : 0x38000007 mtval : 0x00000000 mepc : 0x400461c4 mstatus: 0x80007880 __stext:0x40000000 __etext:0x400bdfe0,stack: stack_addr:0x30064330 stack_addr_end:0x30066330 0x0000007f 0x00000009 0x400c45c8 0x4002bf64 0x0000001b 0x30044d8c 0x30064212 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x0000007f 0x00000009 0x400c45c8 0x000000fd 0x0000001b 0x30044d8c 0x30064190 0x4002b9c0 0xdeadbeef 0xdeadbeef 0x00000000 0x30064190 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x0dadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x4001a874 [backtrace_call_stack:123]__stext:0x40000000 __etext:0x400bdfe0 0x400461c4 0x4002bf64 0x4002b9c0 0x4001a874
-
将串口终端的输出信息保存为 txt 文本,并使用 panic_parse.py 进行解析。
假设 backtrace 信息保存在根目录中,保存的输出示例 txt文件为 kunlunpi-panic.txt,则在 SDK 根目录执行如下操作命令:python3 tools/scripts/panic_parse.py -l ./kunlunpi-panic.txt
- 查看解析后的输出,确定导致异常的具体函数位置。解析结果示例如下,分析文件指明了函数调用的关系和导致异常的函数具体位置:
CPU: RISC-V ELF: output/d13x_kunlunpi88-nor_rt-thread_helloworld/images/d13x.elf Toolchain: riscv64-unknown-elf Text section: 0x40000000 - 0x400bdfe0, size: 778208 Bytes --------------------------------------------------------------- CPU Registers: --------------------------------------------------------------- CPU Exception: 7 (Store/AMO Access Fault) x1 (ra): 0x4002bf64 _msh_exec_cmd at kernel/rt-thread/components/finsh/msh.c:294 x2 (sp): 0x30066270 x3 (gp): 0x30042d8c x4 (tp): 0xdeadbeef x5 (t0): 0x80007880 x6 (t1): 0x300662b4 x7 (t2): 0xdeadbeef x8 (s0/fp): 0x00000014 x9 (s1): 0x30064212 x10 (a0): 0x00000001 x11 (a1): 0x80000000 x12 (a2): 0x12345678 x13 (a3): 0x00000000 x14 (a4): 0x30064226 x15 (a5): 0x80000000 x16 (a6): 0x30064226 x17 (a7): 0xfffffffd x18 (s2): 0x400461ae stack_protector_test at packages/artinchip/lvgl-ui/aic_ui.c:64 x19 (s3): 0x400bddf8 __console_init_start at ??:? x20 (s4): 0x40155fb8 x21 (s5): 0x400bdf30 __fsymtab_end at ??:? x22 (s6): 0x0000007f x23 (s7): 0x30044d04 x24 (s8): 0x20636961 x25 (s9): 0x400c45d4 x26 (s10): 0x300641c2 x27 (s11): 0x30064212 x28 (t3): 0x00000022 x29 (t4): 0x0000005c x30 (t5): 0x0000000a x31 (t6): 0xdeadbeef mcause: 0x00000000 mtval: 0x00000000 mepc: 0x00000000 mstatus: 0x00000000 --------------------------------------------------------------- Call Stack: --------------------------------------------------------------- Stack section: 0x30064330 - 0x30066330, size: 8192 Bytes 0: [0x4002bf64] _msh_exec_cmd at kernel/rt-thread/components/finsh/msh.c:294 1: [0x4002b9c0] finsh_thread_entry at kernel/rt-thread/components/finsh/shell.c:657 2: [0x4001a874] _thread_exit at kernel/rt-thread/src/thread.c:91