Skip to content

feat: 增加 Native Hook 批量符号化 - #170

Draft
qiqingzhixin wants to merge 2 commits into
maokelong:mainfrom
qiqingzhixin:codex/issue-152-symbolization
Draft

feat: 增加 Native Hook 批量符号化#170
qiqingzhixin wants to merge 2 commits into
maokelong:mainfrom
qiqingzhixin:codex/issue-152-symbolization

Conversation

@qiqingzhixin

@qiqingzhixin qiqingzhixin commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

变更

  • 增加 SymbolResolver::get_symbols 批量符号化接口,支持 demangle、源码位置、内联链、缺失 SO 汇总和显式 SO 名称映射。
  • 增加调用方持有的进程内 SymbolResolver,复用 SO 路径索引、模块命中/缺失缓存和 Symbolizer
  • 提供单次调用自由函数 get_symbols,内部创建临时 SymbolResolver
  • 增加临时验证适配器 kat-native-hook-symbolize,从当前验证使用的 trace_streamer SQLite 导出 Excel 和 missing_modules 工作表。
  • SQLite/Excel 仅作为真实 Trace 到符号结果的串联验证胶水,不作为独立生产级数据管道。
  • 增加独立的符号化 SDD;不包含应用操作或真机采集脚本。
  • 明确 Rust 核心是与 Trace 存储无关的 ELF 元数据解析能力,不创建 Dataset facts,也不发布 kat.trace 分析语义。
  • CLI 不是 Datasource、KAT 用户入口或长期数据产品,不承诺跨 TraceStreamer 版本或 Excel 格式兼容。

核心代码调用方式

单次调用 get_symbols

use std::{collections::HashMap, path::Path};

use kat_rs_native_hook_symbolize::get_symbols;

let addresses = vec![
    "/system/lib/ld-musl-arm.so.1+0x1234".to_owned(),
    "/system/lib/libexample.so+0x5678".to_owned(),
];
let module_name_map = HashMap::from([
    ("/system/lib/ld-musl-arm.so.1".to_owned(), "libc.so".to_owned()),
]);

let result = get_symbols(
    &addresses,
    Path::new(r"D:\zxlDown\images\laster"),
    &module_name_map,
    true,
)?;

for symbol in result.symbols {
    println!("{symbol}");
}
for missing in result.missing_modules {
    eprintln!("{}: {}", missing.module_path, missing.occurrence_count);
}

参数约定:

  • addr_list:批量输入,地址格式为 模块路径或名称+0x十六进制地址;不能解析的输入保持原样。
  • symbol_dir:本地符号表根目录;存在合法地址输入时,目录不存在会报错。
  • module_name_mapTrace 中的 SO 名称/路径 -> 符号目录中的 SO 名称/路径;可传空表。
  • include_source_locationtrue 返回完整源码路径、行号和内联链;false 只返回函数符号。
  • 返回值 SymbolizationResultsymbols 与输入顺序一一对应;missing_modules 汇总未找到的 SO 及出现次数。

项目内连续调用

整个项目连续处理多批地址时,推荐在进程内复用同一个 SymbolResolver

use std::collections::HashMap;

use kat_rs_native_hook_symbolize::SymbolResolver;

let mut resolver = SymbolResolver::new(r"D:\zxlDown\images\laster");
let module_name_map = HashMap::new();

let first = resolver.get_symbols(&first_batch, &module_name_map, false)?;
let second = resolver.get_symbols(&second_batch, &module_name_map, false)?;

SymbolResolver 首次遇到合法查询时建立一次目录索引,并缓存模块命中和缺失结果。实例存活期间应将符号目录视为只读;目录内容变化后创建新实例。

Trace 转符号示例

cargo run -p kat-rs-native-hook-symbolize `
  --release `
  --bin kat-native-hook-symbolize -- `
  target/trace/run/trace.db `
  --symbol-dir D:/zxlDown/images/laster `
  --output target/trace/run/symbols.xlsx `
  --module-map /system/lib/ld-musl-arm.so.1=libc.so `
  --include-source-location

输出 Excel 的 symbols 工作表包含 callchain_iddepthinput_valueresolved_or_originalcallchain_id 以十进制文本保存,后者在符号化失败时保留输入值;missing_modules 工作表记录缺失 SO 和出现次数。超过单个 Excel 工作表上限时自动分页。

真实 120 秒 Trace 测试

测试条件:Release 模式;符号目录 D:\zxlDown\images\laster,约 23.37 GB、3171 个 SO;启用源码位置、行号、内联链和 musl loader 名称映射。Release 构建耗时不计入转换耗时。

数据与转换结果

指标 结果
Trace 实际时长 119.832 秒
trace.db 大小 42,143,744 B
Native Hook 栈帧总数 131,949
已经是符号或无需转换的输入 60,227
待转换地址 71,722
成功转换地址 69,517
地址转换成功率 96.93%
包含源码文件和行号 68,003
包含内联调用链 26,197
未转换地址 2,205
Excel 大小 2,554,987 B

2,205 条未转换地址全部来自同一个缺失模块:

/vendor/lib/chipsetsdk/libmali-bifrost-g52-g7p0-ohos.so

耗时

场景 耗时
冷缓存 SQLite -> get_symbols -> Excel 36.739 秒
热缓存 SQLite -> get_symbols -> Excel 8.589 秒
热缓存读取 SQLite 0.341 秒
热缓存 get_symbols 首次实例调用 5.443~7.712 秒
同一进程复用 SymbolResolver,相同批次再次调用 0.448 秒
写入 Excel 2.723 秒

热缓存 get_symbols 处理速度约 2.42 万帧/秒。相同批次复用实例约 29.5 万帧/秒,属于目录索引、模块路径和文件系统缓存充分的最佳情况;不同地址批次会高于 0.448 秒,但仍能复用目录索引和模块缓存。

批量规模回归

以下是基于一份真实 30 秒帧序列进行 1×/2×/4× 复制的核心接口规模测试,用于观察输入规模增长趋势,不等同于真实 60/120 秒采集结果:

等效规模 总输入 每次新建实例 复用实例 提升
30s / 1× 282,982 2,593 ms 395 ms 6.6×
60s / 2× 565,964 3,887 ms 1,065 ms 3.6×
120s / 4× 1,131,928 5,981 ms 2,509 ms 2.4×

验证

  • cargo test -p kat-rs-native-hook-symbolize:15 passed(9 个库测试、3 个 CLI 单元测试、3 个 CLI 集成测试)。
  • cargo fmt --all -- --check
  • cargo clippy -p kat-rs-native-hook-symbolize --all-targets -- -D warnings
  • git diff --check
  • PR CI:等待新 head 的检查结果。
  • 真实 120 秒 Trace 已完成 SQLite 读取、批量符号化、缺失模块汇总和 Excel 导出的完整串联验证。

Trace 采集由 #171 独立交付。

Closes #169

Refs #152

@qiqingzhixin
qiqingzhixin force-pushed the codex/issue-152-symbolization branch from 8a02abf to 2bc2d04 Compare July 21, 2026 09:17
@qiqingzhixin qiqingzhixin changed the title feat: 增加 Native Hook 符号化与 Excel 导出 feat: 增加 Native Hook 批量符号化 Jul 21, 2026
@qiqingzhixin

Copy link
Copy Markdown
Collaborator Author

Review Agent 评审结果(head 0bbdd775

固定对象:base a15bac16,merge-base 02312047,head 0bbdd775;实际变更为 8 个文件,新增 1322 行、删除 1 行。

总分 ★★★★☆
├── 冷读评审 ★★★★☆
│   ├── 表达结构 ★★★★☆ high
│   ├── 信息自足性 ★★★★☆ high
│   └── 命名准确性 ★★★★☆ high
├── 一致性评审 ★★★★★
│   ├── 对象—设计一致性 ★★★★★ high
│   └── 决策演进完整性 ★★★★★ high
└── 同行评审 ★★★★☆
    ├── 技术成立性 ★★★★☆ high
    └── 生态适配性 ★★★★☆ high

总分按最低分支计算,为 4 星。

冷读评审 findings

F-ES-001:“兼容函数”缺少兼容对象

  • Problem:README 和设计文档把自由函数 get_symbols 称为“兼容函数”,但该 crate 和接口都是本 PR 新增,没有说明兼容哪个历史接口或调用方式。
  • Static evidencecrates/kat-rs-native-hook-symbolize/README.md:35docs/superpowers/specs/2026-07-17-native-hook-symbolization-design.md:74
  • Project impact:调用方无法仅凭文档判断它是迁移桥接入口、长期稳定入口,还是普通便利包装。

F-IS-001:公开 API 文档没有完整承载调用契约

  • Problem:关键约束主要写在 README 和 SDD 中,Rust API 自身的 rustdoc 没有完整说明映射方向、目录稳定性、延迟校验时机、源码/内联开关和失败返回语义。
  • Static evidencecrates/kat-rs-native-hook-symbolize/src/lib.rs:54-71,169-176;对应约束见 README.md:31,48 和设计文档 :74-88
  • Project impact:只通过生成的 Rust API 文档接入时,调用方无法获得完整契约。

F-NA-001:module_path 也可能只是 SO 名称

  • ProblemMissingModule::module_path 的名称表示路径,但合法输入也可以只有 libfoo.so 这样的 basename。
  • Static evidencecrates/kat-rs-native-hook-symbolize/src/lib.rs:16-17,25-28,94-100,339-344
  • Project impact:下游可能误把该值当成可直接定位文件的完整路径。

一致性评审

无正式 finding。新设计已经明确 Rust 核心只负责 ELF 元数据解析,不创建 Dataset Trace facts、不发布 kat.trace 分析语义;SQLite→Excel 只作为临时验证适配器,并保持原 Native Hook Datasource/domain/sink 边界。与 accepted ADR 0024、0049、0050 没有观察到冲突。

同行评审 findings

T1:Issue 要求的源码位置自动化覆盖尚未形成

  • Problem:Issue feat: Native Hook Trace 采集与符号转换 #152 明确要求 Rust 单元测试覆盖源码位置;当前自动化测试没有成功符号化含 DWARF 的 ELF并断言函数名、偏移、源码文件/行号、inline 链或 demangle 结果。
  • Static evidence:生产路径位于 crates/kat-rs-native-hook-symbolize/src/lib.rs:310-327;库测试位于 :338-468
  • Project impact:Issue 的文字验收与现有自动化覆盖不完全一致。约 23 GB 真实 OpenHarmony 符号目录属于外部构建产物,不提交仓库;普通 CI 无法携带该目录本身不构成 finding。真实 120 秒 Trace 验证使技术成立性保持为 4 星,而不是 3 星。

E1:Issue 记录的交付 PR 仍是旧编号

Pending(不参与评分)

  • PR 正文中的测试、Clippy、真实 120 秒 Trace 和性能数据,本轮未运行复验。
  • 外部 23 GB 符号目录不进入仓库或普通 CI,不作为 finding。
  • PR 当前仍为 Draft,且没有远端 status checks。
  • 当前 PR 相对最新 mainCONFLICTING / DIRTY;这是 base 演进产生的集成挑战,没有用于限制评分。
  • 真实 Trace 的 vaddrVirtOffset 语义对应仍依赖已有外部验证证据。

本轮仅进行静态评审,没有修改文件、运行测试或执行程序。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Native Hook 地址批量符号转换

1 participant