一、需求分析
so 的崩潰並不像 Java 代碼那么好定位,我們通常看到的就只是 so 中的一大段崩潰的堆棧信息。那么我們怎么通過這個堆棧信息來定位我們的問題呢?
二、addr2line
1. 介紹
Addr2line 工具(它是標准的 GNU Binutils 中的一部分)是一個可以將指令的地址和可執行映像轉換成文件名、函數名和源代碼行數的工具。
一般適用於 debug 版本或帶有 symbol 信息的庫。
2. 工具位置
我們下載的 NDK 里面已經默認有了這個工具,對應的路徑如下,其中 .. 表示你的 NDK 安裝的路徑(每個人的可能都不一樣)
Windows:
32位:..\ndk-bundle\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-addr2line.exe
64位:..\ndk-bundle\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin\aarch64-linux-android-addr2line.exe
Linux:
32位:../android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line
64位:../android-ndk-r16b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-addr2line
當然我們也可以把這個路徑配置到環境變量中去。
3. 指令釋義
4. 使用示例
5. 實際應用
例如出現了如下崩潰:
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4d42d8b4 r0 ead025fc r1 ead025f0 r2 ead025fd r3 4d42d8a4 r4 efba899c r5 ead025fc r6 ead0263c r7 efba8984 r8 ead00000 r9 ead00000 sl ead025fc fp 00000001 ip 00000000 sp ee5ff348 lr 0007ffff pc efb5e15e cpsr 800f0030 backtrace: #00 pc 0005915e /system/lib/libc.so (arena_dalloc_bin_locked_impl+345) #01 pc 00058ffd /system/lib/libc.so (je_arena_dalloc_bin_junked_locked+12) #02 pc 0007ae27 /system/lib/libc.so (je_tcache_bin_flush_small+366) #03 pc 0007ac5b /system/lib/libc.so (je_tcache_event_hard+58) #04 pc 0006a505 /system/lib/libc.so (je_malloc+636) #05 pc 00339c7f /vendor/lib/libstfaceunlock.so #06 pc 00282064 /vendor/lib/libstfaceunlock.so #07 pc 001fc094 /vendor/lib/libstfaceunlock.so #08 pc 002056b0 /vendor/lib/libstfaceunlock.so #09 pc 002809d8 /vendor/lib/libstfaceunlock.so #10 pc 00103f58 /vendor/lib/libstfaceunlock.so #11 pc 00105398 /vendor/lib/libstfaceunlock.so #12 pc 001062c4 /vendor/lib/libstfaceunlock.so #13 pc 000a4f14 /vendor/lib/libstfaceunlock.so #14 pc 0007957c /vendor/lib/libstfaceunlock.so #15 pc 00023d2c /vendor/lib/libstfaceunlock.so (cv_face_create_tracker+424)
我們就可以把每個段地址翻譯成具體的代碼:
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4d42d8b4 r0 ead025fc r1 ead025f0 r2 ead025fd r3 4d42d8a4 r4 efba899c r5 ead025fc r6 ead0263c r7 efba8984 r8 ead00000 r9 ead00000 sl ead025fc fp 00000001 ip 00000000 sp ee5ff348 lr 0007ffff pc efb5e15e cpsr 800f0030 backtrace: #00 pc 0005915e /system/lib/libc.so (arena_dalloc_bin_locked_impl+345) #01 pc 00058ffd /system/lib/libc.so (je_arena_dalloc_bin_junked_locked+12) #02 pc 0007ae27 /system/lib/libc.so (je_tcache_bin_flush_small+366) #03 pc 0007ac5b /system/lib/libc.so (je_tcache_event_hard+58) #04 pc 0006a505 /system/lib/libc.so (je_malloc+636) #05 pc 00339c7f /vendor/lib/libstfaceunlock.so --> /usr/local/google/buildbot/src/android/master-ndk/toolchain/gcc/gcc-4.9/libstdc++-v3/libsupc++/new_op.cc:56 #06 pc 00282064 /vendor/lib/libstfaceunlock.so --> google::protobuf::internal::StringTypeHandlerBase::New() #07 pc 001fc094 /vendor/lib/libstfaceunlock.so --> caffe::LayerParameter::MergePartialFromCodedStream(google::protobuf::io::CodedInputStream*) #08 pc 002056b0 /vendor/lib/libstfaceunlock.so --> caffe::NetParameter::MergePartialFromCodedStream(google::protobuf::io::CodedInputStream*) #09 pc 002809d8 /vendor/lib/libstfaceunlock.so --> google::protobuf::MessageLite::ParseFromCodedStream(google::protobuf::io::CodedInputStream*) #10 pc 00103f58 /vendor/lib/libstfaceunlock.so --> ReadProtoFromBinaryResource(protector::ModelResource&, google::protobuf::MessageLite*) #11 pc 00105398 /vendor/lib/libstfaceunlock.so --> protector::CaffeModel::Init(protector::TarModelResource&, std::string const&, protector::NetConfig, bool #12 pc 001062c4 /vendor/lib/libstfaceunlock.so --> protector::ModelLoader::LoadByName(std::string const&, bool) const #13 pc 000a4f14 /vendor/lib/libstfaceunlock.so --> stsdk::detection::DetectorHunter::Init(protector::ModelLoader&) #14 pc 0007957c /vendor/lib/libstfaceunlock.so --> __appProtect_cv_common_detection_hunter_create_start #15 pc 00023d2c /vendor/lib/libstfaceunlock.so (cv_face_create_tracker+424)
三、objdump
1. 介紹
objdump 是 gcc 工具,用來查看編譯后目標文件的組成。
2. 工具位置
我們下載的 NDK 里面同樣默認有了這個工具,對應的路徑如下,其中 .. 表示你的 NDK 安裝的路徑(每個人的可能都不一樣)
Windows:
32位:..\ndk-bundle\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-objdump.exe
64位:..\ndk-bundle\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin\aarch64-linux-android-objdump.exe
Linux:
32位:../android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-objdump
64位:../android-ndk-r16b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-objdump
當然我們也可以把這個路徑配置到環境變量中去。
3. 指令釋義
4. 使用示例
通常我們會把輸出重定向到一個文本文件中去,使用語法如下:
arm-linux-androideabi-objdump -d 庫文件 > 輸出文件
打開文件,查看匯編執行順序,找到 23098 地址段
通過 backtrace 地址里的匯編段和偏移量在上面的匯編順序里找到對應匯編命令
這里的方法名不容易看懂,可以使用 c++filt 命令找到實際的代碼段可以更方面定位代碼
然后找到具體的代碼
判斷是在 gen_statistics 函數之前,所以增加非空判斷
其它:
————————————————
版權聲明:本文為CSDN博主「阿飛__」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/afei__/article/details/81181827