从 tombstone 定位 APK 中崩溃的 .so 文件

在 Android 原生或 Flutter 项目中,当 tombstone 日志只给出一个相对于 base.apk 的 pc 地址时,需要先知道各 .so 在 APK 中的起始偏移,才能判断崩溃落在哪个库里。本文记录完整的排查流程。

前置条件

  • 已安装 Android SDK,build-tools 版本 ≥ 35.0.0
  • 设备已开启 USB 调试,adb 可正常连接
  • 手头有崩溃设备的 tombstone 日志

步骤 1:从设备拉取 base.apk

adb pull /data/app/com.xxxxx-YFgvdgMjcqZOXepu4c9bAg==/base.apk

com.xxxxx 替换为目标应用的包名;哈希后缀可通过 adb shell pm path <package> 获取。


步骤 2:用 zipalign 列出 .so 文件的偏移量

"E:\Android\Sdk\build-tools\35.0.0\zipalign.exe" -c -v 4 "path\to\base.apk" | findstr "\.so"

macOS / Linux 等价命令:

zipalign -c -v 4 base.apk | grep "\.so"

示例输出

1310720   lib/arm64-v8a/libapp.so (OK)
5521408   lib/arm64-v8a/libbatt_cal_export.so (OK)
5537792   lib/arm64-v8a/libdatastore_shared_counter.so (OK)
5554176   lib/arm64-v8a/libflutter.so (OK)
16613376  lib/armeabi-v7a/libapp.so (OK)
21184512  lib/armeabi-v7a/libbatt_cal_export.so (OK)
21200896  lib/armeabi-v7a/libdatastore_shared_counter.so (OK)
21217280  lib/armeabi-v7a/libflutter.so (OK)
29065216  lib/x86/libdatastore_shared_counter.so (OK)
29081600  lib/x86_64/libapp.so (OK)
33357824  lib/x86_64/libdatastore_shared_counter.so (OK)
33374208  lib/x86_64/libflutter.so (OK)

每行格式为 <十进制偏移量> <APK 内路径> (OK)(OK) 表示该 .so 已按 4 字节对齐,可被系统直接 mmap。


步骤 3:将 tombstone pc 地址转为十进制并对比偏移量表

tombstone 示例行:

#00 pc 0042596c  /data/app/com.xxxxx-U3noKoo2eh0ULAWD1_1BJA==/base.apk

3.1 十六进制 → 十进制

0x0042596c = 4348268

可用任意计算器或命令行完成:

# bash
printf '%d\n' 0x0042596c
# 输出:4348268
# PowerShell
[Convert]::ToInt64("0042596c", 16)
# 输出:4348268

3.2 对比偏移量表(以 arm64-v8a 为例)

起始偏移 文件
1,310,720 lib/arm64-v8a/libapp.so
5,521,408 lib/arm64-v8a/libbatt_cal_export.so
5,537,792 lib/arm64-v8a/libdatastore_shared_counter.so
5,554,176 lib/arm64-v8a/libflutter.so

4,348,268 大于 1,310,720libapp.so 起始),小于 5,521,408(libbatt_cal_export.so 起始),因此:

崩溃发生在 lib/arm64-v8a/libapp.so

3.3 计算库内偏移

库内偏移 = pc地址十进制 - 该so起始偏移
         = 4348268 - 1310720
         = 3037548  (0x2E596C)

拿到库内偏移后,可进一步用 addr2linellvm-symbolizer 还原到具体的源码行:

llvm-symbolizer --obj=libapp.so --demangle 0x2E596C

小结

步骤 工具 目的
adb pull adb 获取设备上的 APK
zipalign -c -v zipalign 列出各 .so 在 APK 中的起始偏移
进制转换 计算器 / shell 将 tombstone pc 地址转为十进制
区间比较 手动 / 脚本 确定 pc 落在哪个 .so 的地址范围内
addr2line / llvm-symbolizer NDK 工具链 进一步还原到源码行(可选)