跳到主要内容

Backtrace Host 符号化

本文档说明 Issue #146host 端 backtrace 日志符号化工具的用途、前置条件、命令参数与典型工作流。

它与 target 侧(QEMU / 板载)输出的 raw backtrace 块 配合使用,由 PR #635 提供实现;target 侧 raw 格式与 E2E 测例由 PR #646 等提供。

设计分工

阶段运行环境职责
Unwind + raw 日志Target(ArceOS / 应用)沿帧指针链展开栈,串口输出固定格式块(BACKTRACE_BEGIN / BT / BACKTRACE_END),仅包含 ipfp 等原始信息
SymbolizeHost(开发机 / 容器)读取日志与同一次构建的 ELF,用 llvm-addr2line / addr2line 解析函数名与源文件行号

这样做的原因包括:

  • Target 在 panic / oops 路径上不宜依赖完整在线 DWARF 解析(体积、稳定性)。
  • Raw 块便于 CI 用正则校验 unwind 是否成功。
  • Host 可使用完整 debuginfo 与成熟的 addr2line 工具链。

本工具 不使用 components/axbacktrace/src/dwarf.rs 的 target 在线符号化路径。

前置条件

  1. Host 工具PATH 中可执行 llvm-addr2lineaddr2line
  2. ELF:与产生日志的那次构建一致(例如 target/x86_64-unknown-none/release/arceos-backtrace-raw-normal),且含 debug 信息(测例通常通过 [env] DWARF=y 等打开帧指针与调试构建)。
  3. 日志:串口或 QEMU 输出中已包含 target 打印的 raw 块(例如 Backtrace::capture().kind("raw")、panic 路径的 .kind("panic")、trap 的 .kind("trap"))。

命令

在仓库根目录执行:

cargo xtask backtrace symbolize \
--elf <ELF> \
[--log <LOG>] \
[--kind <KIND>] \
[--adjust-ip true|false] \
[--ip-bias <I64>]

参数说明

参数必填说明
--elf PATH用于符号化的内核/应用 ELF 路径
--log PATH捕获的文本日志;省略时从 stdin 读取
--kind KIND仅处理 BACKTRACE_BEGINkind= 匹配的块(如 rawpanictrap
--adjust-ip默认 true:符号化前对 ip 减 1,对齐典型 call-site;可用 --adjust-ip false 关闭
--ip-bias I64符号化前对 ip 施加有符号偏移,用于运行时地址与 ELF 布局不一致时(默认 0

实现位于 scripts/axbuild/src/backtrace.rs,由 cargo xtask backtrace 子命令调用。

Target 日志格式(输入)

工具解析如下块(与 axbacktrace 在设置 kind 后的 Display 输出一致):

BACKTRACE_BEGIN kind=raw arch=x86_64 alloc=true dwarf=true
BT 0 ip=0x... fp=0x...
BT 1 ip=0x... fp=0x...
BT_ERROR invalid_fp # 可选,展开失败时
BACKTRACE_END
  • 日志前可有任意前缀噪声;解析器从第一个 BACKTRACE_BEGIN 起进入块内状态。
  • 缺少 BACKTRACE_END 时仍会尝试符号化已捕获的帧。
  • 重复的 BACKTRACE_BEGIN 会拆成多个逻辑块输出。

输出说明

符号化成功后,stdout 大致为:

BACKTRACE_BLOCK 0 kind=raw arch=x86_64
BT 0 ip=0x... fp=0x... <function> (<file>:<line>)
...

若某 ip 无法在 ELF 中解析,可能仍只显示 ip / fp,或解析失败;请确认 ELF 与日志来自同一次构建,必要时尝试 --ip-bias

典型工作流(当前:两步)

在 PR #635(本工具)与 #646(raw 测例)均合入 dev 之前,请使用对应分支构建。

1. 在 target 上产生 raw 日志

示例:ArceOS Rust QEMU 测例 backtrace-raw-normal

cargo xtask arceos test qemu \
--arch x86_64 \
--test-group rust \
--test-case backtrace-raw-normal \
2>&1 | tee /tmp/arceos-backtrace.log

确认日志中有 BACKTRACE_BEGINBT n ip=... fp=...test pass 等。

2. 在 host 上符号化

cargo xtask backtrace symbolize \
--elf target/x86_64-unknown-none/release/arceos-backtrace-raw-normal \
--log /tmp/arceos-backtrace.log \
--kind raw

Panic 路径若使用 kind=panic 的 raw 块,将 --kind 改为 panic,并确保 --elf 与产生该日志的构建一致。

ArceOS QEMU 测试:跑完自动 symbolize

Unix 主机上,cargo xtask arceos test qemu 运行 rust 用例时,默认仅当该用例的 build-<target>.toml 启用了 backtrace 构建[env]BACKTRACE=yDWARF=y,与 axbuild 为帧指针 / 调试信息开门条件一致)时,在 QEMU 结束后:

  1. 将本次串口输出 tee 到 .axbuild/tmp/qemu-logs/<case>-<target>.log
  2. 用同次构建的 ELF 调用 host backtrace symbolize,在终端打印 === host backtrace symbolize === 段。

未启用上述 env 的用例(如 fs/shellexception不会 tee、也不会自动 symbolize;与合并前行为一致。backtrace E2E(如 backtrace-raw-normalDWARF=y)通常 一条命令 即可看到符号化栈。

关闭自动符号化:

cargo xtask arceos test qemu --arch x86_64 --test-group rust --test-case backtrace-raw-normal --no-symbolize

用例名按 - / / 分段匹配 rawpanictrap(例如 backtrace-raw-normal--kind raw;避免 draw 等误匹配)。仍可用上文「手动两步」对任意保存的日志做 symbolize。

验证

在 host 上可运行:

cargo fmt --check
cargo clippy -p axbuild -- -D warnings
cargo test -p axbuild backtrace::

相关文档与 PR