写点什么

踩内存问题一键定位:HWASAN + BinXO 无源码内存检测实战指南

  • 2026-08-03
    北京
  • 本文字数:4338 字

    阅读完需:约 14 分钟

本原创文章帖发布在华为开发者联盟社区,欢迎开发者前往访问评论交流,更多与该内容相关讨论,请点击原帖查看:踩内存问题一键定位:HWASAN + BinXO无源码内存检测实战指南-华为开发者话题 | 华为开发者联盟

适用版本:DevEco Studio 6.1.0.830 及以上版本

【背景与收益】

什么是 HWASAN?

HWASAN(Hardware-Assisted Address Sanitizer,硬件辅助地址消毒器)是 Clang 开源社区推出的一种内存检测工具,主要用于开发态的内存问题检测。它利用 ARMv8.5 及以上芯片的 MTE(Memory Tagging Extension)硬件特性,在内存访问时通过 tag 比对快速发现踩内存问题。

注意:HWASAN 定位为开发态检测工具,不建议在发布版本中使能。其主要用于开发阶段和测试阶段快速发现内存问题,提升应用稳定性。

在鸿蒙应用开发中,踩内存(Memory Corruption) 是 C++ Native 层最常见的稳定性问题之一。踩内存问题包括堆缓冲区溢出(heap-buffer-overflow)、堆内存释放后使用(heap-use-after-free)、双重释放(double-free)等,这些问题往往导致应用随机崩溃,且由于崩溃现场与根因脱节,定位极其困难。

为什么需要 HWASAN + BinXO?

传统 HWASAN(Hardware-Assisted Address Sanitizer)需要开发者基于源码重新编译,面临以下痛点:

HWASAN + BinXO 方案的核心收益

• ✅ 无源码插桩:基于 BinXO 二进制编译优化技术,对已编译的 .so 动态库直接进行 HWASAN 插桩,无需源码

• ✅ 一键使能:DevEco Studio 6.1.0.830+ 版本支持 IDE 界面勾选,无需手动添加编译参数

• ✅ 全面覆盖:同时开启源码编译插桩 + 无源码二进制插桩,检测覆盖率大幅提升

• ✅ 快速定位:IDE 集成堆栈跟踪分析工具,直接定位报错栈和申请栈

【技术原理】

BinXO 二进制插桩原理

BinXO 是华为自研的轻量化二进制编译优化器,可以在二进制层级进行优化和运行时信息采集。基于 BinXO 的 SourceLess HWASAN 方案,在汇编层级对已编译的 .so 动态库进行 HWASAN 插桩,实现无源码场景下的内存访问检测。

核心流程如下:

  1. 访存指令插桩:在汇编层级识别所有 load/store 访存指令,插入 tag 检查逻辑

  • 保存部分寄存器于栈上,用于后续计算

    提取访问地址 addr

    计算对应 tag(基于地址高位 / shadow memory)

    与 shadow memory 中存储的 tag 对比

    不匹配则触发异常(report + abort),匹配则恢复相关寄存器继续运行

2. 堆内存插桩:识别 malloc/free 函数的调用点,动态插入 tag 分配和回收代码

  • 分配内存时自动添加 tag

    释放内存时自动清除 tag 信息

    为返回地址高位打上 tag

3. 运行时检测:每次内存访问时,检查地址高位 tag 与 shadow memory 中的 tag 是否一致,不匹配则触发异常

支持检测的内存问题类型

注意:BinXO 二进制插桩当前主要支持堆类内存检测,栈类检测需使用源码编译插桩。

可检测的访存指令类型

BinXO 支持以下访存指令的检测:

标量指令:

  • A64_LDP_STP

    A64_LDR_STR_IMMED

    A64_LDR_STR_REG

    A64_LDR_STR_UNSIGNED_IMMED

SIMD 指令:

  • A64_LDX_STX_MULTIPLE

    A64_LDX_STX_MULTIPLE_POST

    A64_LDX_STX_SINGLE

    A64_LDX_STX_SINGLE_POST

【典型使用场景】

以下场景推荐使用 HWASAN + BinXO 进行内存问题检测:

1. C++ Native 占比高的应用:如音视频处理、游戏引擎、图像处理等大量使用 C++ 的应用

2. 集成第三方 SDK 的应用:第三方 SDK 通常只有编译好的 .so 文件,无源码可用

3. 线上踩内存问题频发:天网版本检测到大量踩内存问题,需要快速定位根因

4. 跨模块内存问题排查:多个模块间内存交互复杂,需要全量插桩检测

未使用 HWASAN + BinXO 时,开发者可能遇到以下问题:

【详细操作指南】

方式一:IDE 界面配置(推荐)

适用场景:调试/本地场景,DevEco Studio 6.1.0.830 及以上版本

步骤 1:创建 Native 工程

在 DevEco Studio 中创建包含 C++ Native 的代码工程。

步骤 2:开启 HWASAN

1. 点击菜单 Run > Edit Configurations

2. 进入 Diagnostics 选项卡

3. 勾选 Hardware-Assisted Address Sanitizer,开启 C++ 源码编译插桩检测

步骤 3:开启 BinXO(无源码二进制插桩)

从 DevEco Studio 6.1.0.830 版本开始,在同一界面勾选 BinXO check,开启无源码 .so 文件的 HWASAN 插桩检测。

步骤 4:构建 HAP 包

点击构建按钮,DevEco Studio 将自动完成 HWASAN 源码插桩和 BinXO 二进制插桩,生成检测包。

步骤 5:推包并运行测试

1. 将构建的 HAP 包推送到设备

2. 关闭应用 freeze 检测(依赖 HAP 包指定为 DEBUG 包):

aa attach -b <bundleName>
复制代码

 3. 启动应用,执行相关用例

步骤 6:获取 HWASAN 日志

IDE 将自动收集 HWASAN 日志,可在日志视图中查看。

 步骤 7:堆栈跟踪分析

1. 将 HWASAN 日志拷贝到 IDE 分析工具的左上角区域

2. 勾选 "解读堆栈跟踪"

3. 导入符号表信息

4. 点击 "开始分析"

5. 观测右下角的 报错栈 和 申请栈,直接定位问题

方式二:配置文件

适用场景:需要持久化配置或流水线构建

系统级配置

在工程目录下的 AppScope/app.json5 文件中添加 HWASAN 配置开关:

{  "app": {    "hwasanEnabled": true  }}
复制代码

模块级配置

在模块级 build-profile.json5 中添加构建参数:

{  "buildOption": {    "externalNativeOptions": {      "arguments": [        "-DOHOS_ENABLE_HWASAN=ON",        "-DOHOS_ENABLE_BINXO=ON"      ]    }  }}
复制代码

版本说明

• DevEco Studio 6.1.0.830 以下版本:仅配置 -DOHOS_ENABLE_HWASAN=ON(仅源码插桩)

• DevEco Studio 6.1.0.830 及以上版本:同时配置两个参数,开启源码 + 无源码检测

方式三:命令行参数

适用场景:流水线/CI 构建

# DevEco Studio 6.1.0.830 及以上版本hvigorw assembleHar -p ohos-enable-hwasan=true -p ohos-enable-binxo=true# DevEco Studio 6.1.0.830 以下版本(仅源码插桩)hvigorw assembleHar -p ohos-enable-hwasan=true
复制代码

可选配置:排除特定 SO

部分 .so 由于技术原理限制不支持 BinXO 插桩,需要配置忽略以避免构建报错:

{  "buildOption": {    "nativeLib": {      "excludeSoFromBinXO": ["**/liblibrary.so"]    }  }}
复制代码

支持正则匹配,可在工程级或模块级 build-profile.json5 中配置。

【真实案例分析】

XXXX App 案例

XXXX App 使用 SourceLess HWASAN 后,帮助开发者发现了 libxxxa.so 中的访存问题。

原始日志:

Reason:HWASAN==appspawn==14177==ERROR: HWAddressSanitizer: allocation-tail-overwritten; heap object [0x00130004a600,0x00130004aa51) of size 1105Stack of invalid access unknown. Issue detected at deallocation time.deallocated here:#0 0x5ae366b394 (/system/asan/lib64/libclang_rt.hwasan.so+0x2b394) (BuildId: ace54fff777e92f7758544f77b2b931f9f1c7b55)#1 0x651af0b720 (/data/storage/el1/bundle/libs/arm64/libtocks.so+0xb720) (BuildId: 85c301da032d17f70c0e1d6bf4de932b58317447)#2 0x5aee4e6c84 (/system/asan/lib64/platformsdk/libace_napi.z.so+0x66c84) (BuildId: ccd61d3dec598e77f88de9fb142e4095)#3 0x7e86a5b5cc (/system/asan/lib64/module/arkcompiler/stub.an+0x5c85cc)#4 0x7e864a3320 (/system/asan/lib64/module/arkcompiler/stub.an+0x10320)#5 0x275bdd79f4 ([anon:ArkTS Heapsemi space]+0x179f4)allocated here:#0 0x5ae366b0e0 (/system/asan/lib64/libclang_rt.hwasan.so+0x2b0e0) (BuildId: ace54fff777e92f7758544f77b2b931f9f1c7b55)#1 0x651af12d54 (/data/storage/el1/bundle/libs/arm64/libtocks.so+0x12d54) (BuildId: 85c301da032d17f70c0e1d6bf4de932b58317447)#2 0x651af0b6b0 (/data/storage/el1/bundle/libs/arm64/libtocks.so+0xb6b0) (BuildId: 85c301da032d17f70c0e1d6bf4de932b58317447)#3 0x5aee4e6c84 (/system/asan/lib64/platformsdk/libace_napi.z.so+0x66c84) (BuildId: ccd61d3dec598e77f88de9fb142e4095)#4 0x7e86a5b5cc (/system/asan/lib64/module/arkcompiler/stub.an+0x5c85cc)#5 0x7e864a3320 (/system/asan/lib64/module/arkcompiler/stub.an+0x10320)#6 0x275bdd79f4 ([anon:ArkTS Heapsemi space]+0x179f4)
复制代码

从日志可以看出,堆内存[0x00130004a600,0x00130004aa51) 出现了越界访问。该块内存的申请的代码在 libtocks.so+0x12d54 的位置。

反汇编该 so,通过汇编可以看出,在 0x12d6c 的位置有一个越界访问。 如果开发者有源码, 可以更快的发现内存的问题。

检测效果

  • 无需获取第三方库源码

    直接定位到具体 .so 文件中的问题

    大幅缩短问题定位周期

【常见问题解答】

Q1:BinXO 二进制插桩有哪些规格限制?

Q2:HWASAN 使用 ARM64 地址高 8 位,会与应用冲突吗?

HWASAN 使用了 ARM64 虚拟地址的高 8 位作为 tag 存储。如果应用中也有动态库使用了高 8 位,会产生冲突导致误报。

规避方案

1. 优先方案:该动态库针对 HWASAN 版本单独出一个二进制,关闭对地址高 8 位的使用

2. 次选方案:关闭该 .so 的 HWASAN/BinXO 插桩(影响:该 .so 的踩内存故障无法检测)

Q3:源码编译插桩遇到 `fixup not sufficiently aligned` 报错怎么办?

根因:HWASAN 源码编译要求栈变量 16 字节对齐,报错文件中有内联汇编开辟了未 16 字节对齐的栈变量,或定义了 pack 强制未 16 字节对齐的临时变量。

解决方案

• 修改为 16 字节对齐

• 或在问题函数定义右侧添加修饰符:__attribute__((no_sanitize("hwaddress"))),该函数不进行 HWASAN 编译插桩

Q4:BinXO 插桩报错如何处理?

【参考文档】

• HWASAN 原理介绍:https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-stability-address-sanitizer-principle

• HWASAN 使用指南:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-hwasan#section31022911513

• HWASAN 最佳实践:https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-stability-hwasan-detection

• Clang HWASAN 开源文档:https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html

总结:HWASAN + BinXO 方案通过二进制插桩技术,实现了无源码场景下的内存访问检测,大幅降低了踩内存问题的定位门槛。开发者只需在 DevEco Studio 中勾选两个选项,即可开启全面的内存检测能力,结合 IDE 集成的堆栈跟踪分析工具,能够快速定位内存问题根因,提升应用稳定性。


🔗 官网开发者学堂视频:https://developer.huawei.com/consumer/cn/training/result?type2List=201783644516849879&orderBy=1&courseType=5

🔗 社区 DFX 专题文章: https://developer.huawei.com/consumer/cn/forum/subject/2101218731402391001

【扫码加入 HarmonyOS DFX 技术交流群】