从 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,720(libapp.so 起始),小于 5,521,408(libbatt_cal_export.so 起始),因此:
崩溃发生在
lib/arm64-v8a/libapp.so
3.3 计算库内偏移
库内偏移 = pc地址十进制 - 该so起始偏移
= 4348268 - 1310720
= 3037548 (0x2E596C)
拿到库内偏移后,可进一步用 addr2line 或 llvm-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 工具链 | 进一步还原到源码行(可选) |