查看: 3682|回复: 3

鸿蒙DFX Skills实战:崩溃符号化与trace多版本对

[复制链接]
发表于 5 天前 | 显示全部楼层 |阅读模式
从手工查日志到 Skill 调用:DFX Skills 解决什么问题

HarmonyOS / OpenHarmony 应用出现崩溃、卡死、卡顿、内存泄漏或性能回退时,传统做法是拿到 faultlog 后翻文档、手敲命令行工具、逐帧核对堆栈。DFX Skills 把这部分 DFX 专家经验沉淀为可被 AI Agent 调用的 Skill,面向 HarmonyOS / OpenHarmony 生态提供故障自动化分析能力,开源仓库位于 gitcode 的 openharmony-sig/developtools_dfx_skills。

这套技能集包含 cppcrash-analysis、jscrash-analysis、jsleak-analysis、appfreeze-analysis、perf-analysis 等技能。实际使用时的主线很清晰:描述问题、给出日志,由技能完成解析、反解、对比和根因定位。下面按五类高频问题拆解具体操作。

一、崩溃分析:符号表反解的状态门禁

很多人把 crash 日志丢给 Agent 后,最担心的是堆栈没符号化就给出修复建议。cppcrash-analysis 与 jscrash-analysis 设有“符号表反解状态门禁”机制:技能在输出修复建议前,会自动判断关键栈帧是否已经符号化,未反解时会在建议中要求补充匹配 BuildID 的符号文件。

门禁的判断规则分两种。已反解:明确说明使用了匹配 BuildID 的符号文件,并给出函数名或源码行;未反解:未核对 BuildID,或关键帧仍只有裸地址加 offset。对应的门禁动作是——应用侧未反解就要求提供应用 .so / 符号,系统侧未反解就要求提供系统模块符号。

所以提示词不必写得很复杂,关键是把符号文件和源码路径交代清楚。CppCrash 场景可以这样描述:已准备好符号表,符号表 .so 路径为 D:/symbols/libentry.z.so,源码项目根目录为 D:/MyHarmonyApp,请用 ohos_llvm_tools.py addr2line 反解后结合源码分析。JSCrash 场景则是给出 sourceMaps.json 目录与 crash 日志文件路径,要求用 hstack 反解后重新分析根因。

二、符号化流程:不需要手动反编译日志

有符号表时无需先把日志反编译好再交给 Agent,把符号表 / SourceMap 与故障日志一起提供即可,技能会自动完成反解、校验和源码定位。

Native 层由 addr2line 加 objdump 完成反解。cppcrash-analysis 的 Script 目录下工具有固定流程:main.py 先提取关键日志中的 Reason、信号、寄存器、调用栈帧;识别到 .so 裸地址后,检查是否存在匹配 BuildID 的符号;再由 addr2line 把 pc 偏移还原为函数名与源文件行号。
  1. python "<skill-root>/scripts/ohos_llvm_tools.py" addr2line "libentry.z.so" 0xa3f0
复制代码

当需要分析多参数、虚表、函数指针这类信息时,用 objdump 反汇编 pc 附近指令:
  1. python "<skill-root>/scripts/ohos_llvm_tools.py" objdump "libentry.z.so" output/
复制代码

提供源码目录后,技能会结合行号上下文检查空值、边界、线程与回调时序,这比只看函数名更容易定位到真实缺陷。

ArkTS 层走 hstack 加 SourceMap 的路径。日志中出现 Cannot get SourceMap info, dump raw stack,或者函数名被混淆时,就视为未反解。提供 sourceMaps.json 后,技能先做 UUID / 构建指纹校验,指纹一致才执行 hstack 反解;启用混淆时追加 -n 并提供 nameCache.json,方法名会同步还原。
  1. Windows: hstack.bat -i "<crash-dir>" -o "<output-dir>" -s "<source-map-dir>"
  2. Linux/macOS: hstack -i "<crash-dir>" -o "<output-dir>" -s "<source-map-dir>"
复制代码

反解完成后会做一次校验:至少有一个应用帧被还原为“源文件:函数:行:列”,后续分析以反解后的堆栈为准,避免在裸地址上做无效推理。

三、内存泄漏:三模式快照对比

jsleak-analysis 内置 heap_cluster.js,提供三种对比模式,把快照目录交给 Agent 并描述诉求,技能会自动选择模式。

多快照总榜(--multi)适合把多份快照聚合分析,找出持续出现、累计占用最大的对象:
  1. & $NODE "$SKILL_DIR/scripts/node/heap_cluster.js" --multi --multi-top 20 "D:/snapshots/" "D:/output/"
复制代码

产出包括累计 Retained Size、出现次数、平均排名和代表引用链。双版本增长对比(--compare)用于旧版本与新版本的差异分析:
  1. & $NODE "$SKILL_DIR/scripts/node/heap_cluster.js" --compare --compare-top 20 "D:/v1/" "D:/v2/" "D:/output/"
复制代码

产出新增对象 TopN、增长对象 TopN、增长量 / 比例以及相似引用链组,据此判断是新增泄漏还是已有泄漏加重。测试版差值对比(--compare-experimental)则优先展示 retained size 差值最大的对象:
  1. & $NODE "$SKILL_DIR/scripts/node/heap_cluster.js" --compare-experimental --compare-top 20 "D:/v1/" "D:/v2/" "D:/output/"
复制代码

对比之后技能还会继续往下走:为每个嫌疑对象匹配故障模式(ROOT_VM / ROOT_FRAME / LOCAL_HANDLE / GLOBAL_HANDLE),输出三级根因并给出回归排查建议;如果提供 native hook DB,还可以执行 GlobalHandler 关联 native 堆栈,把 JS 侧的持有关系接到 native 调用链上。

四、性能回退:多版本 trace 独立分析再归并

perf-analysis 支持多日志独立分析加汇总归并。把多个 trace 路径交给 Agent,技能逐个转换、逐个分析,最后归并出 Top 3 根因。例如对比 v1 基线 D:/traces/v1/trace_v1.sys 与 v2 新版 D:/traces/v2/trace_v2.sys,问题描述为“列表滑动卡顿,新版本更严重”。

执行上分几步:对每个 trace 调用 convert_hitrace_to_sqlite,返回 sqlite_path 和时间范围;再按症状自动选择分析技能——“卡顿 / 丢帧”走 frame_drop_analysis,“启动 / 冷启动”走 launch_perf,“调度 / 线程阻塞”走 sched_analysis,“负载对比”走 load_compare,无法明确时走 ad_hoc_exploration;随后逐个 run_skill,auto_continue=True 自动执行到完成,单个失败不阻断其他日志。

汇总阶段做三件事:同一根因去重归并,按严重度乘涉及日志数排序取 Top 3,并标注每个根因涉及哪些版本。输出形如:RS 渲染耗时过长(v2),建议优化复杂布局;UI 线程 Binder 超时(v1、v2),建议异步化跨进程调用;主线程连续耗时回调(v2),建议把长任务拆分为分帧执行。对比结论是 v2 丢帧更严重,RS 负载从偶发变为持续。

五、开发态日志采集:AppFreeze 与 jsleak

DFX Skills 遵循“日志就绪”原则,日志缺失时会主动引导采集,而不是直接给出空泛结论。

AppFreeze(冻屏 / 卡死):系统在主线程或业务线程阻塞 6 秒后自动生成 faultlog,例如 THREAD_BLOCK_6S。开发态复现可以在代码中模拟主线程阻塞,如 sleep、死循环、死锁。日志文件位于 /data/log/faultlog/ 和 /data/log/reliability/。把 faultlog 与采样栈文件交给 Agent 后,技能先读 overview,再按需读取各区段。

JS 内存泄漏:在 DevEco Studio 的 Profiler → Memory 中,于操作前后各抓一次 .rawheap,形成基线与对比。文件路径为 /data/log/memleak/,命名格式是 memleak-js-{bundleName}-{pid}-{timestamp}.rawheap。注意 .rawheap 可能以 .log 扩展名保存,确认后创建副本再交给技能;技能内置 rawheap_translator,会自动转换为 .heapsnapshot 再聚类,多快照可直接用 --multi 或 --compare 对比。

性能场景的 trace 与 perf 抓取同样不用手查文档:perf-analysis 内置 catch-trace.md 与 catch-perf.md 抓取指南,日志缺失时技能会自动引导完成 hdc hitrace 和 hiperf 采集。

实践建议

这套技能真正的价值不在“少敲几条命令”,而在把几个容易出错的环节固化了:符号表匹配 BuildID 的门禁,避免在未反解的裸地址上得出错误结论;SourceMap 的 UUID / 构建指纹校验,避免用了错误版本的映射文件;快照与 trace 的多版本对比模式,把“哪个版本变差了、差在哪个对象或哪段渲染”变成可重复的分析流程。对团队而言,日常排障可以先把日志解析和对比交给 Agent,人专注在根因确认与修复验证上,这与 DFX Skills “让专家经验可复制”的设计哲学一致。
回复

使用道具 举报

发表于 5 天前 | 显示全部楼层

Re: 鸿蒙DFX Skills实战:崩溃符号化与trace多版本对

这套把 DFX 经验固化成 Agent 可调用 Skill 的思路挺实在,尤其是崩溃分析里的符号表反解状态门禁。以前直接把 crash 日志丢给模型,堆栈全是裸地址加 offset,它照样能一本正经给出修复建议,行号和函数根本对不上,等于白折腾。现在先判断关键帧有没有用匹配 BuildID 的符号反解过,没反解就要求补 .so 和源码路径,这个前置校验很有必要。 addr2line 配 objdump 那段也说到点子上了。只看函数名往往定位不到真问题,虚表、函数指针、多参数这些还得看 pc 附近的指令,再结合源码行号上下文判断空值和边界,才比较靠谱。ArkTS 侧先做 UUID 和构建指纹校验再 hstack,这个细节容易被忽略,指纹不一致反解出来的东西反而误导人。 内存泄漏的三种快照对比模式看着挺顺手,多快照总榜适合长期挂机跑出来的数据,双版本对比适合回归测试。实际用的时候可能要留意快照采集间隔和操作路径尽量一致,不然比出来的增长量大概率是噪声。另外想请教一下,如果 BuildID 匹配不上,门禁是直接拦住不给结论,还是会给一个标注了风险等级的降级分析? 还有个小事,正文好像断在“输出三级根”这里,后面卡死、卡顿和性能回退那几类还没展开,方便的话补个下篇,正好跟着实践一遍。
回复 支持 反对

使用道具 举报

发表于 5 天前 | 显示全部楼层

Re: 鸿蒙DFX Skills实战:崩溃符号化与trace多版本对

看完挺有收获。把 DFX 专家经验沉淀成可调用的 Skill,这个思路对日常排障很实用,尤其是崩溃分析里“符号表反解状态门禁”这一点,能避免在裸地址上直接给修复建议,可靠性会高很多。实际落地时我觉得可以把符号文件、源码根目录、SourceMap、nameCache 和快照目录提前整理成固定输入清单,崩溃场景先确认 BuildID 或构建指纹是否匹配,再让技能做反解和源码定位,效率会更高。 内存泄漏部分的三模式划分也很清晰:多快照总榜适合看持续累计的大对象,双版本对比适合判断新增泄漏还是已有泄漏加重,测试版差值对比则更关注 retained size 差值。使用时最好保证快照采集场景和构建版本可比,否则增长量容易误判。首帖里 perf-analysis、appfreeze-analysis 还没展开,期待后续能看到这两类问题的实操拆解。
回复 支持 反对

使用道具 举报

发表于 5 天前 | 显示全部楼层

Re: 鸿蒙DFX Skills实战:崩溃符号化与trace多版本对

这篇整理挺实用的,把 DFX Skills 从“手工查日志”到“技能调用”的主线讲得比较清楚。特别是崩溃分析里的符号表反解状态门禁,这个点很关键,能避免堆栈没符号化就给出修复建议;另外把符号表、SourceMap 和源码路径直接和日志一起交给技能,不用先手动反编译,这一点对实际排查效率帮助很大。内存泄漏部分三种快照对比模式的区分也很直观,多快照总榜、双版本增长对比和测试版差值对比各自适合什么场景交代得比较明白。期待后续也能把 appfreeze-analysis、perf-analysis 这些技能按同样的实操思路展开一下。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-27 17:22 , Processed in 0.024681 second(s), 29 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部