google breakpad native crash分析工具
一. 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文件格式
minidump文件格式是由微軟開發的用于崩潰上傳,它包括:
- 當dump生成時進程中一系列executable和shared libraries, 包括這些文件的文件名和版本號。
- 進程中的線程列表,對于每個線程,minidump包含它在寄存器中的狀態,線程的stack memory內容。這些數據都是未解析的字節流,Breakpad client通常沒有調試信息(debugging information)能生成函數名,行號,甚至無法確定stack frame的邊界。
- 其他收集關于系統的信息,如:處理器,操作系統高版本,dump的原因等等。
breakpad在所有平臺上(windows/linux等)都統一使用minidump文件格式,而不使用core files,原因是因為:
- core files可能很大,而minidump比較小。
- core files文檔不全
- 很難說服windows機器去生成core files,但可以說服其他機器來生成minidump文件。
- breakpad只支持一種統一的格式會比較簡單,而不是同時支持多種格式。
什么是core files?core files是unit系統上程序崩潰時生成的文件。
參見:http://www.jianshu.com/p/8e1352a9638f
三. Symbols文件格式
symbols文件是基于純文本的,每一行一條記錄,每條記錄中的字段以一個空格作為分隔符,每條記錄的第一個字段表示這一行是什么類型的記錄。
記錄類型:
- 模塊記錄:
MODULEoperatingsystem architecture id name - 文件記錄:
FILEnumber name - 函數記錄:
FUNCaddress size parameter_size name - 行號記錄:address size line filenum
- PUBLIC記錄:
PUBLICaddress parameter_size name STACK WINSTACK CFI
參見:https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
四. 不同平臺的實現原理
默認情況下,當崩潰時breakpad會生成一個minidump文件,在不同平臺上的實現機制不一樣:
- 在windows平臺上,使用微軟提供的
SetUnhandledExceptionFilter()方法來實現。 - 在OS X平臺上,通過創建一個線程來監聽
Mach Exception port來實現。 - 在Linux平臺上,通過設置一個信號處理器來監聽
SIGILLSIGSEGV等異常信號。
當minidump被生成后,在不同平臺上也使用不同的機制來上傳crash dump文件。
參見:Windows SetUnhandledExceptionFilter參見:Mac OS X Exception handling參見:Catching Exceptions and Printing Stack Traces for C on Windows, Linux, & Mac
五. 異常處理機制
提供兩種不同的異常處理機制:
- 同進程(in-process)
- 跨進程(out-precess)
因為在崩潰的進程寫minidump文件是不安全的,所以三個平臺(windows、linux、mac os)都提供跨進程的異常處理機制。
六. 在Linux平臺使用breakpad
這里因為要研究Android上使用breakpad,所有主要研究linux平臺,windows和mac平臺的使用方法請自行參考文檔。
6.1 構建Breakpad庫
breakpad提供自動構建工具來構建linux client庫和processor庫。
在breakpad源碼目錄下通過運行命令:
./configure
make
將自動生成 src/client/linux/libbreakpad_client.a 文件, 其包含了在你的應用中生成minidumps文件的必要代碼。
6.2 在你的應用中使用Breakpad
首先配置build precess來link剛生成的 libbreakpad_client.a 文件。
然后設置 include paths 來 包含 google-breakpad 目錄下的 src 目錄。
接下來include頭文件:
#include "client/linux/handler/exception_handler.h"
現在你就可以初始化 ExceptionHandler 對象,初始化的時候需要提供一個用于寫minidump文件的目錄,以及一個回調函數用于在minidump文件寫完以后調用。
int main(int argc, char* argv[]) {// 初始化ExceptionHandlergoogle_breakpad::MinidumpDescriptor descriptor("/tmp"); // minidump文件寫入到的目錄google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);crash();return 0;
}// 寫完minidump后的回調函數
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,void* context, bool succeeded) {printf("Dump path: %s\n", descriptor.path());return succeeded;
}// 觸發crash來測試
void crash() {volatile int* a = (int*)(NULL);*a = 1;
}
編譯并運行這個實例應該會在 /tmp 目錄下生成 minidump 文件,并且終端下會輸入minidump文件的路徑。
關于初始化ExceptionHandler可以接受的參數需要參見源碼
ExceptionHandler(const MinidumpDescriptor& descriptor,FilterCallback filter,MinidumpCallback callback,void* callback_context,bool install_handler,const int server_fd);
具體參數:
- descripter,minidump文件寫入的目錄
- filter,可選,在寫minidump文件之前,會先調用filter回調。根據它返回true/false來決定是否需要寫minidump文件。
- callback, 可選,在寫minidump文件之后調用的回調函數
- callback_context,
- install_handler, 如果為ture,不管怎樣當未捕捉異常被拋出時都會寫入minidump文件,如果為false則必須明確調用了
WriteMinidump才會寫入minidump 文件 - server_fd, 如果為-1,則使用同線程模式(in-precess),如果有一個有效的值,則使用跨線程模式(out-of-process)
參見:exception_handler.h源碼
需要注意的是,你必須在callback回調函數中做盡量少的工作,因為你的程序處于一個不安全的狀態,它需要無法安全的去分配內存,或調用其他共享庫中的函數。安全的方式是 fork 和 exec 一個新進程去做想要做的事情。如果你需要在回調中做一些工作,breakpad源碼提供一些簡單的重新實現的libc庫里的方法,來避免直接調用libc, 并提供一個a header file for making linux system calls,來避免直接調用其他共享庫的方法。
6.3 發送minidump文件
在真實環境中,你通常需要以某種方式來處理minidump文件,例如把它發送給服務器來進行分析,Breakpad源碼提供了一些HTTP上傳的代碼,并提供一個minidump上傳工具( 詳見minidump_upload.cc)。
6.4 生成symbols文件
為了生成可讀的stack trace, breakpad需要你將binaries里的調試符號(debugging symbols)轉換成基于文本格式的symbol files。
首先確保你在編譯代碼的時候加上 -g 參數來生成帶調試符號的。
然后使用 configure && make breakpad源碼來生成 dump_syms 工具。
接著運行 dump_syms 命令來生成 symbol files,如下:
$ google-breakpad/src/tools/linux/dump_syms/dump_syms ./test > test.sym
為了可以使用 ``minidump_stackwalk` 工具來生成stack trace,你需要將文件放置在一定的目錄結構,symbol file的第一行說明了需要放置的目錄結構,可以使用命令,或使用 Mozilla 提供的 symbolstore.py 工具來新建這樣的目錄結構。
$ head -n1 test.sym
// MODULE Linux x86_64 6EDC6ACDB282125843FD59DA9C81BD830 test
$ mkdir -p ./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
$ mv test.sym ./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
6.5 生成Stack Trace
breakpad包含一個叫做 minidump_stackwalk 的工具來將 minidump 文件,外加symbol files來生成一個人可讀的stack trace。在編譯breakpad后,這個工具一般在 google-breakpad/src/processor 目錄下, 通過將 minidump 和 symbol files 傳入給它即可:
$ google-breakpad/src/processor/minidump_stackwalk minidump.dmp ./symbols
它會生成verbose output到stderr, stacktrace到stdout。
參見:How To Add Breakpad To Your Linux Application
七. 在Android平臺使用Breakpad
Breakpad支持 ARM x86 和 MIPS 架構的Android系統。需要Android NDK r11c及以上版本。
7.1 構建client庫
Android版本的Client庫設計為一個靜態庫(static library)來使得你可以鏈接到你的Android native代碼里。
一共有兩種方法來build。
7.1.1 方法1:使用ndk-build構建(推薦)
使用ndk-build來構建,需要如下幾個步驟:
- 在你的項目中的 Android.mk 中 include google-breakpad的 Android.mk
include $(LOCAL_PATH)/breakpad/android/google_breakpad/Android.mk
- 鏈接break-client未你的靜態庫模塊
LOCAL_STATIC_LIBRARIES += breakpad_client
- 因為需要c++ STL,所以還需要在
Application.mk文件中加入 STL 支持:
APP_STL := stlport_static
7.1.2 方法2:使用Android toolchain構建
$GOOGLE_BREAKPAD_PATH/configure --host=arm-linux-androideabi \--disable-processor \--disable-toolsmake -j4
將會build到 src/client/linux/libbreakpad_client.a 文件。
可使用 make check 來在Android設備上運行測試。
7.2 在Android上使用Breakpad
在Android平臺上使用breakpad,基本和在linux平臺上是基本類似的。
需要如下幾個步驟:
- 在cpp文件中include exception_handler頭文件
#include "client/linux/handler/exception_handler.h"
- 如果使用ndk-build,需要配置include path(在Android.mk文件中)
LOCAL_C_INCLUDES := $(GOOGLE_BREAKPAD_PATH)/src/common/android/include \$(GOOGLE_BREAKPAD_PATH)/src
并且加上 -llog flag
LOCAL_LDLIBS := -llog
- 時刻記住在Android系統上沒有
/tmp目錄,需要指定一個其他目錄,可以是 application 專有目錄(/data/data/packageName/files),或者存儲到SDCard上面去(需要寫入權限)
7.3 生成stack trace
這個操作和其他平臺一樣。
- 從設備上獲取minidumps文件
- 使用dump_syms工具生成so的symbol files
dump_symc $PROJECT_PATH/obj/local/$ABI/libfoo.so > libfoo.so.sym
- 創建symbol files專有目錄結構
// MODULE Linux x86_64 6EDC6ACDB282125843FD59DA9C81BD830 test$PROJECT_PATH/symbols/libfoo.so/6EDC6ACDB282125843FD59DA9C81BD830/libfoo.sym
- 使用
minidump_stackwalk來生成stack trace:
minidump_stackwalk $MINIDUMP_FILE $PROJECT_PATH/symbols
參見:breakpad for android 官方文檔
作者:駱駝騎士
鏈接:https://www.jianshu.com/p/295ebf42b05b
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
以上是生活随笔為你收集整理的google breakpad native crash分析工具的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求薛之谦歌词
- 下一篇: 百度贴里的“举报”功能是放着专门应付审查