阅读 555

google-breakpad - 使用篇

前言

前段时间无聊时看chromium无意间发现了这个breakpad库,发现正好可以应用到我们团队中(windows已经有了),本篇章节将会介绍brekapad的源码编译和linuxbreakpad的使用。在下一篇文档中将会通过breakpad的源码去揭开它神秘的面纱。

简介

breakpadgoogle开发的一个跨平台C/C++ dump捕获开源库,崩溃文件使用微软的minidump格式存储,也支持发送这个dump文件到你的服务器,breakpad可以在程序崩溃时触发dump写入操作,也可以在没有触发dump时主动写dump文件。breakpad支持windowslinuxmacosandroidios等。目前已有Google Chrome, Firefox, Google Picasa, Camino, Google Earth等项目使用。

整体概述

图片左上角是一个完整的应用程序,它包含了三部分即程序代码、Breakkpad Client(即brekapad提供出来的静态库),调式信息

Build Systembreakpadsymbol生成工具借助应用层序中的Debugging Information这一部分生成一个Google自己的符号文件,这个符号文件类似于windows上的pdb文件,最终呢在发布应用层序的时候使用strip将调式信息去除

User's System中运行的应用程序是通过strip去除了调式信息的,倘若应用程序发生CrashBreakpad client就会写minidump文件到指定目录,并且可以将产生的minidump文件发送到远端服务器即Crash Colletcor

Crash Collector就可以利用Build System中产生的symol文件和User's System中上报的minidump文件生成用户可读的stack trace

breakpad有三个主要的组件:

  • breakpad-client : client是一个静态库,主要提供给应用程序使用,它可以帮助应用层序捕获应用层序并且生成minidump文件以及上传minidump文件

  • symbol dumper : symbol dumper的表现形式是一个可执行文件,它可以通过调式信息生成一个symbol file, 这个symbol file的格式是google自己的格式,具体请查看

Minidump

Minidump是微软开发的一种用于崩溃时记录的小存储器转储文件,它类似与linux下的core fileminidump中包含以下信息:

  • 进程装载的驱动程序和共享库列表,这个列表中包含了指定的名称和版本号

  • 进程中存在的线程列表。对于每个线程,小型转储包括处理器寄存器的状态和线程堆栈内存的内容。这些数据是未解释的字节流,因为 Breakpad 客户端通常没有可用于生成函数名称或行号,甚至标识堆栈帧边界的调试信息。

  • 已停止的处理器的上下文 (PRCB)

  • 已停止的进程的信息和内核上下文 (EPROCESS)

  • 有关收集转储的系统的其他信息:处理器和操作系统版本、转储的原因等。

Breakpad 在所有平台上使用 Windows 小型转储文件,而不是传统核心文件,原因如下:

  • 核心文件可能非常大,因此无法通过网络将其发送到收集器进行处理。小型转储更小,因为它们被设计为这样使用。

  • 核心文件格式记录得很差。例如,Linux 标准基础不描述寄存器如何存储在段中。

  • 说服 Windows 计算机生成核心转储文件比说服其他计算机编写小型转储文件更难。

  • 它简化了 Breakpad 处理器,仅支持一种文件格式。

源码下载以及编译

mkdir breakpad && cd breakpad fetch breakpad cd src ./configure && make make check make install 复制代码

使用教程

breakpad分为 in-processout-process

In-Process

#include "client/linux/handler/exception_handler.h" static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) {   printf("Dump path: %s\n", descriptor.path());   return succeeded; } void crash() { volatile int* a = (int*)(NULL); *a = 1; } int main(int argc, char* argv[]) {   google_breakpad::MinidumpDescriptor descriptor("/tmp");   google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);   crash();   return 0; } 复制代码

MinnidumpDescriptor设置了dump生成目录为/tmp,然后初始化了ExceptionHandler,之后crash函数模拟了程序的崩溃,在程序崩溃之后会在tmp目录下生成一个dump文件,路径是descriptor.path()

编译

g++ -g -o test.cc test -I/usr/local/include/breakpad -lbreakpad_client -lpthread 复制代码

给你的应用程序生成symbol文件

通过上面的步骤你还是只有dump文件,你需要通过google提供的dump_syms二进制程序给你的应用程序生成symbol文件(如果你运行了make install,在/usr/local/bin目录下就会有这个二进制文件), 之后通过symbol文件和dump文件就可以产生可读堆栈信息


通过dump_symstest生成symbol文件

dump_syms ./test > test.sym 复制代码

symbol文件需要根据 test.sym的第一行类容来防止目录结构位置,才能够被正确读取

head -n1 test.sym // 输出 MODULE Linux x86_64 6EDC6ACDB282125843FD59DA9C81BD830 test 复制代码

根据上面的信息,你的test.sym信息需要放置到./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830/test.sym, 当然这样你也还是只加载来你应用层序的symbol,上面同样的操作你还需要对你依赖的动态库进行符号文件的生成。

根据minnidump和symbol生成stack trace

minidump_stackwalk是一个二进制可执行程序,你执行过make install/usr/local/bin里面可以找到这个可执行程序,这个可执行程序可以生成可读堆栈信息

minidump_stackwalk minidump.dump ./symbols 复制代码

Out-Process

out-process表示dump文件的生成和写入在崩溃进程外进行,linux中进程间采用socketpair通信

int server_fd; int client_fd; void OnClientDumpRequestCallabck(void* context, const ClientInfo* client_info, const string* file_path) { } int main(void) {   CrashGenerationServer::CreateReportChannel(&server_fd, &client_fd);   CrashGenerationServer crash_server(     server_fd,     &OnClientDumpReuqestCallabck,     NULL,     NULL,     NULL,     true,     "/tmp");   crash_server.Start();   // 拉起检查崩溃进程,并且传入client_fd, 在崩溃检查进程中初始化ExceptionHandler类,最后一个参数传入client_fd }


作者:spider集控团队
链接:https://juejin.cn/post/6899070041074073614


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐