Linux下Qt breakpad编译使用

news/2024/9/12 19:09:58

一、下载安装包

  • 下载qbreakpad源码:
git clone https://github.com/buzzySmile/qBreakpad.git
  •  下载breakpad源码
git clone https://github.com/google/breakpad
  • 下载linux-syscall-support
    没有这个文件,编译报错
git clone https://github.com/adelshokhy112/linux-syscall-support.git

 二、编译

第一步:

cd breakpad

第二步:

./configure

cxx@cxx-virtual-machine:~/Demo/breakpad$ ./configure  

 第三步:把linux-syscall-support目录下的lss文件拷贝到breakpad/src/third_party,如下图

 第四步:编译 

make -j12

注意:

如果make提示以下错误

 ./third_party/lss/linux_syscall_support.h: In member function ‘bool google_breakpad::ExceptionHandler::GenerateDump(google_breakpad::ExceptionHandler::CrashContext*)’:
./third_party/lss/linux_syscall_support.h:2146:75: error: listing the stack pointer register ‘rsp’ in a clobber list is deprecated [-Werror=deprecated]
 2146 |                              : "rsp", "memory", "r8", "r10", "r11", "rcx");
      |                                                                           ^

 则修改/lss/linux_syscall_support.h,如下图

 重新编译

make -j12

出现以下信息,则编译成功

 第四步:

sudo make install

查看生成文件路径

which dump_syms

cxx@cxx-virtual-machine:~/Demo/breakpad$ which dump_syms
/usr/local/bin/dump_syms
cxx@cxx-virtual-machine:~/Demo/breakpad$ cd /usr/local/bin
cxx@cxx-virtual-machine:/usr/local/bin$ ls
core2md    dump_syms_mac        minidump-2-core  minidump_stackwalk  pid2md
dump_syms  microdump_stackwalk  minidump_dump    minidump_upload     sym_upload

 Qt中如何运用

在.pro文件中添加 

INCLUDEPATH +=/usr/local/include/breakpad
LIBS +=/usr/local/lib/libbreakpad_client.a
LIBS +=/usr/local/lib/libbreakpad.a

在main.cpp中添加头文件和

#include "client/linux/handler/exception_handler.h"
#include "client/linux/handler/minidump_descriptor.h"
#include "mainwindow.h"
#include <iostream>
#include <QApplication>
#include "client/linux/handler/exception_handler.h"
#include "client/linux/handler/minidump_descriptor.h"
using namespace std;

using namespace google_breakpad;

bool minidumpDB(const MinidumpDescriptor& descriptor,void* context,bool succeeded)
{
    if(succeeded){
        std::cout<<"Mini Dump file:"<<descriptor.path()<<std::endl;
    }
    return succeeded;
}
int crash(int a,int b){
    return a/b;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //路径为生成.dmp文件的路径
    google_breakpad::MinidumpDescriptor descriptor("/home/cxx/Demo/build-breakTest-Desktop_Qt_5_14_2_GCC_64bit-Debug");
    google_breakpad::ExceptionHandler eh(descriptor,NULL,minidumpDB,NULL,true,-1);
    MainWindow w;
    w.show();
    crash(5,0);
    return a.exec();
}

在生成的可执行文件目录下,创建一个breakpad.sh文件:

 breakpad.sh文件,内容如下

# -*- coding: utf-8 -*-
import os 
import sys
import subprocess
import shutil
import traceback

ENVPATH = "/usr/local/bin"
def track_error():
    error_message=""
    (type,value,trace)=sys.exc_info()
    print("**************************************************************")
    print("Error_Type:\t%s\n"%type)
    print("Error_Value:\t%s\n"%value)
    print("%-40s %-20s %-20s %-20s\n"%("Filename", "Function","Linenum", "Source"))
    for filename, linenum, funcname, source in traceback.extract_tb(trace):
        print("%-40s %-20s %-20s%-20s" % (os.path.basename(filename),funcname,linenum, source))
    print("**************************************************************")

class RunDump(object):
    def __init__(self,m_app):
        self.current = os.path.abspath(os.path.dirname(m_app))
        self.appname = os.path.basename(m_app)
        self.app = os.path.abspath(m_app)
        self.symbols = os.path.join(self.current,"symbols")
        self.dump = None
        self.symfile = "%s.sym"%(self.app)
        self.mkdirpath = None
       

        self.Run()

    def __del__(self):
        if  os.path.exists(self.symbols):
            shutil.rmtree(self.symbols)
        if self.dump:
            os.remove(self.dump)
    def Get_Dump(self):
        dmp = list(filter(lambda file:  os.path.splitext(file)[-1] == ".dmp",os.listdir(self.current)))
        if dmp == list():
            print("dmp file not exist...")
            exit(1)
        self.dump = os.path.join(self.current,dmp[-1])
        
      
    def RunCmd(self,cmd):
        new_env = os.environ.copy()
        new_env["PATH"] = ENVPATH
        pid = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True,env = new_env)
        for i in pid.communicate():
            if len(i)>0:
                print(i)
        return pid.wait()
    
    def readlline(self):
        line = ""
        with open(self.symfile) as fd:
            for line in fd:
                break
        linemd5 = line.split()[-2]
        self.mkdirpath = os.path.join(self.symbols,self.appname,linemd5)
        os.makedirs(self.mkdirpath,exist_ok = True)   
        shutil.move(self.symfile,self.mkdirpath)
        print("symbols目录生成:%s"%self.mkdirpath )

    def Run(self):
        self.Get_Dump()
        self.CreatSym()
        self.readlline()
        self.CreatDump()

    def CreatSym(self):
        cmd = "dump_syms %s>%s"%(self.app,self.symfile)
        if self.RunCmd(cmd):
            print("%s 运行出错"%cmd)
            exit(1)
        else:
            print("生成sym文件:%s"%self.symfile)
         
    def CreatDump(self):
        sysmbols = os.path.join(os.path.join(self.current,"symbols"))
        creashlog = os.path.join(os.path.join(self.current,"crash.log"))
        errorlog = os.path.join(os.path.join(self.current,"error.log"))
        cmd = "minidump_stackwalk %s %s >%s 2>%s"%(self.dump,sysmbols,creashlog,errorlog)
        if self.RunCmd(cmd):
            print("%s 运行出错"%cmd)
        else:
            print("crash.log生成成功:%s"%creashlog)
    

if __name__ == "__main__":
    if len(sys.argv[:])<2:
        print("""输入命令:./Breakpad.py  AppPath 
            AppPath:程序app 所在路径
        """)
        exit(1)
    try:
        app = sys.argv[1]
        RunDump(app)
    except BaseException:
            track_error()

 执行程序,即可在可执行目录下生成一个dmp文件

 执行dmp解析

python3 breakpad.py ./breakTest

cxx@cxx-virtual-machine:~/Demo/build-breakTest-Desktop_Qt_5_14_2_GCC_64bit-Debug$ python3 breakpad.py ./breakTest 
生成sym文件:/home/cxx/Demo/build-breakTest-Desktop_Qt_5_14_2_GCC_64bit-Debug/breakTest.sym
symbols目录生成:/home/cxx/Demo/build-breakTest-Desktop_Qt_5_14_2_GCC_64bit-Debug/symbols/breakTest/EC33EEC8E77904C93D41C11D6FAE6E180
crash.log生成成功:/home/cxx/Demo/build-breakTest-Desktop_Qt_5_14_2_GCC_64bit-Debug/crash.log 

 生成crash.log 和error.log文件

 打开crash.log,即可看到记录到的详细错误信息。

dmp 解析脚本:

GitHub - heisai/breakpad: breakpad 解析生成log


http://lihuaxi.xjx100.cn/news/1305188.html

相关文章

(0019) H5-Vue路由中引入组件Component的三种方式

一 普通引入方式 import login from ‘/components/login’优点: 易理解&#xff0c; 缺点:webpack在打包的时候会把整个路由打包成一个js文件&#xff0c;如果页面一多&#xff0c;会导致这个文件非常大&#xff0c;加载缓慢二 Vue异步组件技术 component: (resolve) > re…

kong-dashboard安装

简介 kong-dashboard提供了UI界面操作和查看kong&#xff0c;可以进行api、consumers、plugins操作 官网&#xff1a;https://hub.docker.com/r/pgbi/kong-dashboard/ 安装 联网安装 [slviewDEMO:~]$ docker search kong-dashboard INDEX NAME …

C++思维,作业7.3

#include <iostream> #include <cstring> using namespace std; int monster_blood10000; //英雄 class Hero { protected:string name;int hp;int attck; public:Hero(){//cout << "Hero的无参构造" << endl;}Hero(string name,int hp,int …

vue项目使用luckyexcel插件预览excel表格

温馨提示&#xff1a;需要用到luckysheet文件和luckyexcel插件&#xff0c;根据下面步骤一步一步操作会避免踩坑&#xff0c;比如我当时遇到了window.luckysheet is not defined控制台报红的问题。 第一步 引入luckysheet的相关依赖&#xff08;本地文件或者在线cdn引入&#…

ASIC数字设计:前端设计、验证、后端实现

前端设计 数字系统设计中有三个重要的设计级别概念&#xff1a;行为级&#xff08;Behavior Level&#xff09;、寄存器传输级&#xff08;Register Transfer Level&#xff09;和门级&#xff08;Gate level&#xff09;。其中&#xff0c; 行为级通过行为级算法描述数字系统&…

Python|Pyppeteer实现自动登录TextNow并获取cookie(15)

前言 本文是该专栏的第15篇,结合优质项目案例持续分享Pyppeteer的干货知识,记得关注。 本文以TextNow自动登录为例,使用puppeteer的python版本pyppeteer来实现。 对于pyppeteer比较陌生的同学,笔者这里暂时不详述了,对pyppeteer知识点感兴趣的同学,可查看本专栏前面详细…

Java性能权威指南-总结23

Java性能权威指南-总结23 数据库性能的最佳实践JDBCJDBC驱动程序预处理语句和语句池JDBC连接池 数据库性能的最佳实践 此部分主要探讨由Java驱动的数据库应用的性能。访问数据库的应用程序经常会受制于一些与Java不直接相关的性能问题&#xff0c;譬如使用的数据库有I/O瓶颈&a…

git学习使用技巧

目录 关于版本控制 本地版本控制系统 集中化的版本控制系统 分布式版本控制系统 Git 是什么 直接记录快照&#xff0c;而非差异比较 近乎所有操作都是本地执行 Git 保证完整性 Git 一般只添加数据 三种状态 起步 - 初次运行 Git 前的配置 初次运行 Git 前的配置 用户…