google breakpad native crash分析工具
一. BreakPad简介
Google breakpad是一个跨平台的崩溃转储和分析框架和工具集合。
Breakpad由三个主要组件:
- client,以library的形式内置在你的应用中,当崩溃发生时写 minidump文件
- symbol dumper, 读取由编译器生成的调试信息(debugging information),并生成 symbol file
- processor, 读取 minidump文件 和 symbol file ,生成可读的c/c++ Stack trace.
简单来说就是一个生成 minidump,一个生成symbol file,然后将其合并处理成可读的Stack trace。
二. MiniDump文件格式
minidump文件格式是由微软开发的用于崩溃上传,它包括:
- 当dump生成时进程中一系列executable和shared libraries, 包括这些文件的文件名和版本号。
- 进程中的线程列表,对于每个线程,minidump包含它在寄存器中的状态,线程的stack memory内容。这些数据都是未解析的字节流,Breakpad client通常没有调试信息(debugging information)能生成函数名,行号,甚至无法确定stack frame的边界。
- 其他收集关于系统的信息,如:处理器,操作系统高版本,dump的原因等等。
breakpad在所有平台上(windows/linux等)都统一使用minidump文件格式,而不使用core files,原因是因为:
- core files可能很大,而minidump比较小。
- core files文档不全
- 很难说服windows机器去生成core files,但可以说服其他机器来生成minidump文件。
- breakpad只支持一种统一的格式会比较简单,而不是同时支持多种格式。
什么是core files?core files是unit系统上程序崩溃时生成的文件。
参见:http://www.jianshu.com/p/8e1352a9638f
三. Symbols文件格式
symbols文件是基于纯文本的,每一行一条记录,每条记录中的字段以一个空格作为分隔符,每条记录的第一个字段表示这一行是什么类型的记录。
记录类型:
- 模块记录:
MODULE
operatingsystem architecture id name - 文件记录:
FILE
number name - 函数记录:
FUNC
address size parameter_size name - 行号记录:address size line filenum
- PUBLIC记录:
PUBLIC
address parameter_size name STACK WIN
STACK CFI
参见:https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
四. 不同平台的实现原理
默认情况下,当崩溃时breakpad会生成一个minidump文件,在不同平台上的实现机制不一样:
- 在windows平台上,使用微软提供的
SetUnhandledExceptionFilter()
方法来实现。
- 在OS X平台上,通过创建一个线程来监听
Mach Exception port
来实现。
- 在Linux平台上,通过设置一个信号处理器来监听
SIGILL
SIGSEGV
等异常信号。
当minidump被生成后,在不同平台上也使用不同的机制来上传crash dump文件。
参见:Windows SetUnhandledExceptionFilter参见:Mac OS X Exception handling参见:Catching Exceptions and Printing Stack Traces for C on Windows, Linux, & Mac
五. 异常处理机制
提供两种不同的异常处理机制:
- 同进程(in-process)
- 跨进程(out-precess)
因为在崩溃的进程写minidump文件是不安全的,所以三个平台(windows、linux、mac os)都提供跨进程的异常处理机制。
六. 在Linux平台使用breakpad
这里因为要研究Android上使用breakpad,所有主要研究linux平台,windows和mac平台的使用方法请自行参考文档。
6.1 构建Breakpad库
breakpad提供自动构建工具来构建linux client库和processor库。
在breakpad源码目录下通过运行命令:
./configure
make
将自动生成 src/client/linux/libbreakpad_client.a
文件, 其包含了在你的应用中生成minidumps文件的必要代码。
6.2 在你的应用中使用Breakpad
首先配置build precess来link刚生成的 libbreakpad_client.a
文件。
然后设置 include paths 来 包含 google-breakpad 目录下的 src 目录。
接下来include头文件:
#include "client/linux/handler/exception_handler.h"
现在你就可以初始化 ExceptionHandler
对象,初始化的时候需要提供一个用于写minidump文件的目录,以及一个回调函数用于在minidump文件写完以后调用。
int main(int argc, char* argv[]) {// 初始化ExceptionHandlergoogle_breakpad::MinidumpDescriptor descriptor("/tmp"); // minidump文件写入到的目录google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);crash();return 0;
}// 写完minidump后的回调函数
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,void* context, bool succeeded) {printf("Dump path: %s\n", descriptor.path());return succeeded;
}// 触发crash来测试
void crash() {volatile int* a = (int*)(NULL);*a = 1;
}
编译并运行这个实例应该会在 /tmp 目录下生成 minidump 文件,并且终端下会输入minidump文件的路径。
关于初始化ExceptionHandler可以接受的参数需要参见源码
ExceptionHandler(const MinidumpDescriptor& descriptor,FilterCallback filter,MinidumpCallback callback,void* callback_context,bool install_handler,const int server_fd);
具体参数:
- descripter,minidump文件写入的目录
- filter,可选,在写minidump文件之前,会先调用filter回调。根据它返回true/false来决定是否需要写minidump文件。
- callback, 可选,在写minidump文件之后调用的回调函数
- callback_context,
- install_handler, 如果为ture,不管怎样当未捕捉异常被抛出时都会写入minidump文件,如果为false则必须明确调用了
WriteMinidump
才会写入minidump 文件 - server_fd, 如果为-1,则使用同线程模式(in-precess),如果有一个有效的值,则使用跨线程模式(out-of-process)
参见:exception_handler.h源码
需要注意的是,你必须在callback回调函数中做尽量少的工作,因为你的程序处于一个不安全的状态,它需要无法安全的去分配内存,或调用其他共享库中的函数。安全的方式是 fork
和 exec
一个新进程去做想要做的事情。如果你需要在回调中做一些工作,breakpad源码提供一些简单的重新实现的libc库里的方法,来避免直接调用libc, 并提供一个a header file for making linux system calls,来避免直接调用其他共享库的方法。
6.3 发送minidump文件
在真实环境中,你通常需要以某种方式来处理minidump文件,例如把它发送给服务器来进行分析,Breakpad源码提供了一些HTTP上传的代码,并提供一个minidump上传工具( 详见minidump_upload.cc)。
6.4 生成symbols文件
为了生成可读的stack trace, breakpad需要你将binaries里的调试符号(debugging symbols)转换成基于文本格式的symbol files。
首先确保你在编译代码的时候加上 -g
参数来生成带调试符号的。
然后使用 configure && make
breakpad源码来生成 dump_syms
工具。
接着运行 dump_syms
命令来生成 symbol files,如下:
$ google-breakpad/src/tools/linux/dump_syms/dump_syms ./test > test.sym
为了可以使用 ``minidump_stackwalk` 工具来生成stack trace,你需要将文件放置在一定的目录结构,symbol file的第一行说明了需要放置的目录结构,可以使用命令,或使用 Mozilla 提供的 symbolstore.py 工具来新建这样的目录结构。
$ head -n1 test.sym
// MODULE Linux x86_64 6EDC6ACDB282125843FD59DA9C81BD830 test
$ mkdir -p ./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
$ mv test.sym ./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
6.5 生成Stack Trace
breakpad包含一个叫做 minidump_stackwalk
的工具来将 minidump 文件,外加symbol files来生成一个人可读的stack trace。在编译breakpad后,这个工具一般在 google-breakpad/src/processor
目录下, 通过将 minidump 和 symbol files 传入给它即可:
$ google-breakpad/src/processor/minidump_stackwalk minidump.dmp ./symbols
它会生成verbose output到stderr, stacktrace到stdout。
参见:How To Add Breakpad To Your Linux Application
七. 在Android平台使用Breakpad
Breakpad支持 ARM x86 和 MIPS 架构的Android系统。需要Android NDK r11c及以上版本。
7.1 构建client库
Android版本的Client库设计为一个静态库(static library)来使得你可以链接到你的Android native代码里。
一共有两种方法来build。
7.1.1 方法1:使用ndk-build构建(推荐)
使用ndk-build来构建,需要如下几个步骤:
- 在你的项目中的 Android.mk 中 include google-breakpad的 Android.mk
include $(LOCAL_PATH)/breakpad/android/google_breakpad/Android.mk
- 链接break-client未你的静态库模块
LOCAL_STATIC_LIBRARIES += breakpad_client
- 因为需要c++ STL,所以还需要在
Application.mk
文件中加入 STL 支持:
APP_STL := stlport_static
7.1.2 方法2:使用Android toolchain构建
$GOOGLE_BREAKPAD_PATH/configure --host=arm-linux-androideabi \--disable-processor \--disable-toolsmake -j4
将会build到 src/client/linux/libbreakpad_client.a 文件。
可使用 make check
来在Android设备上运行测试。
7.2 在Android上使用Breakpad
在Android平台上使用breakpad,基本和在linux平台上是基本类似的。
需要如下几个步骤:
- 在cpp文件中include exception_handler头文件
#include "client/linux/handler/exception_handler.h"
- 如果使用ndk-build,需要配置include path(在Android.mk文件中)
LOCAL_C_INCLUDES := $(GOOGLE_BREAKPAD_PATH)/src/common/android/include \$(GOOGLE_BREAKPAD_PATH)/src
并且加上 -llog flag
LOCAL_LDLIBS := -llog
- 时刻记住在Android系统上没有
/tmp
目录,需要指定一个其他目录,可以是 application 专有目录(/data/data/packageName/files),或者存储到SDCard上面去(需要写入权限)
7.3 生成stack trace
这个操作和其他平台一样。
- 从设备上获取minidumps文件
- 使用dump_syms工具生成so的symbol files
dump_symc $PROJECT_PATH/obj/local/$ABI/libfoo.so > libfoo.so.sym
- 创建symbol files专有目录结构
// MODULE Linux x86_64 6EDC6ACDB282125843FD59DA9C81BD830 test$PROJECT_PATH/symbols/libfoo.so/6EDC6ACDB282125843FD59DA9C81BD830/libfoo.sym
- 使用
minidump_stackwalk
来生成stack trace:
minidump_stackwalk $MINIDUMP_FILE $PROJECT_PATH/symbols
参见:breakpad for android 官方文档
作者:骆驼骑士
链接:https://www.jianshu.com/p/295ebf42b05b
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关文章:

Java基础教程(15)--枚举类型
枚举类型定义了一个枚举值的列表,每个值是一个标识符。例如,下面的语句声明了一个枚举类型,用来表示星期的可能情况: public enum Day {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY } 实际上,这个…

基于AOA协议的android USB通信
摘 要:AOA协议是Google公司推出的用于实现Android设备与外围设备之间USB通信的协议。该协议拓展了Android设备USB接口的功能,为基于Android系统的智能设备应用于数据采集和设备控制领域提供了条件。介绍了Android系统下USB通信的两种模式,并给…

Linux下使用ssh动态验证码登陆机器
ssh动态验证码登录机器Google Authenticator是一个动态验证码程序,兼容各种智能手机平板设备,可以用来做各种帐号的二次验证,增加帐号的安全性。SSH是Linux系统的最重要防线之一,为了防止密码泄露或者被爆破,可以使用G…
【C++】枚举类型应用
运行环境:VS2017 可以参考:【C】枚举类型 医院内科有A,B,C,D,E,F,G共七位医生,每人在一周内要值一次夜班,排班的要求: (1ÿ…

量子力学又一突破,中国科学家首次实现量子纠缠态自检验
这也是国际上首个具有“高可靠、抗干扰”特性的纠缠态自检验实验。 最近,量子力学领域又传来好消息,中国科学技术大学的郭光灿院士团队在实验中首次实现了量子纠缠态的自检验,推动了自检验在各种量子信息过程中的基础发展。 何为量子纠缠&a…

awk命令中执行多条shell命令
awk中使用的shell命令,有2种方法:一。使用system()二。使用print cmd | “/bin/bash”http://www.gnu.org/software/gawk/manual/gawk.html#I_002fO-Functions一。使用所以system()awk程序中我们可以使用sy…

LAMP高级环境实战
LAMP架构应用实战介绍LAMP指的Linux(操作系统)、Apache(HTTP 服务器),MySQL(数据库软件) 和PHP(有时也是指Perl或Python) 的第一个字母,一般用来建立web 服务…

【C++】用类来处理排序问题
运行环境:VS2017 由小到大排序 可以看出在主函数中所做的事: (1)定义对象。 (2)向各对象发出“消息”,通知各对象完成有关任务。即调用有关对象的成员函数,去完成相应的操作。 …

winform 弹出窗体位置设定
[转]https://www.cnblogs.com/liushenglin/p/5350641.html 一、C#中弹出窗口位置 加入命名空间using System.Drawing和using System.Windows.Forms假定窗口名为form1,则 form1.StartPosition FormStartPosition.CenterScreen;窗体位置在屏幕中间form1.StartPosition FormSta…
pkg-config工具在实际工程中的用法
在如今这个开源的环境里,想要开发某个功能,我们都会下意识的上网搜索有没有开源库,如果有开源库,那么好,下载下来给它编译好,使用。但是在使用过程中,你是否遇到不知如何将第三方库编译…

linux中pipe
调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过filedes参数传出给用户程序两个文件描述符,filedes[0]指向管道的读端,filedes[1]指向管道的写端(很好记就像0是标准输入1是标准输出一样)。所以管道在用户程序看起来就像一个打开的文通r…
【C++】利用构造函数对类对象进行初始化
运行环境:VS2017 一、对象的初始化 每一个对象都应当在它建立之时就有就有确定的内容,否则就会失去对象的意义。 class Time {int hour 0;int min 0;int sec 0; }; 这种是错误的,类并不是一个实体,并不占储存空间ÿ…

自定义Chrome浏览器
一、全局 自用备份,窗体透明化、要添加对应网站的窗体class到对应的位置 /*主页背景*/ /*https://images.cnblogs.com/cnblogs_com/AardWolf/1350846/o_5900399dcdcbd.jpg*/ /*https://ws4.sinaimg.cn/large/0072Vf1pgy1foxkfzphb2j31hc0u0gvv.jpg*/body { backgrou…

ubuntu添加sudo权限
使用如下命令可以添加到用户组(也可是超级用户组)。 命令如下: sudo usermod -aG 超级用户组名 用户名 例子:sudo usermod -aG sudo username 其中a:表示添加,G:指定组名第二种方法是直接修改,…

File.separator
报告“No such file or diretory ”的异常,上传不了。后来发现是文件路径的问题。模拟测试环境是windowstomcat,而正式的的环境是linuxtomcat,文件路径的分隔符在windows系统和linux系统中是不一样。 比如说要在temp目录下建立一个test.txt文…
【C++】对象数组
运行环境:VS2017 对象数组:每个元素都是同类的对象 如果构造函数只有一个参数,在定义数组时可以直接在等号后面的花括号内提供实参。 Student stud[3]{60,70,80}; 如果构造函数有多个参数,则不能用在定义数组时直接提供所有实…

C# 算法系列一基本数据结构
一、简介 作为一个程序员,算法是一个永远都绕不过去的话题,虽然在大学里参加过ACM的比赛,没记错的话,浙江赛区倒数第二,后来不知怎么的,就不在Care他了,但是现在后悔了,非常的后悔!!!如果当时好好学算法的话,现在去理解一些高深的框架可能会很easy,现在随着C#基础和Web技能的提…

git管理大项目或者大文件
git 是追踪代码库演进的最佳选择,并且它能让你与你的同事间高效协作。当你想要追踪的库非常巨大时会发生什么?在这篇文章里,我会尝试着给你一些想法和技巧来恰当地处理不同种类的大仓库。两种大代码库如果仔细想想,大概会有两种导…

window下java开发环境安装
首先请去Java的官网上下载,最好下载最新版本地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 如图,点击下载java platform(JDK),然后选择接受接受协议(Accept …
【ACM】蛇形填数
先判断,再移动,而不是发现越界了再退回来。 #include "stdio.h" #include "string.h" #define maxn 20 int a[maxn][maxn]; int main() {int n, x, y, tot 0;scanf_s("%d", &n);memset(a, 0, sizeof(a));tot a[x …

Mybatis中Oracle和Mysql的Count字段问题
Mybatis中Oracle和Mysql的Count字段问题 我们在进行项目开发时经常会碰到查询总数的问题,所以我们直接是用select count(1) from table来进行查询。那么在Mybatis通常情况下我们是这么写的 <select id"testCount" resultType"int">select…

为什么free()时不需要传指针大小
malloc()和free()是c中两个非常基本的函数,但这种最基本的东西往往都是特别复杂的。malloc和free的原形如下:void *malloc(unsigned int num_bytes); void free(void *ptr);在c的标准中并没有定义这两个函数的具体实现,在我们最常用的gcc中&a…

redis cluster 安装配置
一、redis集群安装配置1、下载redis源码包并下载wget http://download.redis.io/releases/redis-3.0.7.tar.gz $ tar xzf redis-3.0.7.tar.gz $ cd redis-3.0.7 yum -y install gcc gcc-c libstdc-devel #解决相关依赖关系$ make && make install 因我们安装redis 集…

【ACM】汉诺塔
https://blog.csdn.net/xueerfei008/article/details/9904681

什么是机器人底盘 答案在这里!
机器人底盘承载了机器人本身的定位、导航及避障等基本功能,可帮助机器人实现智能行走,以思岚科技的ZEUS为例,内置SLAMWARE高性能自主定位导航模块,用户可根据实际需要搭载不同的应用,可广泛适用于餐厅、商场、银行、办…

嵌入式linux内存使用和性能优化
这本书有两个关切点:系统内存(用户层)和性能优化。 这本书和Brendan Gregg的《Systems Performance》相比,无论是技术层次还是更高的理论都有较大差距。但是这不影响,快速花点时间简单过一遍。 然后在对《Systems Performance》进行详细的学…

【算法导论】插入排序
循环不变式 在数学上阐述了通过循环(迭代,递归)去计算一个累计的目标值的正确性。 关于循环不变式,我们必须要证明三条性质: 初始化:循环第一次迭代之前,它为真。保持:如果循环的…

gdb+gdbserver
内容摘要 远程调试环境由宿主机GDB和目标机调试stub共同构成,两者通过串口或TCP连接。使用 GDB标准程串行协议协同工作,实现对目标机上的系统内核和上层应用的监控和调试功能。调试stub是嵌入式系统中的一段代码,作为宿主机GDB和目标机调试程…

Android开发技巧——去掉TextView中autolink的下划线
我们知道,在布局文件中设置textview的autolink及其类型,这时textivew上会显示link的颜色,并且文字下面会有一条下划线,表示可以点击。而在我们在点击textview时,应用将根据我们所设置的类型跳转到对应的界面。但是有时…