breakpad: Native crash 日志收集工具前言正题breakpad工作原理项目集成

前言

现在大部分应用都会有Java层的崩溃日志收集机制,一般就是程序crash后,展示一个上报界面,用户点击就上传了。 但是Native程序crash了,很少有做处理的,几个方面原因:

  1. 大部分应用不用C/C++编写,或者说用也只是很小的一个模块。
  2. 编写一个高质量的Native crash工具本身就不是很容易,搞不好自己还引发崩溃:( 。

正题

今天发现了Google开源了一个工具:breakpad,研究了一下,感觉不错的,特意分享一下。

breakpad工作原理

breakpad并不是只针对Android,而是一个全平台的C/C++程序的崩溃日志收集工具,适配了Windows/MacOX/Linux,当然也支持了Android。

先来看张工作原理图:

breakpad工作原理

解释一下: breakpad其实一套解决方案,包含几个模块:

  • client,编译进入项目中,随项目一起编译发布,发布出去的so是strip掉debug信息的。当在用户手机上崩溃的时候,client就收集信息,写入特定格式的崩溃文件。文件最后被收集到服务端。这个过程就是:
  • server段工具,在server端,当你在编译so的时候,除了编译strip后的so,还得保留strip前的so。假如你是用gradle编译的话,两者都是存在的,分别在:app/build/intermediaters/transforms/mergejniLibs和stripDebugSymbol下:

找到未strip的so后,使用breakpad在编译出来的dump_syms提取符号表:

dump_syms path/of/libxxx.so > libxxx.so.sym

注意libxxx.so.sym前面必须和libxxx.so同名。

上面所说对应图中:

  1. 利用符号表和崩溃文件还原崩溃时堆栈,这里面会包含崩溃时的线程(并会标明是哪个线程崩溃),线程在源码中的崩溃点,崩溃原因,加载的so,以及cpu信息等。

上面所说对应图中:

具体怎么使用操作呢? a. 首先从符号表中的第一行提取标识符,比如:

MODULE Linux arm 489FF5B0639F40A4A961DDC068B5B0770 libnative-lib.so

就是489FF5B0639F40A4A961DDC068B5B0770

b. 建立如下目录结构:

 |symbol
 |--libnative-lib.so       //用你的so名称创建子文件夹
 |----489FF5B0639F40A4A961DDC068B5B0770     //用a中提取的标识符创建子文件夹
 |------libnative-lib.so.sym      //将前面提取的符号表放置在这里,注意文件名                                  

注意:上述以libnative-lib.so展示了文件目录结构,你需要根据自己的so名称做调整。为了简化这种重复且容易出错的工作,我已经将其自动化,见CrashDump

c. 执行minidump_stackwalk name/of/xxx.dmp path/of/symbol > result.txt

d. result.txt中就是可阅读的崩溃信息:

Operating system: Android
                  0.0.0 Linux 3.4.0-gd59db4e #1 SMP PREEMPT Mon Mar 17 15:16:36 PDT 2014 armv7l
CPU: arm
     ARMv7 Qualcomm Krait features: swp,half,thumb,fastmult,vfpv2,edsp,neon,vfpv3,tls,vfpv4,idiva,idivt
     4 CPUs

GPU: UNKNOWN

Crash reason:  SIGSEGV
Crash address: 0x0
Process uptime: not available

Thread 0 (crashed)
 0  libnative-lib.so!crash() [native-lib.cpp : 13 + 0x2]
     r0 = 0x00000000    r1 = 0x00000001    r2 = 0xbef0d46c    r3 = 0x532dbdca
     r4 = 0x6dbfede0    r5 = 0x41a033d8    r6 = 0x00000004    r7 = 0xbef0d4d0
     r8 = 0xbef0d4d8    r9 = 0x4160bca8   r10 = 0x41a033e8   r12 = 0x7591bed4
     fp = 0xbef0d4ec    sp = 0xbef0d3d4    lr = 0x758dd623    pc = 0x758dd596
    Found by: given as instruction pointer in context
 1  libnative-lib.so!Java_com_andr0day_ndktest_MainActivity_stringFromJNI [native-lib.cpp : 22 + 0x3]
     r4 = 0x6dbfede0    r5 = 0x41a033d8    r6 = 0x00000004    r7 = 0xbef0d4d0
     r8 = 0xbef0d4d8    r9 = 0x4160bca8   r10 = 0x41a033e8    fp = 0xbef0d4ec
     sp = 0xbef0d3d8    pc = 0x758dd623
    Found by: call frame info
 2  libdvm.so + 0x1dd4e
     r4 = 0x6dbfede0    r5 = 0x41a033d8    r6 = 0x00000004    r7 = 0x4160bcb0
     r8 = 0xbef0d4d8    r9 = 0x4160bca8   r10 = 0x41a033e8    fp = 0xbef0d4ec
     sp = 0xbef0d4d8    pc = 0x4156bd50
    Found by: call frame info

......

Loaded modules:
0x400d9000 - 0x400dafff  app_process  ???  (main)  (WARNING: No symbols, app_process, 231A2557AC947E46614FB6EAA0030AE80)
0x400dd000 - 0x400ebfff  linker  ???  (WARNING: No symbols, linker, BC3131FBBFE15F3BE40D5EBCF67A71AE0)
0x400f3000 - 0x400fbfff  libcutils.so  ???
0x400fe000 - 0x40100fff  liblog.so  ???
0x40103000 - 0x40149fff  libc.so  ???  (WARNING: No symbols, libc.so, FC9E828FFFAA5CE4E7C28E25988A9C1F0)
0x4015e000 - 0x4015efff  libstdc++.so  ???
0x4015f000 - 0x40160fff  libstdc++.so  ???
0x40161000 - 0x40178fff  libm.so  ???

...

从中看出:线程0在native-lib.cpp的13行处崩溃,原因是:SIGSEGV,cpu的信息等,足够用来定位问题。

  • 其他辅助工具

breakpad还包含若干辅助工具,比如构建上述所说目录结构时,其实可以执行其自带的python命令得到,不再多说。

项目集成

不再多说,直接给出一个已经集成好的demo,依葫芦画瓢即可。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨建荣的学习笔记

有趣的linux命令总结(78天)

linux命令可以简化我们工作中的许多任务。关于Linux这个主题已经考虑很久了,也还是在不断的完善中,在自己的实验和各种资料的整理中,认为还是一些不错的命令。...

29350
来自专栏向治洪

再谈Android动态链接库

前不久,我们准备将自己开发的视频播放sdk提供给公司其他部门,在打包的时候,同事问了我一个问题,为什么我们打sdk的时候需要分别提供armeabi和arm64-...

24470
来自专栏源码之家

如何通过SSH更改Linux系统下文件(或文件夹)的拥有者

31230
来自专栏SDNLAB

从一个 Neutron DHCP 补丁谈起

前言 前几个星期,社区通过了一个 Patch 来解决一个遗留很久的 DHCP 相关的问题,这个 Patch 并不复杂(review 地址是 https://re...

41670
来自专栏编程坑太多

『中级篇』play with docker 的使用(44)

Marcos 和 Jonathan 还带来了另一个炫酷的功能就是可以在 PWD 实例中通过拖放文件的方式将 Dockerfile 直接上传到 PWD 窗口。

6910
来自专栏杨建荣的学习笔记

有趣的linux命令总结(78天)

linux命令可以简化我们工作中的许多任务。关于Linux这个主题已经考虑很久了,也还是在不断的完善中,在自己的实验和各种资料的整理中,认为还是一些不错的命令。...

380120
来自专栏北京马哥教育

JMeter使用技巧

在这此对新版本jmeter的学习+温习的过程,发现了一些以前不知道的功能,所以,整理出来与大分享。本文内容如下。 如何使用英文界面的jmeter 如何使用镜像...

52990
来自专栏C/C++基础

Linux下离线手动下载安装C++开发环境

Linux下我们习惯了使用软件包管理器来安装我们需要的软件,比如Red Hat公司的Fedora、RHEL(Red Hat Enterprise Linux)和...

52820
来自专栏owent

ARM 交叉编译环境搭建

最近研究了一下ARM的交叉编译环境搭建,太麻烦了必须作一下记录啊。 前两个方法比较简单一点,关键是淫家Google帮你弄好了大部分功能

32820
来自专栏大数据架构师专家

namp 渗透测试-安装篇

nmap是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端。确定哪些服务运行在哪些连接端,并且推断计算机运行哪个操作系统。

13930

扫码关注云+社区

领取腾讯云代金券