1.BreakPad简介
Google breakpad是一个跨平台的崩溃转储和分析框架和工具集合。
Breakpad由三个主要组件:
- client,以library的形式内置在你的应用中,当崩溃发生时写 minidump文件
- symbol dumper, 读取由编译器生成的调试信息(debugging information),并生成 symbol file
- processor, 读取 minidump文件 和 symbol file,生成可读的c/c++ Stack trace.
简单来说就是一个生成 minidump,一个生成symbol file,然后将其合并处理成可读的Stack trace。
- MiniDump文件格式说明
- Symbols文件格式
2.模拟崩溃
2.1 获取breakpad代码
点击https://chromium.googlesource.com/breakpad/breakpad这个链接,选择左侧的master,下载tgz文件
有些文章说会缺少 linux_syscall_support.h 文件,但是本人实践下来并没有缺少,可能版本更新加进去了,如果没有,可自行查找并添加
2.2 编译
进入源代码根目录,执行以下命令
./configure && make
编译完以后会在生成两个可执行文件,分别是src/processor/minidump_stackwalk和src/tools/linux/dump_syms/dump_syms
2.3 添加环境变量(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 # 此处需要注意的是,路径中不要指定具体执行文件名,否则会报找不到相关命令,例如${BREAKPAD_HOME}/src/tools/linux/dump_syms/dump_syms,这样执行dump_syms命令会找不到
### 更新环境变量
source ~/.zshrc
2.4 下载官方Demo并生成so文件和dmp文件
官方Demo的地址在https://github.com/AndroidAdvanceWithGeektime/Chapter01.
一开始本人在编译的时候用的是ndk20的,发现提示C和C++编译器没有设置.经过好几次反复才发现原来是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 是当一个进程执行了一个无效的内存引用,或发生段错误时发送给它的信号。
Thread 0 (crashed) //crash 发生时候的线程
0 libnative-lib.so + 0x325f4 //发生 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崩溃的原因
参考文献
https://www.jianshu.com/p/295ebf42b05b
https://blog.csdn.net/fengyulinde/article/details/81707346
https://www.jianshu.com/p/1687c92efb89