Android 如何正确使用符号表排查ndk so库崩溃

15 阅读1分钟

1、确认 ABI 匹配

崩溃发生在什么架构的手机上(arm64-v8a, x86_64 等),去对应的 obj/[ABI]/ 目录下找那个大的 .so 文件。

2、如何提取符号表

1.1 使用objcopy提取符号表

比如:Android/Sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin


$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objcopy \
 --only-keep-debug app.so \
 app.so.debug

# 或者用strip保留调试信息
$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip \
 --only-keep-debug app.so \
 -o app.so.debug

1.2 得到2个文件
app.so            # 发布版(剥离符号表,体积小)

app.so.debug      # 调试版(包含完整符号表,用于解析)

3、用 ndk-stack 定位

比如:./ndk/25.2.9519653/ndk-stack

将崩溃日志保存为 crash_log.txt

$NDK_HOME/ndk-stack -sym /项目路径/app/build/intermediates/cxx/Debug/[随机ID]/obj/x86_64 -dump crash_log.txt

结果: 它会将 pc 000000000001a4c4地址xxx 这种地址直接翻译成 函数名.cpp:行号

4、使用 addr2line 解析堆栈 (高版本可能去了)

比如:./ndk/22.0.7026061/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line

$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line 
    -e app.so                     # 指定so文件
    -f -C -p                      # 显示函数名、demangle、完整信息
    0x12345678                    # 崩溃地址

结果:

CrashFunction() at /src/main.cpp:108
CallerFunction() at /src/utils.cpp:42

5、针对 Release 版的处理,务必做备份。