1. HWASan报告基础从崩溃日志到问题定位第一次看到HWASan的崩溃报告时我盯着满屏的十六进制地址和内存标记完全摸不着头脑。这种体验就像拿到一份用外星语写的病历明明知道它指出了问题所在却看不懂具体含义。经过多次实战调试后我发现HWASan报告其实有固定的语法规则只要掌握关键信息提取方法就能快速定位内存问题。HWASanHardware Address Sanitizer是Android平台上的硬件辅助内存检测工具相比传统的ASan它通过ARMv8.5的MTEMemory Tagging Extension特性实现了更低开销的内存错误检测。当发生内存越界、释放后使用等问题时系统会生成包含以下核心要素的报告Access Error记录错误访问类型读/写、内存地址和标记Cause指出根本原因如use-after-freeMemory Information显示问题内存区域的状态堆栈轨迹包含从触发点到问题源头的调用链举个实际案例某次我在调试相机HAL层时遇到HWASan崩溃报告开头显示9569ERROR: HWAddressSanitizer: tag-mismatch on address 0x00433ae20045 READ of size 1 at 0x00433ae20045 tags: 5b/83 (ptr/mem)这段信息告诉我们在地址0x00433ae20045发生了1字节的读取操作指针标记(5b)与内存标记(83)不匹配。这种tag-mismatch就是HWASan检测到内存错误的主要表现形式。2. 解剖HWASan报告逐段解码实战2.1 Access Error深度解析Access Error是HWASan报告的第一现场记录。以这个典型错误为例READ of size 4 at 0x0042ffa3e008 tags: e5/00 (ptr/mem)各字段含义如下READ/WRITE表明是读取还是写入操作触发的错误size操作涉及的字节数对排查缓冲区溢出特别重要address发生错误的内存地址0x0042ffa3e008tags指针标记(e5)与内存标记(00)的对比这里有个实用技巧当看到内存标记为00时通常意味着访问了未分配或已释放的内存区域。我曾遇到一个案例某个结构体在释放后仍被访问报告显示内存标记为00结合后面的use-after-free提示很快就锁定了问题代码。2.2 Cause与Memory Information关联分析Cause部分直接指出问题本质常见类型包括use-after-free内存释放后继续使用heap-buffer-overflow堆缓冲区溢出stack tag-mismatch堆栈变量越界或返回后使用对应的Memory Information会详细描述内存状态。例如use-after-free错误会显示[0x0042ffa3e000,0x0042ffa3e020) is a small allocated heap chunk; size: 32 offset: 8 Cause: use-after-free 0x0042ffa3e008 is located 8 bytes inside of 16-byte region [0x0042ffa3e000,0x0042ffa3e010) freed by thread T1 here:这段信息揭示了三个关键点问题内存区域的大小32字节和偏移量8字节具体是16字节区域内的第8字节出问题内存释放的堆栈轨迹位置2.3 堆栈轨迹的符号化处理原始报告中的堆栈轨迹是这样的#0 0x7240450c68 (/system/lib64/vndk-sp-R/libcutils.so0x8c68) #1 0x723dffd490 (/vendor/lib64/sensors.ssc.so0x34490)要将其转换为可读信息需要用到hwasan_symbolize工具。具体操作步骤确保有带符号的二进制文件通常在out/target/product//symbols/目录使用以下命令进行符号化prebuilts/clang/host/linux-x86/clang-r450784d/bin/hwasan_symbolize \ out/target/product/rk3588/symbols/ crash.log symbolized.log符号化后的输出会显示具体的函数名和行号这对定位问题代码至关重要。3. 高级调试技巧特殊场景处理3.1 堆栈变量的tag-mismatch当遇到堆栈变量相关错误时报告会显示Cause: stack tag-mismatch Address 0x007d4d251e80 is located in stack of thread T64这类问题特别棘手因为堆栈帧信息需要额外处理。我常用的方法是使用adb pull获取设备的/proc//maps文件结合hwasan_symbolize的--objdump选项解析堆栈布局通过偏移量计算确定具体的变量位置3.2 历史记录耗尽的情况有时会遇到报告显示HWAddressSanitizer can not describe address in more detail.这表明HWASan的历史缓冲区已满。解决方法有两种增加历史记录大小在设备上设置adb shell echo history_size7 /data/local/tmp/hwasan.options adb shell export HWASAN_OPTIONS$(cat /data/local/tmp/hwasan.options)或者在编译时修改build/soong/cc/sanitize.go中的hwasanGlobalOptions3.3 嵌套bug的处理当看到nested bug in the same thread提示时这通常是HWASan运行时自身的bug。我的处理流程是记录完整的崩溃日志和设备信息尝试在最新代码库上复现如果确认是工具问题向AOSP提交bug报告4. 实战案例从崩溃到修复的全过程最近调试一个视频解码问题时遇到如下HWASan报告12345ERROR: HWAddressSanitizer: tag-mismatch on address 0x0078ab45c12d WRITE of size 16 at 0x0078ab45c12d tags: 34/00 (ptr/mem) [0x0078ab45c120,0x0078ab45c140) is a small allocated heap chunk; size: 32 offset: 13 Cause: heap-buffer-overflow 0x0078ab45c12d is located 13 bytes to the right of 20-byte region [0x0078ab45c110,0x0078ab45c124) allocated by thread T3 here: #0 0x72404ce554 (/system/lib64/libclang_rt.hwasan-aarch64-android.so0xd554) #1 0x723af23040 (/vendor/lib64/libomxil.so0x123040)通过符号化处理后发现是视频解码器中一个结构体数组越界访问。具体是分配了20字节的内存区域0x0078ab45c110-0x0078ab45c124但在0x0078ab45c12d处尝试写入16字节数据导致写入超出分配区域13字节修复方案是调整结构体大小并添加边界检查类似这样typedef struct { uint8_t data[16]; uint32_t flags; } DecoderBuffer; // 总大小20字节 // 使用时添加检查 if (offset sizeof(buffer-data) buffer_size) { ALOGE(Buffer overflow detected); return -EINVAL; }这个案例展示了如何通过HWASan报告中的内存区域信息和堆栈轨迹准确定位到代码中的缓冲区溢出问题。实际调试中建议结合git bisect等工具当HWASan报告出现时能快速定位引入问题的代码变更。