Android使用Breadkpad抓取Native崩潰信息

Android使用Breadkpad抓取Native崩潰信息

簡介

在進行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文件
有了dump文件需要對其進行解析,使用minidump_stackwalk這個工具
這個工具AndroidStudio自帶的,在AndroidStudio的安裝目錄下bin\lldb\bin裏,將上述dump文件拷貝到這個目錄下(這裏我將dump文件重命名了)
crash文件
解析成功後打開crash文件,截取部分信息如下圖
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下載

感謝

感謝參考來源:https://www.jianshu.com/p/0bfe7800bdef

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章