Google Breakpad的使用

本文介绍了GoogleBreakpad,一个用于收集和分析应用程序崩溃的框架,涉及客户端集成、minidump生成、符号文件处理和不同平台的实现机制,包括Windows、OSX和Linux的异常捕获方法。
摘要由CSDN通过智能技术生成

Google Breakpad的使用

Google breakpad是一个跨平台的崩溃转储和分析框架和工具集合。
Breakpad由三个主要组件:

  • client 是一个库,以library的形式内置在你的应用中,以配置客户端发生了崩溃时写入一个minidump文件

  • symbol dumper 是一个程序,读取由编译器产生的调试信息(debugging information),并生成一个使用Breakpad格式的符号文件( symbol file)

  • processor 是一个程序,读取 minidump文件 和 symbol file,生成可读的c/c++ 堆栈跟踪(Stack trace.)

默认情况下,当崩溃时breakpad会生成一个minidump文件,
在不同平台上的实现机制不一样:

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

当minidump被生成后,在不同平台上也使用不同的机制来上传crash dump文件。

在Linux平台使用breakpad

  1. 下载源码,具体的编译过程请参考breakpad
  git clone https://chromium.googlesource.com/breakpad/breakpad

git clone https://github.com/google/breakpad.git
  1. 在breakpad源码目录下通过运行命令:
./configure
make

编译出错

In file included from ./src/client/linux/dump_writer_common/thread_info.h:36,
                 from ./src/client/linux/minidump_writer/linux_dumper.h:53,
                 from ./src/client/linux/minidump_writer/minidump_writer.h:41,
                 from src/tools/linux/core2md/core2md.cc:37:
./src/common/memory_allocator.h:49:10: fatal error: third_party/lss/linux_syscall_support.h: No such file or directory
   49 | #include "third_party/lss/linux_syscall_support.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:5667: src/tools/linux/core2md/core2md.o] Error 1

下载依赖包

git clone https://chromium.googlesource.com/linux-syscall-support src/third_party/lss

连接可能超时,无法下载。或 下载文件
进入 breakpad 的 src 目录的 third-party 文件夹,创建 lss 文件夹,拷贝下载的依赖包里的文件。

执行验证文件的正确性: gcc -Wall -Wextra -Wstrict-prototypes -c linux_syscall_support.h

然后重新编译

编译完以后会在生成两个可执行文件,分别是src/processor/minidump_stackwalk和src/tools/linux/dump_syms/dump_syms
生成 src/client/linux/libbreakpad_client.a

  1. 在应用中使用Breakpad
    将自动生成 src/client/linux/libbreakpad_client.a 文件, 其包含了在你的应用中生成minidumps文件的必要代码。

首先配置build precess来link刚生成的 libbreakpad_client.a 文件。

然后设置 include paths 来 包含 google-breakpad 目录下的 src 目录。

接下来include头文件:

现在你就可以初始化 ExceptionHandler 对象,初始化的时候需要提供一个用于写minidump文件的目录,以及一个回调函数用于在minidump文件写完以后调用。

#include "client/linux/handler/exception_handler.h"
// 写完minidump后的回调函数
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
                         void* context, bool succeeded) {
  printf("Dump path: %s\n", descriptor.path());
  return succeeded;
}
// 触发crash来测试
void testCrash() {
  int* a = nullptr;
  *a = 1;
}
int main(int argc, char* argv[]) {
  // 初始化ExceptionHandler
  google_breakpad::MinidumpDescriptor descriptor("/tmp"); // minidump文件写入到的目录
  google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);
  testCrash();
  return 0;
}

编译并运行这个实例应该会在 /tmp 目录下生成 minidump 文件,并且终端下会输入minidump文件的路径。

g++ -g -I ../breakpad/src -o test breakpad_sample.c ../breakpad/src/client/linux/libbreakpad_client.a -lpthread
  1. 生成symbols文件

为了生成可读的stack trace, breakpad需要你将binaries里的调试符号(debugging symbols)转换成基于文本格式的symbol files。
首先确保你在编译代码带调试符号,release的时候加上 -g 参数来生成带调试符号的。

运行 dump_syms 命令来生成 symbol files,如下:

$ google-breakpad/src/tools/linux/dump_syms/dump_syms ./TestBreakPad_linux > TestBreakPad_linux.sym
  1. 生成Stack Trace
    为了可以使用 `minidump_stackwalk 工具来生成stack trace,你需要将文件放置在一定的目录结构,symbol file的第一行说明了需要放置的目录结构,可以使用命令,或使用 Mozilla 提供的 symbolstore.py 工具来新建这样的目录结构。
$ head -n1 TestBreakPad_linux.sym.sym 
// MODULE Linux x86_64 E52092337B1FB1646ED685CC18FD30790 TestBreakPad_linux
├── symbol
│   └── TestBreakPad_linux
│       └── E52092337B1FB1646ED685CC18FD30790 
│           └── TestBreakPad_linux.sym

$ mkdir -p ./symbol/TestBreakPad_linux/E52092337B1FB1646ED685CC18FD30790
$ mv test.sym ./symbol/TestBreakPad_linux/E52092337B1FB1646ED685CC18FD30790

$ google-breakpad/src/processor/minidump_stackwalk 41c013b5-9e9a-4dfc-ec430795-b944e4b3.dmp ./symbol

它会生成verbose output到stderr, stacktrace到stdout。

CPU: amd64
     family 6 model 78 stepping 3
     4 CPUs

GPU: UNKNOWN

Crash reason:  SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: not available

Thread 0 (crashed)
 0  TestBreakPad_linux!testCrash() [main.cpp : 16 + 0x4]
    rax = 0x0000000000000000   rdx = 0x0000000000000000
    rcx = 0x00007fff570e1350   rbx = 0x0000000000000000
    rsi = 0x0000000000000000   rdi = 0x0000561071a596c0
    rbp = 0x00007fff570e13a0   rsp = 0x00007fff570e13a0
     r8 = 0x0000000000000000    r9 = 0x000056107214af88
    r10 = 0x0000000000000008   r11 = 0x00007f84945a4ce0
    r12 = 0x00007fff570e1678   r13 = 0x0000561071a40068
    r14 = 0x0000561071a58a18   r15 = 0x00007f8494840040
    rip = 0x0000561071a4005f
    Found by: given as instruction pointer in context
 1  TestBreakPad_linux!main [main.cpp : 24 + 0x5]
    rbx = 0x0000000000000000   rbp = 0x00007fff570e1560
    rsp = 0x00007fff570e13b0   r12 = 0x00007fff570e1678
    r13 = 0x0000561071a40068   r14 = 0x0000561071a58a18
    r15 = 0x00007f8494840040   rip = 0x0000561071a4013a
    Found by: call frame info
 2  libc.so.6 + 0x29d90
    rbx = 0x0000000000000000   rbp = 0x0000000000000001
    rsp = 0x00007fff570e1570   r12 = 0x00007fff570e1678
    r13 = 0x0000561071a40068   r14 = 0x0000561071a58a18
    r15 = 0x00007f8494840040   rip = 0x00007f84943b4d90
    Found by: call frame info
 3  TestBreakPad_linux!testCrash() [main.cpp : 17 + 0x3]
    rsp = 0x00007fff570e1580   rip = 0x0000561071a40068
    Found by: stack scanning
 4  0x1570e1688
    rbp = 0x0000561071a40068   rsp = 0x00007fff570e1588
    rip = 0x00000001570e1688
    Found by: call frame info
 5  TestBreakPad_linux!testCrash() [main.cpp : 17 + 0x3]
    rsp = 0x00007fff570e15b0   rip = 0x0000561071a40068
    Found by: stack scanning
 6  0x561071a58a18
    rbp = 0x0000561071a40068   rsp = 0x00007fff570e15b8
    rip = 0x0000561071a58a18
    Found by: call frame info
 7  libc.so.6 + 0x29e40
    rsp = 0x00007fff570e1610   rip = 0x00007f84943b4e40
    Found by: stack scanning
 8  TestBreakPad_linux!google_breakpad::ConvertUTF8toUTF32(unsigned char const**, unsigned char const*, unsigned long**, unsigned long*, google_breakpad::ConversionFlags) [clone .cold] + 0xd
    rsp = 0x00007fff570e1640   rip = 0x0000561071a3ff20
    Found by: stack scanning
 9  TestBreakPad_linux!_start + 0x25
    rsp = 0x00007fff570e1660   rip = 0x0000561071a3ff45
    Found by: stack scanning
10  0x7fff570e1668
    rsp = 0x00007fff570e1668   rip = 0x00007fff570e1668
    Found by: call frame info

Loaded modules:
0x561071a3c000 - 0x561071a51fff  TestBreakPad_linux  ???  (main)
0x7f84942a4000 - 0x7f849432dfff  libm.so.6  ???
0x7f849438b000 - 0x7f8494547fff  libc.so.6  ???  (WARNING: No symbols, libc.so.6, 489D3869975ADB93E873F0EA2C93E02E0)
0x7f84945b3000 - 0x7f84945ccfff  libgcc_s.so.1  ???
0x7f84945d3000 - 0x7f849477cfff  libstdc++.so.6  ???
0x7f8494806000 - 0x7f8494831fff  ld-linux-x86-64.so.2  ???
0x7fff57182000 - 0x7fff57183fff  linux-gate.so  ???
2023-09-12 11:52:35: minidump.cc:5558: INFO: Minidump closing minidump
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值