Breakpad 崩溃状态信息收集

2020-02-25 language

一个跨平台的 Crash 状态采集工具,相对 Linux 中的 CoreDump 文件来说,采集的内容更小。

简介

Breakpad 是 Google 开发的一个跨平台 C/C++ Dump 捕获库,其保存文件格式采用微软的 minidump 格式存储,其支持在崩溃时触发,也可以通过手动触发。

主要包含三个组件:

  • Client 以 library 形式内置在应用中,当崩溃或者需要时生成 minidump 文件。
  • SymbolDumper 读取由编译器生成的调试信息,并保存为 Symbol 文件,格式详见 docs/symbol_files.md 中的介绍。
  • Processor 读取 minidump 和 symbol 文件,生成可读的栈信息。

也就是说要在编译阶段生成 Symbol 文件,在运行时生成 minidump 文件,然后根据这两个文件生成调用栈。

minidump

这是由微软开发,用于崩溃上传的文件格式,其包含了:

  • 当 dump 生成时,进程中一系列可执行文件以及动态库信息,包括这些文件的文件名和版本号。
  • 进程中的线程信息,包括寄存器状态、栈内存等信息。
  • 其它相关信息,例如 CPU、OS、dump原因等。

相对 Core 文件来说,minidump 文件会比较小,之所以没有采用 Core 文件,主要还是考虑到跨平台的统一。

底层实现

不同平台上的实现机制略有区别:

  • Windows 使用微软提供的 SetUnhandledExceptionFilter() 方法实现。
  • OS X 通过创建一个线程来监听 Mach Exception Port 来实现。
  • Linux 设置一个信号处理器来监听 SIGILL SIGSEGV 等异常信号。

考虑到在崩溃的进程写 minidump 文件是不安全的,三种平台都提供了跨进程的异常处理机制。

示例

其中 ExceptionHandler() 的声明以及参数含义介绍如下:

ExceptionHandler(
	const MinidumpDescriptor& descriptor,
	FilterCallback filter,
	MinidumpCallback callback,
	void* callback_context,
	bool install_handler,
	const int server_fd
);
  • filter 可选,用来决定是否要写 minidump 文件。
  • callback 可选,写 minidump 文件之后调用的回调函数。
  • install_handler 分成两种场景:A) ture 未捕捉异常抛出时都写 minidump 文件;B) false 明确调用了 WriteMinidump 才会写入。
  • server_fd 当是 -1 是则使用同线程模式;否则使用跨线程模式。

注意,在 callback 回调函数中做尽量少的工作,因为此时程序处于不安全状态,一般不允许分配内存或者调用其它共享库,此时 breakpad 提供了一些简单 libc 库的实现,详见 linux_libc_support.h 中的实现。

另外,Breakpad 还提供了一个 HTTP 上传的实现,详见 minidump_upload.cc 的实现。

参考