文章目录
前言
目前参与的项目需要从 Windows 平台移植到 arm-Linux 平台,之前项目上使用的异常奔溃收集库不适用于 Linux,因此亟需一个跨平台的奔溃采集库(实在不想维护两套代码)。这时我们发现了 google breakpad ,由于是基于 Qt 的开发,我还注意到了 qBreakpad 这个开源项目。
Google - Breakpad
Breakpad 是 Google 公司开发的开源 跨平台C++崩溃检测库。Breakpad可以捕获发布给用户的应用程序的崩溃,并记录软件崩溃的调试信息到 minidump 文件中。调试信息包括错误行号,报错详情,堆栈错误(stack traces)。
qBreakpad
qBreakpad 是一个使用 google-breakpad 的Qt第三方库,可以很方便的用于检测软件奔溃。但是这个项目最近一次维护是在4年前了,使用时发现了一些错误,想提交到 GitHub,但苦于没有 ISS,目前的想法是自行维护并开源…git地址确定后将在留言放出。当然遇到的那些坑,在本文也会告知解决方法。
编译
Breakpad
本地编译 x86_64_linux
根据 Breakpad 的 GitHub-README ,编译非常简单:
# 克隆仓库
git clone https://github.com/cmzy/beakpad.git
# 如果嫌github慢,可使用 https://gitee.com/jyu_hsy/breakpad.git
cd breakpad
# configure 配置,若未知configure提供了哪些参数,可使用 ./configure -help
./configure
# make it
sudo make
由于这里最终的目标是 qBreakpad,这里的编译只是为了生成所需的 dump_syms & microdump_stackwalk 而已,通过以下指令查看其文件类型:
# 我目前只用到dump_syms & microdump_stackwalk
file beakpad/src/tools/linux/dump_syms
file beakpad/src/processor/microdump_stackwalk
ps:编译时会提示找不到 /breakpad/src/third_party/lss/linux_syscall_support.h
这时需要将 linux-syscall-support 拉取下来,然后将 linux_syscall_support.h 放到指定路径:
git clone https://gitee.com/jyu_hsy/linux-syscall-support.git
cp linux-syscall-support/lss/linux_syscall_support.h ./breakpad/src/third_party/lss
交叉编译 arm_linux
若之前已经配置了 configure,建议删除后重新克隆项目:
# 克隆仓库
git clone https://github.com/cmzy/beakpad.git
# 如果嫌github慢,可使用 https://gitee.com/jyu_hsy/breakpad.git
cd breakpad
# configure 配置,若未知configure提供了哪些参数,可使用 ./configure -help
# 交叉编译设置
export CC=aarch64-linux-gnu-gcc
export CXX=aarch64-linux-gnu-g++
./configure --host=aarch64-linux-gnu
sudo make
# 嫌慢的可以使用 sudo make -j4
ps:
这里生成的 dump_syms & microdump_stackwalk 是在目标板上运行的,我们同样可以通过 file 查看其类型。
qBreakpad
源码下载
git clone --recursive https://github.com/buzzySmile/qBreakpad.git
# 这里使用 --recursive 将会去克隆以下两个项目:
# google-breakpad [master]- https://chromium.googlesource.com/breakpad/breakpad
# linux-syscall-support [master] - https://chromium.googlesource.com/linux-syscall-support
# 由于某些原因我们是克隆不下来的,因此建议使用:
git clone https://github.com/buzzySmile/qBreakpad.git
git clone https://github.com/cmzy/beakpad.git
git clone https://github.com/adelshokhy112/linux-syscall-support.git
# 然后将 beakpad 放至qBreakpad/third_party/beakpad
# 然后将 linux-syscall-support/lss 放至qBreakpad/third_party
qBreakpad 编译
QTCreator打开qBreakpad/handler/handler.pro- 选择你的
Kits构建即可(这里可以是本地编译也可以是交叉编译,取决于你的Kits) - 构建完成,我们将得到
qBreakpad.a
使用
使用过程遇到问题请先查看本文 Q&A 部分!
添加静态库
//project.pro
# link qBreakpad library
unix:!macx: LIBS += -L$$PWD/qbreakpad -lqBreakpad
INCLUDEPATH += $$PWD/qbreakpad
DEPENDPATH += $$PWD/qbreakpad
unix:!macx: PRE_TARGETDEPS += $$PWD/qbreakpad/libqBreakpad.a
使用静态库
//main program
#include <QBreakpadHandler.h>
//...
QBreakpadInstance.setDumpPath(QLatin1String("crashes"));
//...
添加debug设置
//project.pro
# 生成调试信息
QMAKE_CFLAGS_RELEASE += -g
QMAKE_CXXFLAGS_RELEASE += -g
# 禁止优化
QMAKE_CFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE -= -O2
dump_syms
添加完成后,在软件奔溃时,将在 ./crashes(当然这取决于你的 setDumpPath() )路径下生成 dmp 文件,dmp文件并不能直接查看,我们使用 dump_syms读取调试信息并生成Breakpad 符号文件。
./dump_syms ./appname > appname.sym
minidump_stackwalk
tools / minidump_stackwalk 可以获取一个 minidump 及其相应的符号,并产生一个符号化的 stacktrace。通常我们需要重定向一下:
./minidump_stackwalk -s xxx.dmp appname.sym > error.log
error.log
查看 error.log,我们只能看到奔溃时堆栈地址,例如在主程序 0x835c 上奔溃,我们可以直接使用以下指令查看奔溃的具体函数及其所处的行号:
addr2line 0x835c -e appname -f
debug lib.so
对于动态库,若想通过 dump 定位,需要在编译动态库时加上 -g 并 禁止优化, Qt Project 中配置如下:
//libprojectname.pro
TEMPLATE = lib
#加入调试信息
QMAKE_CFLAGS_RELEASE += -g
QMAKE_CXXFLAGS_RELEASE += -g
#禁止优化
QMAKE_CFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE -= -O2
重新编译生成 testosapp 后,通过 minidump_stackwalk 生成 error.log,·假设 error.log 如下:
Operating system: Linux
0.0.0 Linux 4.4.194-59119-g968ba5005831 #583 SMP Tue Jul 14 15:10:24 CST 2020 aarch64
CPU: arm64
6 CPUs
GPU: UNKNOWN
Crash reason: SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: not available
Thread 0 (crashed)
0 libtestos.so.1 + 0x6d0
x0 = 0x0000000000000000 x1 = 0x0000000000000001
x2 = 0x0000000000000000 x3 = 0x0000007f980063c0
x4 = 0x00000055aeb65ca0 x5 = 0x0000000000000000
x6 = 0x0000007fd4414590 x7 = 0x0000000000000000
x8 = 0x0000000000000042 x9 = 0x000002180093006e
x10 = 0x0000000000000000 x11 = 0x0000000000000010
x12 = 0x0000007fa337faf8 x13 = 0x0000000000000000
x14 = 0x0000000000000093 x15 = 0x000000000000006e
x16 = 0x000000557a081b80 x17 = 0x0000007fa396c6bc
x18 = 0x0000000000ff0000 x19 = 0x00000055aeb65ca0
x20 = 0x0000007fd4414590 x21 = 0x0000000000000000
x22 = 0x0000007fa31d5230 x23 = 0x0000000000000026
x24 = 0x0000000000000001 x25 = 0x0000000000000000
x26 = 0x0000000000000001 x27 = 0x0000007fd44135f8
x28 = 0x0000007f8c0117f0 fp = 0x0000007fd4413410
lr = 0x000000557a056438 sp = 0x0000007fd44133f0
pc = 0x0000007fa396c6d0
Found by: given as instruction pointer in context
//...
同样可以通过以下指令查看库中的奔溃位置:
addr2line 0x6d0 -e libosname -f
Q&A
Q1:
qt.qpa.plugin: Could not find the Qt platform plugin “eglfs” in “”
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
A1:
将 libEGL.so & libGLESv2.so 移动至 /usr/lib 即可。
Q2:
使用qBreakpad.a时出现:
/home/hsy/SW/Qt5.9.3/Project/test-qBreakpad/qBreakpad/libqBreakpad.a(exception_handler.o):在函数‘google_breakpad::ExceptionHandler::SimulateSignalDelivery(int)’中:
exception_handler.cc:(.text+0xef4):对‘breakpad_getcontext’未定义的引用
/home/hsy/SW/Qt5.9.3/Project/test-qBreakpad/qBreakpad/libqBreakpad.a(exception_handler.o):在函数‘google_breakpad::ExceptionHandler::WriteMinidump()’中:
exception_handler.cc:(.text+0x11e2):对‘breakpad_getcontext’未定义的引用
A2:
检查后发现问题出在我们构建动态库的工程中:
// in handler - breakpad.pri
// Add this code:
SOURCES += $$BREAKPAD_PATH/common/linux/breakpad_getcontext.S \
Q3:
使用
qBreakpad.a时出现:error:reference to 'once_flag' is ambiguous
A3:
该问题主要出现在使用了 std 的项目中,std 中也定义了 once_flag。
因此需要修改我们的头文件cell_once.h:
inline static void qCallOncePerThread(Function func)
{
using namespace CallOnce;
if (!CallOnce::once_flag()->hasLocalData()) {
CallOnce::once_flag()->setLocalData(new QAtomicInt(CO_Request));
qCallOnce(func, *CallOnce::once_flag()->localData());
}
}
参考鸣谢
12.5-使用Qt实现跨平台C++崩溃捕获,看这一篇就足够了(Breakpad)
google breakpad /qbreakpad 在 arm移植


1156

被折叠的 条评论
为什么被折叠?



