GoogleBreakpad库生成Dump文件

文章目录

    • 一、软件奔溃捕获的意义

    • 二、Breakpad介绍

    • 三、Qt工程中加入breakpad库的方法

    • 四、测试是否可以生成dump崩溃文件

    • 五、软件奔溃dump文件上报处理

    • 六、根据dump文件获取Stack Trace

    • 七、编译工具“dump_syms”的方法

    • 八、编译工具"minidump_stackwalk"的方法

    • 九、示例工程中的源码等资源获取

    • 十、参考文章列表

一、软件奔溃捕获的意义

应用程序发布后,不能保证百分百没有bug并引发崩溃。因此,在出现崩溃的情况下需要记录崩溃详情并给用户弹出崩溃提示对话框,提示用户重启软件以及上报(上传)崩溃。
这样做意义是:
能保证软件在使用过程中发现的bug都能被收集起来,并根据崩溃详情修改bug,然后发布修复bug的版本。如果软件在使用过程中直接闪退没有任何提示,不仅用户体验不好,还无法获取崩溃的原因。之后更具用户反馈的口头描述来找bug就会非常头疼了。

二、Breakpad介绍

  1. breakpad简介
    Breakpad是Google公司开发的开源多平台C++崩溃检测库。Breakpad可以捕获发布给用户的应用程序的崩溃,并记录软件崩溃的调试信息到“minidump”文件中。调试信息包括错误行号,报错详情,堆栈错误(stack traces)。软件崩溃时候把生成的“minidump”上传到自己的服务器上就可已方便的获取足够细致崩溃详情。
    支持平台:
    windows、linux、mac、ios、solaris、android ndk

  2. breakpad实现原理简单了解

  • 在不同平台下使用平台特有的函数以及方式实现异常捕获:
    Windows:通过SetUnhandledExceptionFilter()设置崩溃回掉函数
    Max OS:监听 Mach Exception Port 获取崩溃事件
    Linux:监听 SIGILL SIGSEGV 等异常信号 获取崩溃事件

  • MiniDump文件格式
    minidump是由微软开发的崩溃记录文件格式。minidump为二进制文件,体积小。为了保持统一,breakpad在其他系统下也选择生成minidump文件。

  • BreakPad工作原理示意图

    示意图要表达的意思如下:
    a. 包含了breakpad客户端(静态库)的应用程序在发布Release版本的时候。在编译的时候选择保留调试信息。
    b. 使用Breakpad提供的dump_syms工具根据release版本程序生成“symbols文件”。“symbols文件”包括程序之前保留的调试信息。
    c. 发布给用户的release版本程序发生崩溃后包含在程序内“breakpad客户端”会捕捉崩溃并生成“minidump文件”。
    d. “minidump文件”被应用程序发送到你指定的服务器,或通过其他方式收到用户软件崩溃产生的“minidump文件”。
    e. 收到“minidump文件”后,结合发布应用的所对应的 “symbols文件”,通过“minidump_stackwalk” 工具来转换生成文本格式的“stack trace 文件”。这个文件内的信息就是程序员可以直接阅读的崩溃堆栈详情。从而准确的找到触发崩溃的bug。

三、Qt工程中加入breakpad库的方法

breakpad可以先编译生成lib文件,然后在加入到自己的qt工程,也可以直接使用源码加入到自己的qt工程中。
为了方便在Qt中加入breakpad并且方便在多个平台编译,这里使用“源码添加breakpad库“的方式。
在Qt工程加入Breakpad的步骤如下:

  1. 下载源码:https://github.com/google/breakpad

  2. 把源码放置到自己工程目录里面,我这里使用的目录是:third_libs/breakpad/thirdparty

  3. 编写“breakpad.pri”文件用于在工程中引入所需要的breakpad源文件,把文件放置到和breakpad源码相同的目录。

  4. 编写多平台封装类。breakpad在不同系统中有不同的崩溃回调函数。为了实现跨平台使用breakpad,需要做一个封装类,然后对外提供一个唯一的接口。编写一个封装类为“BreakpadHandler”,放置在third_libs/breakpad/src目录中。

  5. 接着编写自己封装类的引入文件“breakpadsrc.pri”。并放置在third_libs/breakpad目录中。此配置文件还包括一些编译参数设置,从而包在各个平台的编译生成的release版本中包含调试信息。同时此文件相当于把整个breakpad相关的文件和配置整理到了一起。从而形成一个跨平台的breakpad模块。在自己的Qt工程中直接引入此模块,即可使用所有Breakpad的功能。

  6. 完成以上所有步骤,最终形成的目录结构如下图所示:

  7. 由于引入文件“breakpad.pri”、“breakpadsrc.pri”和“BreakpadHandler封装类”中的内容很长,因此不便在这里列出。请参考本文第九节中所列出的源码地址。源码中不仅集成了breakpad库,并且包含完整使用示例。

四、测试是否可以生成dump崩溃文件

为了演示上一节所制作的Brakpad库的使用方法。本文专门编写了一个示例工程“BreakpadDemo”。工程的编写过程如下:

  1. 使用Qt Creater新建一个工程,叫做“BreakpadDemo”

  2. 在工程的pro文件中引入之前编写好的brakpad模块

QT       += core gui network //本例子包含网络上传代码# link qBreakpad libraryinclude($$PWD/third_libs/breakpad/breakpadsrc.pri)
  1. 在工程的main.cpp文件编写如下代码:

#include <QApplication>#include "BreakpadHandler.h"void crash() { volatile int* a = (int*)(NULL); *a = 1; }int main(int argc, char *argv[]){    QApplication app (argc, argv);    //those settings are need by QStandardPaths and breakpad    QCoreApplication::setApplicationName("BreakpadDemo");    QCoreApplication::setApplicationVersion("0.0.1");    QCoreApplication::setOrganizationName("OrgName");    QCoreApplication::setOrganizationDomain("name.org");    BreakpadHandler *breakpad_instance = BreakpadHandler::GetInstance();    QStringList path_list2 = QStandardPaths::standardLocations(QStandardPaths::DataLocation);    QString std_base_path =  path_list2[0];    QString my_crash_path = std_base_path + "/crashs";    breakpad_instance->SetupBreakPad(my_crash_path);//or just using "crashes"    //run app    DemoDialog w;    w.show();    crash();    return app.exec();}
  1. 编译运行此工程。查看应用程序调试输出窗口,看是否有dump文件生成。如果生成则,表示你集成成功。程序奔溃后在输入窗口的输入如下图所示:(注:本示例代码以第九节所示源码为准)

五、软件奔溃dump文件上报处理

既然生成了崩溃dump文件。就需要把这个文件传递给开发者才能最终解决bug。那么收集dump文件的方法更具不同平台,不同使用场合,可以有不同的dump文件反馈方式:

  1. 有崩溃上报服务器处理方法
    在服务器软件中加入崩溃文件上传接口。软件这边通过联网并调用这个接口上传即可,本例子中包含上传崩溃文件的示例的代码。

  2. 无崩溃上报服务器处理方法
    有些软件处于无网络连接的使用环境,因此通过网络上传便不再可行。那么应该提供一个良好的引导界面,引导用户把崩溃的dump文件,通过其他可行方式反馈给软件开发公司。
    在本示例工程“BreakpadDemo”中,编写了一个崩溃引导界面,作为崩溃反馈的主要示例方法。因为这个方法不用配合服务器软件,可以独立展示和测试。
    测试崩溃引导过程如下:
    a. 编译并启动BreakpadDemo,点击窗口中的“Crash”按钮来触发一个软件崩溃。

    b. 再次启动BreakpadDemo,软件会弹出一个“引导窗口”,窗口提示用户把接下来弹出的文件发送给售后。

    c. 点击“引导窗口”中的“Ok”按钮会弹出崩溃生成的dmp文件。

六、根据dump文件获取Stack Trace

  1. 生成包含调试信息的Release版本软件
    根具之前介绍的breakpad的原理可知,发送给用户的release版本的软件需要包含调试信息。否则收到dunmp文件也不能获取到报错信息的详情。让发布的release版本软件包含调试信息的方法如下。其实在第三节总提到的“breakpadsrc.pri”文件中就已经包含了这个配置。不用你再次配置。这里是拿出来做一个专门的强调。也方便你了解这些配置的作用。

  • 在MacOS、Linux和windows-mingw环境下编译包含调试信息的release软件:

* {    QMAKE_CFLAGS_RELEASE += -g    QMAKE_CXXFLAGS_RELEASE += -g    QMAKE_CFLAGS_RELEASE -= -O2    QMAKE_CXXFLAGS_RELEASE -= -O2    #QMAKE_LFLAGS_RELEASE = -mthreads -Wl}

注意:在以上编译环境下,调试信息就在编译好的软件本身中。

  • 在Windows-msvc环境下,编译包含调试信息的release软件:

#  for generate dpb files at windowswin32-msvc* {    QMAKE_LFLAGS_RELEASE += /MAP    QMAKE_CFLAGS_RELEASE += /Zi    QMAKE_LFLAGS_RELEASE += /debug /opt:ref}

注意:在windows-msvc下软件的调试信息在单独的*.pdb文件中(msvc指编译器)

  1. 生成“Stack Trace”所用到了命令工具介绍

  • “dump_syms”或“dump_syms.exe”
    用户提取调试信息到一个单独的文件“*.sym”中,给“minidump_stackalk”命令使用。

  • “minidump_stackwalk"或"minidump_stackwalk.exe”
    结合“*.sym”和用户反馈的奔溃dump文件生成“Stack Trace”。包含报错的详情

  1. “dump_syms”和命令"minidump_stackalk"的使用方法

  • 使用环境
    在讲命令的使用方法之前先介绍一下命令的使用环境
    MacOS、Linux
    直接使用系统自带的命令行工具即可。
    windows
    下载Git软件,使用“Git Bash”执行以下命令。因为接下来要运行一个shell脚本,为了方便只使用一个脚本,且windows下无法执行shell脚本。所以使用Git软件所带的Bash运行环境。(如果有需要,你可以根据这个shell脚本编写出对应的windows下的bat脚本)。
    Git软件下载官网:https://git-scm.com/book/zh/v2/起步-安装-Git
    使用的Git的工具如下图所示:

  • 编写生成“Stack Trace”的脚本
    由于这两个命令需要配合使用,且在使用过程中会需要手工创建一些特定名称的文件夹,因此编写了一个shell脚本。由于在windows下需要对脚本稍做修改。因此下面分别贴出2个脚本:
    MacOS、Linux和windows-mingw下的使用脚本

#!/bin/bashif [ $# != 2 ] ; then echo "USAGE: $0 EXE_NAME DMP_NAME" echo " e.g.: $0 test 3872B2CF-983B-4963-AFA9-C8534DFD4C44.dmp" exit 1; fi #get input paramexe_file_name=$1dmp_file_name=$2getSymbol() {    echo "@getSymbol: start get symbol"    ./dump\_syms ./$exe_file_name > $exe_file_name'.sym'}getStackTrace() {    echo "@getStackTrace: start get StackTrace"    sym_file_name=$exe_file_name'.sym'    #get first line of $sym_file_name    line1=`head -n1 $sym_file_name`    #echo $line1    #get version number form string of first line    OIFS=$IFS; IFS=" "; set -- $line1; aa=$1;bb=$2;cc=$3;dd=$4; IFS=$OIFS     #echo $dd    version_number=$dd    #make standard dir and move *.sym in it    mkdir -p ./symbols/$exe_file_name/$version_number    mv $sym_file_name ./symbols/$exe_file_name/$version_number    #print stack trace at std output    ./minidump_stackwalk $dmp_file_name ./symbols 2> /dev/null     #print stack trace at a file    #./minidump_stackwalk $dmp_file_name ./symbols 2>/dev/null >result.txt}main() {    getSymbol     if [ $? == 0 ]     then         getStackTrace    fi}# run mainmain

在windows-msvc下的使用的脚本
为了增强阅读体验,windows-msvc所用的脚本不在此列出,在第九节中的源码中统一提供。

  1. 脚本使用方法
    MacOS、Linux和windows-mingw下的使用方法
    注意:BreakpadDemo为编译后的可执行文件(macos平台下注意右键打开包正文/Contents/MacOS下获取)
    命令、脚本、dmp文件、可执行文件等文件如下图目录所示

sh ./process_dump.sh BreakpadDemo 928703D7-EA7B-4050-8DF5-667958A502F0.dmp

在windows-msvc下的使用方法
注意:在windows-msvc环境下,需要使用从编译生成的pdb文件中获取调试信息
命令、脚本、dmp文件、可执行文件等文件如下图目录所示

sh ./process_dump.sh BreakpadDemo.pdb ee4962a8-0bf4-419a-8830-8230e26488cc.dmp

如果出现以下报错请参考,第七小节

CoCreateInstance CLSID_DiaSource failed (msdia*.dll unregistered?)
  1. 脚本执行结果中“Stack Trace”的报错详情截图如下:

  2. 对脚本所做操作的解释
    脚本相当于以下命令依次执行:

#生成symbols文件,生成的文件名字指定为:“test.sym”./dump\_syms ./test > test.sym #得到test.sym这个文本文件的第一行,如下#MODULE mac x86_64 887D1A2C356F3401ABCCA76B666B3A810 testhead -n1  test.sym#依照上面一行中的id名字创建目录mkdir -p ./symbols/test/887D1A2C356F3401ABCCA76B666B3A810#把生成的test.sym符号文件复制到刚刚创建的目录mv test.sym ./symbols/LedStripEditor/887D1A2C356F3401ABCCA76B666B3A810#使用minidump_stackwalk命令生成“stack trace”到result.txt,把处理过程输出到process.txt#当然,在正式脚本中,为了方便查看,直接把“stack trace”输出到了stdout./minidump_stackwalk  xxx.dmp  ./symbols > result.txt 2> process.txt

七、编译工具“dump_syms”的方法

  1. Linux系统下
    安装G++编辑器,编译唯一的一个c++代码即可。未经实际测试。

  2. 在MacOS下:
    安装XCode作为编译工具
    找到breakpad的源码目录,在源码的"src/tools/mac/dump_syms"目录中,找到dump_syms.xcodeproj这个文件用XCode编译即可获得macos平台下的dump_syms工具。

  3. 在Windows系统下:
    安装Visual Studio 2017(并选择Vritual C++编程环境)作为编译工具,不一定是2017版本,任何版本都可以
    找到breakpad的源码目录,在源码的"src/tools/windows/dump_syms"目录中,找到dump_syms.vcproj这个文件用Visual Studio编译即可获得windows平台下的dump_syms工具。
    注意:由于是开源代码源代码不停更新,经过测试,从github下载的源代码会导致此工具编译失败。因此建议使用本示例所使用的breakpad源码。源码在第九节的源码中包含,目录为:BreakpadDemo/third_libs/breakpad/thirdparty/breakpad

  4. 在windows下编译遇到问题解答
    问题1:
    使用Visual Studio导入工程后,编译的时候,报错提示“找不到Windows SDK 8.1”,如下图所示:

    解答问题1:
    下载并安装Windows Sdk。然后在Visual Studio中的“dump_syms”工程,右键“属性”,修改Sdk为你安装的Sdk。如下图所示:

    问题2:
    dump_syms.exe已经编译好了,但是使用命令导出调试信息的时候,出现以下错误输出:

CoCreateInstance CLSID_DiaSource failed (msdia*.dll unregistered?)

错误截图如下:

解答问题2:
错误提示为:msdia*.dll这个dll未注册。解决办法如下:
从网上下载“msdia80.dll”、“msdia100.dll”,“msdia120.dll”这几个dll,实际上只用其中的一个dll。具体用到了那个dll,应该是依据的开发环境所定。这里是把可能用到的都下载了。本文测试环境为win7_32位,因此下载的dll也应该是32位的。这三个Dll本文在第九节的源码中会提供。
把准备好的三个dll放置到以下目录:

c:\Program Files\Common Files\Microsoft Shared\VC

如下图所示:

然后编写一个bat脚本来注册这几个dll。脚本内容如下:

c:\Windows\system32\regsvr32 "c:\Program Files\Common Files\Microsoft Shared\VC\msdia80.dll"c:\Windows\system32\regsvr32 "c:\Program Files\Common Files\Microsoft Shared\VC\msdia100.dll"c:\Windows\system32\regsvr32 "c:\Program Files\Common Files\Microsoft Shared\VC\msdia140.dll"

执行脚本
注意这个脚本直接运行会出现如下图所示错误:

应该选中脚本文件,右键“以管理员身份运行”,即可依次弹出成功消息如下图所示:

八、编译工具"minidump_stackwalk"的方法

  1. MaccOS、Linux系统下编译:
    使用命令行切换到brakpad的源码目录。执行以下命令

./configure && make

编译完成之后,breakpad源码目录中的"src/processor/"中可以找到“minidump_stackwalk”这个编译好的工具。

  1. windows系统下编译:
    由于windows下不具有configure和make等工具。而breakpad的源码中也没有整体的visual studio工程文件。因此选用另一种编译模式,即模拟linux环境的编译模式(类似Qt-mingw编译模式)。操作方式如下:

  • 配置编译器
    下载windows版本的Qt,并断网安装(避免注册)。安装的时候选择安装mingw-32编译器。其他安装选项按需选择。这个步骤主要是为了保证你安装有mingw-32编译器(当然同时你可以在windows下使用Qt Creater编译BreakpadDemo来测试)。
    Qt的下载地址为:http://download.qt.io/archive/qt/5.12/5.12.5/

安装好后,把需要添加环境变量,用于之后在命令行编译的时候能找到编译工具。本文的测试环境中,需要添加的环境变量为:

C:\Qt\Qt5.12.5\Tools\mingw730_32\bin;
  • 配置编译工具
    前面提到要以Linux的方式编译工程。因此需要使用“Git Bash”,这个软件除了作为管理git的代码,还提供了一个标准的shell执行环境。
    Git软件下载官网:https://git-scm.com/book/zh/v2/起步-安装-Git
    这里有一个注意点,不能安装在默认安装目录,不然windows系统的“Program Files”这个目录中的空格会给之后的编译造成问题。编译会报错为:“/usr/bin/sh: C:/Program: No such file or directory”。本文是安装在C盘根目录。

  • 正式编译
    使用configure先生成makefile

./configure

正确配置完成以后,执行make命令

mingw32-make

编译完成之后,breakpad源码目录中的"src/processor/"中可以找到“minidump_stackwalk.exe”这个编译好的工具。

九、示例工程中的源码等资源获取

源码中包含以下内容:

  • BreadpadDemo源码(在MacOS和Windows7下测试验证通过)

  • 用于MaxOS的“dump_syms”和“minidump_stackwalk”工具集合(包含脚本)

  • 用于Windows的“dump_syms”和“minidump_stackwalk”工具集合(包含脚本)

  • 用于在wiindows下编译“dump_syms”的msdia_dll

源码地址为:
点此获取源码

十、参考文章列表

Using Google Breakpad with Qt

(0)

相关推荐

  • 学会这个绝招,让 C 崩溃无处可逃!

    Breakpad 是 Google 用 C++ 编写的一个开源.跨平台的崩溃报告系统,它支持 Windows.Linux 和 macOS,并提供了一个上传器,可以在进程崩溃时向一个配置好的 URL 提 ...

  • 系统蓝屏问题:C:\WINDOWS\Minidump\011721-12968-01.dmp

    表白:关于想你这件事,躲得过对酒当歌的夜,躲不过四下无人的街.  讲解对象:/系统蓝屏问题:C:\WINDOWS\Minidump\011721-12968-01.dmp 作者:融水公子 rsgz 今 ...

  • Windows下切分文件

    Windows下切分文件 在linux下有split可以很方便的切分文件.windows下cmd未找到相关命令.当然,也可以安装GnuWin32,利用现成的split命令来进行切分.但是如者二者都没有 ...

  • Android Studio 4.0.+NDK .so库生成打包

    前言 1. 什么是.so库 2. cmake生成.so方案 3. 传统生成.so方案 4. external tools配置 总结 博客创建时间:2020.10.28 博客更新时间:2020.10.2 ...

  • 模块一 GO语言基础知识-库源码文件

    你已经使用过 Go 语言编写了小命令(或者说微型程序)吗? 当你在编写"Hello, world"的时候,一个源码文件就足够了,虽然这种小玩意儿没什么用,最多能给你一点点莫名的成就 ...

  • C语言这些常用的标准库(头文件),你不得不知道...

    有很多工程师喜欢自己封装一些标准库已有的函数,其实自己封装的函数,并不一定比标准库好,有时候反而代码更冗余,且有bug. 下面小编就来分享一下C语言常见的一些标准库. 标准头文件包括: <ass ...

  • 使用pdfrw库对pdf文件进行读写操作

    大家好,前几天分享了一篇读取pdf文章,但是依然无法少部分的pdf进行操作.今天看Python Weekly最新一期推送的文章中<Creating and Manipulate PDFs wit ...

  • pandas库读取csv文件

    很高兴能给大家分享我学python的经历,今晚的直播很感动.自己在直播前准备还是不够充分,导致讲课后半部分很没逻辑.但大家都很鼓励我,让我很感动.现在先附上大家的鼓励,永远留作纪念. 更有大家的给力支 ...

  • python一键生成生成requirements文件

    表白:黑白圣堂血天使,天剑鬼刀阿修罗.  讲解对象:/python一键生成生成requirements文件  作者:融水公子 rsgz Python3 教程 python教程 http://www.r ...

  • CASS指定点生成数据文件

    CASS指定点生成数据文件

  • 解决安装Pycharm后在C盘下生成大文件的问题

    前言 上次在整理C盘时,无意间发现了一个这样的文件.在我的用户目录下,有个.PyCharm2019.3这样的文件夹,我猜想和Pycharm可能有什么py关系. 那这个文件有多大呢,来操作一下康康. 雾 ...