Android使用Breadkpad抓取Native崩溃信息
- 简介
- 集成
- 抓取dump
- 分析dump信息
- 感谢
简介
在进行Android开发的时候,会发现JNI层的崩溃没有输出如同Java的详细堆栈信息,定位起来比较头疼。
Breakpad是Google开源的跨平台捕获Native崩溃的方案,从Crash的捕获到dump都提供了对应的工具,官方网站是Google breakpad。下面就简单介绍如何将其移植到Android中
集成
在Android studio中新建一个Model,将源码移植到cpp文件夹中。具体工程会在下面给出下载文件。
提供初始化函数给Java层调用,其中path是存放dump文件的文件名
private static native void initBreakpadNative(String path);
Java_com_sample_breakpad_BreakpadInit_initBreakpadNative(JNIEnv *env, jclass type, jstring path_) {
const char *path = env->GetStringUTFChars(path_, 0);
google_breakpad::MinidumpDescriptor descriptor(path);
static google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, NULL, true, -1);
env->ReleaseStringUTFChars(path_, path);
}
之后在主工程里新建一个cpp文件,模拟崩溃的情景
void Crash() {
volatile int *a = (int *) (NULL);
*a = 1;
}
抓取dump
运行主工程,点击按钮。程序崩溃,在path目录下找到dump文件,demo里是在sdcard/crashDump文件夹下面:
有了dump文件需要对其进行解析,使用minidump_stackwalk这个工具
这个工具AndroidStudio自带的,在AndroidStudio的安装目录下bin\lldb\bin里,将上述dump文件拷贝到这个目录下(这里我将dump文件重命名了)
解析成功后打开crash文件,截取部分信息如下图
里面有几个重要信息我们需要关注,可以看到崩溃原因
Crash reason: SIGSEGV(代表引用了一个无效的内存引用)
发生的崩溃的so文件和寄存器信息:libcrash-lib.so + 0x650
分析dump信息
有了具体的寄存器信息,我们进行符号解析,可以使用Android NDK中提供的addr2line来根据地址进行一个符号反解的过程,该工具在Android SDK目录下可以找到。工具链的选择要根据.so的类型来决定,看解析后的文件,有显示CPU信息。
如果是arm-64位的so,解析是需要使用aarch64-linux-android-4.9下的工具链
如果是arm-32位的so,解析是需要使用arm-linux-androideabi-4.9下的工具链。
如果是x86-64位的so,解析是需要使用x86_64-4.9下的工具链。
如果是x86-32位的so,解析是需要使用x86-4.9下的工具链。
这里,因为CPU信息是arm-64,所以选择x86-4.9下的工具链。我们将项目中build目录下的arm-64对应的libcrash-lib.so(app\build\intermediates\transforms\mergeJniLibs\debug\0\lib\arm64-v8a\libcrash-lib.so)拷贝到arm-64下的工具链目录(~l\Android\Sdk\ndk-bundle\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin)中,然后执行如下命令:
可以很清晰的看到崩溃发生在crash.cpp文件的第10行!
至此分析完成。
DEMO下载