Crash 处理
本章节介绍在 WQ SDK 启动及运行中出现 Crash 后,如何通过 log 定位问题,包括 log 分析、BackTrace 分析、反汇编分析及 GDB 与 CoreDump 分析。
Log 分析
发生 crash 后, crash 相关信息会通过 LOG 通道输出。 WQ 下载调试工具接收的 log ,存放在工具软件目录下的 LogUART 文件夹中的 .log 文件。详细信息如下:
[auto]crash_test.c:140 Asserted! //crash 发生的代码位置
0x0412006e:0x020093f8 //crash 发生时,调用栈信息
0x041179cc:0x02009438
0x02005f10:0x02009448
0x0412006e:0x00000000
[auto]mcause: 0x03[Breakpoint] //assert 类型的 crash
[auto]core0: exception registers dump //crash 发生在 core0
ra = 0x0200005a
sp = 0x020092b0
t0 = 0x0000002a
t1 = 0x00000000
t2 = 0x00000023
fp = 0x020093c8
s1 = 0x02006970
a0 = 0x00000000
a1 = 0x000000d2
a2 = 0x00000030
a3 = 0x00e88f1f
a4 = 0x00000002
a5 = 0x00000000
a6 = 0x02009158
a7 = 0x20303030
s2 = 0x02006970
s3 = 0x04116000
s4 = 0x00000000
s5 = 0x00000001
s6 = 0xa5a5a5a5
s7 = 0xa5a5a5a5
s8 = 0xa5a5a5a5
s9 = 0xa5a5a5a5
s10 = 0xa5a5a5a5
s11 = 0xa5a5a5a5
t3 = 0x00000039
t4 = 0x00000009
t5 = 0x0000002e
t6 = 0x00000025
0x0412006e:0x020093f8 //crash 发生时,调用栈信息
0x041179cc:0x02009438
0x02005f10:0x02009448
0x0412006e:0x00000000
[auto]mepc: 0x02000076, mbadaddr: 0x00000000 //crash 发生时的代码位置
coredump_callback address: 0x0411 6c84
Current task RA/SP/A0/FP/EPC 2000 05a 20092b0 0 20093c8 2000076
Core dump len = 4192 (8 0)
================= CORE DUMP START =================
YBAAAAEAAAAIAAAAfAAAAA==
WJQAAjiEAAKkkgACSJQAAg==
sJIAAiROAABQcwACUHMAAliUAAJIcwACC AAAAEvrlycWXxZ/WJQAAgAAAAAHAAAA
......
用户可以通过 mcause 判断 crash 类型,初步分析 crash 原因。表 5 1 列举了常见的 mcause 和相应的分析策略。
mcause |
carsh 原因 |
分析策略 |
0x8000000b |
外部中断 |
外部中断可能导致 crash dump 的只有 watchdog timeout 中
断。因此,可以判定为代码存在死循环
|
1 |
数据访问异常 |
|
2 |
非法指令异常 |
首先根据 crash dump内容排查指令是否被修改。
|
3 |
assert 对应的异常 |
同样看log 和 BackTrace 定位问题。 |
5 |
非对齐访问的异常 |
根据 mepc 定位代码和变量,一般都是地址不对齐导致的。 |
7 |
0地址访问对应的异常 |
根据上面的办法找到对应的变量和代码,推测 0 地址访问产
生的原因。
|
根据上文中的 mcause: 0x03 ,可以判断 Crash 原因为 assert 对应的异常。
BackTrace 分析
用户可以通过运行 BackTrace 命令查看调用栈信息,进而定位 Crash 原因。BackTrace 命令可以使用 WQ 下载调试工具运行或通过编译环境运行。
运行 BackTrace 命令需要 log 和相应 core 的 .elf 文件。ELF 文件在编译时生成,存放于 build 目录下相应 core 的文件夹中。如: /<SDK>/application/target_a/build/acore/target_a_acore.elf 。
使用 WQ 下载调试工具
用户可以使用 WQ 下载调试工具运行 BackTrace 命令,查看调用栈信息。操作步骤如下:
打开 WQ 下载调试工具,点击 LogDebug 菜单栏。
在左侧 LOG FILE 区域,选择 UART 输出的 .log 文件。
说明
WQ 下载调试工具接收的 log 存放于工具软件目录下的 LogUART 文件夹下的 .log 文件。
在左侧 APP ELF FILE 区域,选择发生 crash 的 core 所对应的 .elf 文件。
确保串口处于关闭状态。点击 START,即可生成调用栈信息。
使用 BackTrace 命令
在编译环境下运行 BackTrace 命令可以查看调用栈信息。命令如下:
riscv64-unknown-elf-addr2line -f -e build/acore/target_a_acore.elf 0x0412006e:0x020093f8 0x041179cc:0x02009438 0x02005f10:0x02009448 0x0200005a:0x00000000
命令解析:
riscv64-unknown-elf-addr2line -f -e为指令和参数。build/acore/target_a_acore.elf为 .elf 文件相对路径。0x0412006e:0x020093f8 0x041179cc:0x02009438 0x02005f10:0x02009448 0x0200005a:0x00000000为 Crash Log 中的栈调用信息。
输出结果如下:
crash_test
/wqcore/components/share_task_2/src/crash_test.c:141
app_entry
/wqcore/application/target_a/acore/app.c:221 (discriminator 3)
wrapper_task_func
/wqcore/os/os_shim/src/freertos_10_2_1/os_task.c:44
wq_debug_assert
/wqcore/components/wq_debug/src/wq_debug.c:608
查看反汇编
汇编文件可以用于 Crash 原因定位。
WQ SDK 编译时会在相应 core 的 .elf 文件目录下生成.asm 汇编文件,如 /<SDK>/application/target_a/build/acore/target_a_acore.asm 。 用户也可以通过 .elf 文件和反汇编指令生成汇编文件,方便排查定位故障。反汇编指令如下:
riscv64-unknown-elf-objdump -S -x target_a_acore.elf > target_a_acore.asm
GDB 与 CoreDump 分析
Log 中 "=== CORE DUMP START ===" 与 "=== CORE DUMP END ===" 之间的内容(不包含上述两行)为 CoreDump 信息。详细信息如下:
......
Current task RA/SP/A0/FP/EPC 2000 05a 20092b0 0 20093c8 2000076
Core dump len = 4192 (8 0)
================= CORE DUMP START =================
YBAAAAEAAAAIAAAAfAAAAA==
WJQAAjiEAAKkkgACSJQAAg==
sJIAAiROAABQcwACUHMAAliUAAJIcwACC AAAAEvrlycWXxZ/WJQAAgAAAAAHAAAA
......
7x6iiRJ1QtSefzCbz7Zzd9XaBM//nGsb3VEXELWWS7GOaIW74j9QmNww5zqssBvg
e/dpClD6j9zc8AiMGnAcYESv5ejPgdHcNJJwqhaA4uRfqwWGKn481s+sNxJKvhU/
yHitWLoqXhC7HmjaAAAAAAAAAAA=
================= CORE DUMP END =================
将 CoreDump 信息拷贝到一个文件中,重命名以 .b64 做后缀,如 coredump.b64 。
可以通过 wq_coredump.py 脚本执行 CoreDump 指令:
python3 tools/wq_coredump.py dbg_corefile --gdb ~/xxx/riscv64-unknown-elf-gdb -c dump/coredump.b64 -t b64 elf/xcore.elf
指令解析:
tools/wq_coredump.py为 coredump 脚本路径~/xxx/riscv64-unknown-elf-gdb为 GDB 脚本绝对路径dump/coredump.b64为 coredump 文件路径elf/xcore.elf为 .elf 文件路径
执行完成后,进入 GDB 调试状态。可以执行一些 GDB 指令查看 backtrace(bt) 、thread 信息(info thread )、全局变量( p )等信息,如下图所示。