1.BreakPad簡介
Google breakpad是一個跨平臺的崩潰轉儲和分析框架和工具集合。
Breakpad由三個主要組件:
- client,以library的形式內置在你的應用中,當崩潰發(fā)生時寫 minidump文件
- symbol dumper, 讀取由編譯器生成的調試信息(debugging information),并生成 symbol file
- processor, 讀取 minidump文件 和 symbol file,生成可讀的c/c++ Stack trace.
簡單來說就是一個生成 minidump,一個生成symbol file,然后將其合并處理成可讀的Stack trace。
2.模擬崩潰
2.1 獲取breakpad代碼
點擊https://chromium.googlesource.com/breakpad/breakpad這個鏈接,選擇左側的master,下載tgz文件
有些文章說會缺少 linux_syscall_support.h 文件,但是本人實踐下來并沒有缺少,可能版本更新加進去了,如果沒有,可自行查找并添加
2.2 編譯
進入源代碼根目錄,執(zhí)行以下命令
./configure && make
編譯完以后會在生成兩個可執(zhí)行文件,分別是src/processor/minidump_stackwalk和src/tools/linux/dump_syms/dump_syms
2.3 添加環(huán)境變量(MAC)
vim ~/.zshrc
### 在.zshrc文件的末尾添加剛剛生成的文件的路徑
export BREAKPAD_HOME=/Users/XXX/Documents/breakpad-refs_heads_master # 這里需要替換自己的breakpad路徑
export PATH=$PATH:${BREAKPAD_HOME}/src/processor:${BREAKPAD_HOME}/src/tools/linux/dump_syms # 此處需要注意的是,路徑中不要指定具體執(zhí)行文件名,否則會報找不到相關命令,例如${BREAKPAD_HOME}/src/tools/linux/dump_syms/dump_syms,這樣執(zhí)行dump_syms命令會找不到
### 更新環(huán)境變量
source ~/.zshrc
2.4 下載官方Demo并生成so文件和dmp文件
官方Demo的地址在https://github.com/AndroidAdvanceWithGeektime/Chapter01.
一開始本人在編譯的時候用的是ndk20的,發(fā)現提示C和C++編譯器沒有設置.經過好幾次反復才發(fā)現原來是ndk版本太高,導致了用的是clang去編譯的,然后就一直抱那個錯.后來降低成ndk16就通過了.
還有要注意,用ndk20編譯以后,會在libbreakpad模塊里面生成externalNativeBuild目錄,里面的內容在更換ndk的時候是不會自動更新的,所以需要手動刪除,這個問題我也是找了很久.一開始還以為是代碼缺了什么配置
2.5 分析dmp文件并生成log日志
minidump_stackwalk /Users/xxx/Desktop/3c22839a-812d-4901-983278b1-de602110.dmp > /Users/xxx/Desktop/1.txt
接下來查看1.txt.得出日志結果過長,大體如下:
Operating system: Android
0.0.0 Linux 3.10.90-g01f8576 #1 SMP PREEMPT Tue Oct 25 05:18:00 CST 2016 aarch64
CPU: arm64
8 CPUs
GPU: UNKNOWN
Crash reason: SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: not available
Thread 0 (crashed)
0 libbreakpad-native.so + 0x325f4
x0 = 0x0000000000000000 x1 = 0x0000000000000001
x2 = 0x0000007f74e64240 x3 = 0x0000000000570000
根據文章Android 平臺 Native 代碼的崩潰捕獲機制及實現 的介紹,我們可知“Crash reason: SIGSEGV /SEGV_MAPERR”代表哪種類型的錯誤:
SIGSEGV 是當一個進程執(zhí)行了一個無效的內存引用,或發(fā)生段錯誤時發(fā)送給它的信號。
Thread 0 (crashed) //crash 發(fā)生時候的線程
0 libnative-lib.so + 0x325f4 //發(fā)生 crash 的位置和寄存器信息
有了具體的寄存器信息,我們進行符號解析(注意CPU是arm64)可以使用 ndk 中提供的addr2line來根據地址進行一個符號反解的過程,該工具在
$NDK_HOME/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line
進入addr2line所在目錄輸入(注意地址arm64用aarch64下的工具鏈解析arm64-v8a下的so文件)
aarch64-linux-android-addr2line -f -C -e /Users/xxx/Documents/AdvanAndroid/BreakpadDemo/app/build/intermediates/transforms/mergeJniLibs/debug/0/lib/arm64-v8a/libbreakpad-native.so 0x325f4
我自己在輸入的時候會提示arm-linux-androideabi-addr2line找不到,是因為沒有在PATH里面配置,所以我就輸入的整個的地址.輸出如下
Java_com_example_libbreakpad_BreakPadManager_testBreak
/Users/liuxiaojie/Documents/AdvanAndroid/BreakpadDemo/libbreakpad/.externalNativeBuild/cmake/debug/arm64-v8a/../../../../src/main/cpp/native-lib.cpp:34
之前在ndk切換那里換了個工程,具體地址https://github.com/sunnybird/AdvanAndroid
至此,解析出了native崩潰的原因
參考文獻
http://www.lxweimin.com/p/295ebf42b05b
https://blog.csdn.net/fengyulinde/article/details/81707346
http://www.lxweimin.com/p/1687c92efb89