文章目录

  • 前言
  • 一、如何基于qBreakpad在Linux中生成dump文件
    • 1、源码准备
    • 2、编译qBreakpad
      • 将Breakpad、LSS源码放入third_party目录
      • qBreakpad工程介绍
      • 源码bug修正(本人编译并未遇到任何错误,此错误参考于网上记录,可以跳过忽略)
        • 编译handler工程时,报错
        • 编译demo工程时,报错
        • 编译demo工程,报错
      • 编译生成libqBreakpad.a
    • 3、在程序中调用qBreakpad
    • 4、生成dump文件
  • 二、生成带调试信息的可执行程序
  • 三、生成dump_syms和minidump_stackwalk工具
    • 1、将LSS源码放入src\third_party目录
    • 2、编译、安装Breakpad
  • 四、使用dump_syms和minidump_stackwalk定位bug
    • 1、生成符号文件
    • 2、将符号文件移动到特定路径
    • 3、生成崩溃处调用堆栈信息
  • 五、dump文件上报
  • 六、总结

上一篇Qt Windows系统使用QBreakpad实战

前言

前面写了基于win系统的qBreakpad的编译到项目实战,本章将继续以qBreakpad为基础在linux 系统上面演示程序崩溃的如何生成dump文件并定位到BUG所在

关于一些dump文件的知识和breakpad相关的理念这里就不啰嗦了,因为上一篇在win系统使用中已经全面讲解了,有兴趣的可以去上一篇看了再回来看本篇,此篇主要涉及如何在linux系统中编译出qbreakpad需要的*.so库文件,然后使用qt如何调用,并生成dump文件后,如何定位出bug

ps: 此篇也适用于Max系统上部署QBreakpad调式bug定位

一、如何基于qBreakpad在Linux中生成dump文件

1、源码准备

我们知道qBreakpad是对Breakpad的封装,所以qBreakpad的编译,还依赖2套源码BreakpadLSS

因为github可能需要翻墙,所以我这里给出我收集好的所有源码码云连接,当然下面也会贴出github的源码原链接,有需要的可以自己去克隆或下载也是一样

下载Breakpad源码
下载地址:https://github.com/google/breakpad

下载LSS源码
下载地址:https://github.com/ithaibo/linux-syscall-support

下载qBreakpad源码
下载地址:https://github.com/buzzySmile/qBreakpad

2、编译qBreakpad

以下开发环境:Ubuntu18.04下,Qt Creator(Qt5.12.12) + GCC(7.5.0)编译器。

将Breakpad、LSS源码放入third_party目录

克隆或下载qBreakpad源码后,如果是直接克隆我上面码云的链接,基本就只要拷贝就行了,下面是我自己码云链接克隆后的截图如下:

qBreakpad\third_party目录下,有如下2个空目录,如下:

分别将breakpadLSS(linux-syscall-support)源码拷贝至breakpadlss目录,因为这两个目录下源码需要参与qBreakpad编译。放置好后,如下所示:

breakpad目录下:

lss目录下:

qBreakpad工程介绍

在qBreakpad源码目录下,使用QtCreator打开qBreakpad.pro工程,如下:

  • demo工程下,有两个演示程序programreporter,分别实现了演示生成dump文件上报dump文件的功能。

  • handler为静态库工程,该工程封装了Breakpad,直接编译此工程,可生成libqBreakpad.a

  • tests为一个简单的测试工程

然后直接构建就ok了,构建成功后,会在qBreakpad/handler 目录下生成libqBreakpad.a文件, 如下图

我们只需要拿到这个libqBreakpad.a文件即可, 根据网上查阅资料参考的文章中,有说在编译时会报错,需要修正源码。但是我这边一键构建,没有出现任何错误,不过我下面还是会记录贴出来,以免有人会遇到对应的错误!

源码bug修正(本人编译并未遇到任何错误,此错误参考于网上记录,可以跳过忽略)

以下内容均复制于原帖,无改动~

编译handler工程时,报错

报错如下:

error: No rule to make target ‘…/…/qBreakpad-master/third_party/breakpad/src/common/convert_UTF.c’,
needed by ‘_build/obj/convert_UTF.o’. Stop.

解决办法: 在qBreakpad-master/third_party/breakpad.pri中,

将
$$BREAKPAD_PATH/common/convert_UTF.c \
改为:
$$BREAKPAD_PATH/common/convert_UTF.cc \

重新编译handler工程,错误消失。

编译demo工程时,报错

报错如下:

exception_handler.cc: error: undefined reference to `breakpad_getcontext’

解决办法:该错误是链接libqBreakpad.a时,就会报错。在qBreakpad-master/third_party/breakpad.pri中,unix下添加如下一行

$$BREAKPAD_PATH/common/linux/breakpad_getcontext.S \

效果如下:

重新编译handler工程,生成新的库后,再次编译demo工程,错误本应该消失。但是又出现错误,见下一条。

编译demo工程,报错

报错如下:

error: cannot find -lqBreakpad

解决办法:在qBreakpad-master\demo\reporter\reporter.pro文件中,添加如下一行

QMAKE_LIBDIR += $$OUT_PWD/../../handler

再次编译demo工程,错误消失。

编译生成libqBreakpad.a

Release模式下,编译handler工程,生成libqBreakpad.a静态库, 上面已经贴出我编译成功的截图!

3、在程序中调用qBreakpad

我们建立基于QWidget的一个工程,工程名为qBreakpadTest,如下:

在工程目录下建立qBreakpad目录,用于存放库和头文件。

然后,将libqBreakpad.a拷贝至,qBreakpad\lib\目录下。如图所示:

再将调用库所需的头文件QBreakpadHandler.h、QBreakpadHttpUploader.h、call_once.h、singleton.h共4个文件拷贝至qBreakpad\include下。如下图:

最后目录结构,如下:

qBreakpadTest.pro文件中,添加如下内容:

############ for qBreakpad ############
# qBreakpad中需要使用到network模块
QT += network# 启用多线程、异常、RTTI、STL支持
CONFIG += thread exceptions rtti stl# without c++11 & AppKit library compiler can't solve address for symbols
CONFIG += c++11
macx: LIBS += -framework AppKit# 配置头文件搜索路径和链接库路径
unix:!macx: LIBS += -L$$PWD/qBreakpad/lib/ -lqBreakpadINCLUDEPATH += $$PWD/qBreakpad/include
DEPENDPATH += $$PWD/qBreakpad/includeunix:!macx: PRE_TARGETDEPS += $$PWD/qBreakpad/lib/libqBreakpad.a############ for qBreakpad ############

然后在main.cpp中添加调用代码,如下:

int main(int argc, char *argv[])
{QApplication a(argc, argv);QBreakpadInstance.setDumpPath("crashes"); // 设置生成dump文件路径qBreakpadTest w;w.show();return a.exec();
}

qBreakpadTest 中添加按钮触发的崩溃代码如下:

void qBreakpadTest::on_pushButton_clicked()
{QLabel * label = nullptr;label->setText("crash");
}

4、生成dump文件

编译,运行程序,生成的dump文件,程序调试打印信息如下:

生成的dump文件如下:

前面我们说过需要dump调试信息,才能进行更细致的定位bug

目前dump文件已经生成,接下来了解如何生成调试信息

二、生成带调试信息的可执行程序

debug模式下,生成的可执行程序,默认就会带有调试信息。

但是我们期望的是,在release下也能生成,带有调试信息的可执行程序。毕竟交给客户的是release版,我们大多时候,也只是需要对release版程序进行bug定位。

所以,需要在qBreakpadTest.pro文件中,添加如下内容,让release版程序带上调试信息:

QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO

win系统下,程序的调试信息,是在单独的pdb文件中;在其他linux、mac等系统下,程序的调试信息就包含在程序本体内部,所以带调试信息的程序一般比不带调试信息的大。

将原来的exe更名为qBreakpadTest_no , 再次编译,可以看到,已经生成了带调试信息的程序qBreakpadTest

qBreakpadTest文件大小比不带调试信息时,大得多。

特别注意:

如果是主程序+多个so的开发方式,需要使用上述方法,将每个so也附带调试信息,这样,在so中发生崩溃时,才能根据dump和调试信息定位到so的代码上。

目前我们已经生成了带调试信息的程序,并且程序执行过程中发生崩溃,也可以自动记录dump文件,这两个东西已经具备,接下来,我们看看如何利用他们定位到bug所在位置。

三、生成dump_syms和minidump_stackwalk工具

Breakpad为我们提供了两个工具dump_symsminidump_stackwalk,我们将用他们来分析dump,定位bug

  • dump_syms,将程序导出符号文件;
  • minidump_stackwalk,生成堆栈调用信息,以便阅读。

所以我们需要准备一个干净的Breakpad源码,用于编译生成这两个工具。

1、将LSS源码放入src\third_party目录

首先准备好纯净的BreakpadLSS(linux-syscall-support)源码,就是之前第一次拉取我给的连接里面的源码即可,然后将LSS(linux-syscall-support)源码拷贝到breakpad\src\third_party\lss目录,该lss文件夹不存在,则新建之。如下:

可以看到是没有lss文件夹的,现在我们新建一个lss文件夹,然后将LSS源码放置进去,如下图:

2、编译、安装Breakpad

命令行进入源码目录

cd breakpad

如下图:

configure配置。若未知configure提供了哪些参数,可使用 ./configure -help

./configure

如果提示权限不够,则执行

chmod 755 configure

如下图

configure配置即可

执行完成以后,开始编译(编译需要一段时间)

sudo make


编译完毕后。

  • breakpad/src/tools/linux/dump_syms目录下,生成了dump_syms。如图所示:

  • breakpad/src/processor目录下,生成了minidump_stackwalk

同时还在breakpad/src目录下,生成了libbreakpad.a;以及在breakpad/src/client/linux目录下,生成了libbreakpad_client.a。但这里libbreakpad.alibbreakpad_client.a并不是我们关心的对象。

最后,进行安装。若要卸载,使用sudo make uninstall
安装命令:

sudo make install

安装完毕后,上述生成的文件会被拷贝到系统默认路径,使得我们可以直接在命令行中,使用这些工具。

四、使用dump_syms和minidump_stackwalk定位bug

依照前面的过程,到此我们得到了dump文件、带调试信息的程序文件,以及dump_symsminidump_stackwalk工具。

1、生成符号文件

我们使用dump_syms读取带调试信息的程序文件,并生成符号文件qBreakpadTest.sym

dump_syms ./qBreakpadTest > qBreakpadTest.sym


执行后如图所示:

特别注意:

需要将sym文件放置到特定路径下,方可在后续生成的堆栈信息中,查看到崩溃发生的文件名和行号。否则,堆栈信息中,只能看到内存地址。下一步,将介绍,如何放置到特定路径。

2、将符号文件移动到特定路径

我们在qBreakpadTest程序所在目录下,创建symbols目录,并在该目录下,继续创建如下的目录结构:

解释:

  • 第一级目录,固定为symbols
  • 第二级目录,为即将放入的符号文件名称,如qBreakpadTest.sym,则目录名为qBreakpadTest
  • 第三级目录,在sym文件中第一行内容,有一串16进制编号,将其作为目录名。如下图所示:

    建立好以上路径后,将qBreakpadTest.sym移动到此路径下。

3、生成崩溃处调用堆栈信息

crashes目录拷贝到和symbols目录一个级别目录下,如下图:

然后执行如下命令,生成调用堆栈信息:

minidump_stackwalk ./crashes/7211c8b8-126d-4de2-7f8f00a4-db86eecc.dmp ./symbols > error.log
  • 第一个参数,是dump文件名;
  • 第二个参数,固定为./symbols,应该是指定符号文件位于当前symbols目录下默认路径位置;
  • 第三个参数,将命令执行结果,写入到error.log文件中。

执行报错,没有找到一些模块,不用理会。如下:

生成的堆栈调用信息文件error.log,内容如下:

一般找到“crashed”字样,与它最近的一行,就是发生崩溃时,程序的调用堆栈,可以很清楚的看到,崩溃发生在qBreakpadTestcpp文件,第20行。

与我们编写的测试程序,预期效果,完全符合,如下:

到此,我们顺利通过dump文件、带调试信息的程序文件,成功定位到了bug所在

五、dump文件上报

qBreakpad还提供了上报dump文件的方法。说白了就是,将生成的dump文件上传到指定的服务器。

上报演示程序,位于qBreakpad\demo\reporter下,感兴趣可以去看看。

使用也是十分简单。

class QBreakpadHandler: public QObject
{Q_OBJECT
public:static QString version();QBreakpadHandler();~QBreakpadHandler();QString uploadUrl() const;QString dumpPath() const;QStringList dumpFileList() const;void setDumpPath(const QString& path);void setUploadUrl(const QUrl& url);public slots:void sendDumps();private:QBreakpadHandlerPrivate* d;
};

基本流程:

  • 先通过setDumpPath设置dump文件生成目录;以便在发生崩溃时,自动在该目录下生成dump文件。
  • 再通过setUploadUrl设置上报地址,以便后续将dump文件,上传到该地址。
  • 最后,通过sendDumpsdump文件发送至服务器。该函数会自动遍历,前面设置的dump生成目录,将每一个dump文件进行发送。

文件上传原理:QBreakpadHandlersendDumps函数,使用QNetworkAccessManagerpost()方法,来实现http协议方式的,文件上传。

上报功能,根据自身的需求,来确定有没有必要。此处不再举例说明。

六、总结

我们可以在自己的程序中,借助qBreakpad,很容易实现跨平台的,dump文件生成。

对于在程序中集成qBreakpad,实际就是,在程序中调用qBreakpad的静态库而已,非常的简单。

对于程序生成的dump文件,可以由用户直接发给我们,也可以由程序自动上报到我们的服务器上。

然后,我们拿到dump文件和带调试信息的程序文件,借助dump_symsminidump_stackwalk工具,就可以快速定位bug

特别注意:

  • 定位bug,至少需要dump带调试信息的程序,这两个文件。

关于其它,想自身程序在第一时间也拿到崩溃通知,可以参考上一篇Qt Windows系统使用QBreakpad实战 里面有详细阐述!

Qt Linux系统使用QBreakpad实战相关推荐

  1. qt linux系统获取当前时间(精确到毫秒、微秒)

    qt linux系统获取当前时间(精确到毫秒.微秒) Windows系统获取系统时间可以直接用SYSTEMTIME t;,将Windows平台程序移植到linux后,SYSTEMTIME将不再适用,如 ...

  2. Linux系统shell脚本实战之解决生产ddos攻击

    Linux系统shell脚本实战之解决生产ddos攻击 一.脚本于鏊求 二.脚本内容 三.执行脚本 一.脚本于鏊求 要求屏蔽掉ddos攻击的IP 二.脚本内容 [root@192 scripts]# ...

  3. qt linux系统隐藏任务栏图标

    使用 Qt::Tool, Qt::WindowStaysOnTopHint ,Qt::X11BypassWindowManagerHint三个任意一个都可以隐藏任务栏图标,但不同系统可能对应不同的设置 ...

  4. linux系统LAMP的实战应用

    部署wordpress论坛,并实现正常访问登录论坛 先保证虚拟机能够ping通外网 然后在这里面 安装一个清华的源 yum -y install https://mirrors.tuna.tsingh ...

  5. c linux time微秒_qt linux系统获取当前时间(精确到毫秒、微秒)-Go语言中文社区...

    qt linux系统获取当前时间(精确到毫秒.微秒) Windows系统获取系统时间可以直接用SYSTEMTIME t;,将Windows平台程序移植到linux后,SYSTEMTIME将不再试用,如 ...

  6. linux系统网络驱动简介

    网络设备驱动简介 网络设备驱动是linux内核中三大类设备驱动之一,它用来完成高层网络协议的底层数据传输及设备控制. 网络设备与其他两种设备的区别: 网络接口不存在于linux的文件系统中,及/dev ...

  7. Linux系统下Qt项目实战(原神模拟器)

    原神模拟器 <原神>是由上海米哈游网络科技股份有限公司制作发行的一款开放世界冒险游戏.         <原神>整体的玩法架构可圈可点,基于行业成熟设计经验打造的内容十分惊艳, ...

  8. 迅为IMX6ULL教程更新至2060+页,裸机开发,Linux系统移植,驱动开发,构建文明系统,QT开发,系统编程

    教程更新至2060+页 彻底让零基础的同学真正学会 更完善的教程更全面的讲解更高效的学习 第一部分 总领及学习指引:主要探讨的学习方法,我们将尽量用比较简洁的方式,让大家明白嵌入式系统知识体系,以及它 ...

  9. qt工程在linux系统里颜色显示错误_【飞凌嵌入式RK3399开发板试用体验】+QT开发环境搭建测试(二)...

    作者:飞扬的青春 在拿到开发板之后,已经体验了Android操作系统,接下来就是体验Linux下的开发,本次以QT的一个小案例来测试下. 首先是自己先搭建了一个Ubuntu18.04的虚拟机,使用真机 ...

最新文章

  1. elasticsearch简单操作(二)
  2. html5 居于页面中心,css笔记:如何让一个div居于页面正中间
  3. Apache主配置文件httpd.conf 详解
  4. configure project qt,如何为Qt Framework配置CLion IDE?
  5. MongoDB 计划从“Data Sprawl”中逃脱
  6. powerdesigner辅助导入导出excel文件
  7. zxr10交换机配置手册vlan_中兴ZXR10 G系列交换机SVLAN使用指导
  8. 递归法:财务金额漏掉1笔或者几笔(排列组合)
  9. mt4 显示服务器时间,MQL4编程学习之MT4显示任意时间周期指标的使用方法
  10. Globle.asax错误:异常详细信息: S…
  11. 关于谷歌浏览器安装油猴插件失败的解决方法
  12. 语音识别使用推荐(讯飞、百度、腾讯、云知声等)
  13. fuchsia中virtio 后端实现
  14. ESP32 驱动WS2812B 灯条
  15. EBCDIC、ASCII与EBCDIC的关系及相互转化
  16. iOS 15 UITableView Section间距变大
  17. 银行软件测试面试题目总结,希望可以帮到你
  18. SolrCloud下DIH实践
  19. 数学建模——BP神经网络学习笔记
  20. DirectUI与QQ界面

热门文章

  1. burpsuit抓手机模拟器的包
  2. GLib-CRITICAL **: g_main_context_pop_thread_default: assertion `g_queue_peek_head (stack) == context
  3. 外贸独立站该如何选择跨境支付方式?
  4. 55 | Linux系统启动报错No bootable device
  5. 记录断舍离,极简生活的开始
  6. three.js实现火焰效果
  7. 1279:【例9.23】橱窗布置(flower)
  8. 安装Office 2019
  9. CentOS下主DNS、辅助DNS以及子域DNS的配置
  10. css中首字母下沉_CSS首字母大而精美的首字下沉