如何从仅显示APK的Backtrace中获取JNI代码的函数行信息
我获取到的Backtrace如下:
D callstack-test: #00 pc 000001c5 /system_ext/app/MyService/MyService.apk (offset 0x59c9000)
经测试,该代码属于编译为libjni.so的JNI代码,我预期的Backtrace格式应为:
D callstack-test: #00 pc 0004f049 /system_ext/app/MyService/MyService.apk!libjni.so (offset 0x59e8000)
但实际结果仅显示APK名称,未包含库名,导致无法使用addr2line获取函数行信息。
根据谷歌文档说明:
Frames #00–#03 are from native JNI code that was stored uncompressed in the APK to save disk space rather than being extracted into a separate .so file.
现咨询:当Backtrace仅显示APK名称时,如何获取JNI代码对应的函数行信息?
解决方法
提取APK内的JNI库文件
由于JNI库未压缩内嵌在APK中,可通过解压工具直接提取目标库。比如用unzip命令:unzip MyService.apk lib/arm64-v8a/libjni.so -d extracted_libs注意替换命令中的架构路径(如
arm64-v8a、armeabi-v7a等)为你的实际目标架构。计算正确的解析地址
Backtrace中的pc值是相对于APK加载基址的偏移,需要转换为相对于libjni.so基址的地址:
正确地址 =pc值+APK的offset-libjni.so在APK中的加载基址偏移
其中libjni.so的加载基址偏移可通过readelf工具查看:readelf -l extracted_libs/lib/arm64-v8a/libjni.so | grep LOAD取第一个LOAD段的
VirtAddr(虚拟地址)作为库的基址,再结合APK的offset计算出最终地址。使用
addr2line解析行号
用对应架构的addr2line工具(如aarch64-linux-android-addr2line)执行解析:aarch64-linux-android-addr2line -f -C -e extracted_libs/lib/arm64-v8a/libjni.so [计算后的十六进制地址]参数说明:
-f显示函数名,-C还原C++符号名,-e指定目标库文件。可选:借助Android Studio工具简化流程
将APK和对应的符号文件(.symbols)导入Android Studio的Profiler或Debug面板,IDE会自动识别内嵌库并解析Backtrace,无需手动计算地址。
内容的提问来源于stack exchange,提问作者hi_stackoverflow

