Google breakpad是一个跨平台的崩溃转储和分析框架和工具集合。
Breakpad由三个主要组件:
简单来说就是一个生成 minidump,一个生成symbol file,然后将其合并处理成可读的Stack trace。
minidump文件格式是由微软开发的用于崩溃上传,它包括:
breakpad在所有平台上(windows/linux等)都统一使用minidump文件格式,而不使用core files,原因是因为:
什么是core files?core files是unit系统上程序崩溃时生成的文件。
参见:http://www.jianshu.com/p/8e1352a9638f
symbols文件是基于纯文本的,每一行一条记录,每条记录中的字段以一个空格作为分隔符,每条记录的第一个字段表示这一行是什么类型的记录。
记录类型:
MODULE
operatingsystem architecture id name FILE
number name FUNC
address size parameter_size name PUBLIC
address parameter_size name STACK WIN
STACK CFI
参见:https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
默认情况下,当崩溃时breakpad会生成一个minidump文件,在不同平台上的实现机制不一样:
SetUnhandledExceptionFilter()
方法来实现。 Mach Exception port
来实现。 SIGILL
SIGSEGV
等异常信号。 当minidump被生成后,在不同平台上也使用不同的机制来上传crash dump文件。
参见:Windows SetUnhandledExceptionFilter 参见:Mac OS X Exception handling 参见:Catching Exceptions and Printing Stack Traces for C on Windows, Linux, & Mac
提供两种不同的异常处理机制:
因为在崩溃的进程写minidump文件是不安全的,所以三个平台(windows、linux、mac os)都提供跨进程的异常处理机制。
这里因为要研究Android上使用breakpad,所有主要研究linux平台,windows和mac平台的使用方法请自行参考文档。
breakpad提供自动构建工具来构建linux client库和processor库。
在breakpad源码目录下通过运行命令:
./configure
make
将自动生成 src/client/linux/libbreakpad_client.a
文件, 其包含了在你的应用中生成minidumps文件的必要代码。
首先配置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[]) {
// 初始化ExceptionHandler
google_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);
具体参数:
WriteMinidump
才会写入minidump 文件参见:exception_handler.h源码
需要注意的是,你必须在callback回调函数中做尽量少的工作,因为你的程序处于一个不安全的状态,它需要无法安全的去分配内存,或调用其他共享库中的函数。安全的方式是 fork
和 exec
一个新进程去做想要做的事情。如果你需要在回调中做一些工作,breakpad源码提供一些简单的重新实现的libc库里的方法,来避免直接调用libc, 并提供一个a header file for making linux system calls,来避免直接调用其他共享库的方法。
在真实环境中,你通常需要以某种方式来处理minidump文件,例如把它发送给服务器来进行分析,Breakpad源码提供了一些HTTP上传的代码,并提供一个minidump上传工具( 详见minidump_upload.cc)。
为了生成可读的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
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
Breakpad支持 ARM x86 和 MIPS 架构的Android系统。需要Android NDK r11c及以上版本。
Android版本的Client库设计为一个静态库(static library)来使得你可以链接到你的Android native代码里。
一共有两种方法来build。
使用ndk-build来构建,需要如下几个步骤:
include $(LOCAL_PATH)/breakpad/android/google_breakpad/Android.mk
LOCAL_STATIC_LIBRARIES += breakpad_client
Application.mk
文件中加入 STL 支持:APP_STL := stlport_static
$GOOGLE_BREAKPAD_PATH/configure --host=arm-linux-androideabi \
--disable-processor \
--disable-tools
make -j4
将会build到 src/client/linux/libbreakpad_client.a 文件。
可使用 make check
来在Android设备上运行测试。
在Android平台上使用breakpad,基本和在linux平台上是基本类似的。
需要如下几个步骤:
#include "client/linux/handler/exception_handler.h"
LOCAL_C_INCLUDES := $(GOOGLE_BREAKPAD_PATH)/src/common/android/include \
$(GOOGLE_BREAKPAD_PATH)/src
并且加上 -llog flag
LOCAL_LDLIBS := -llog
/tmp
目录,需要指定一个其他目录,可以是 application 专有目录(/data/data/packageName/files),或者存储到SDCard上面去(需要写入权限)这个操作和其他平台一样。
dump_symc $PROJECT_PATH/obj/local/$ABI/libfoo.so > libfoo.so.sym
// 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 官方文档