利用系统提供的崩溃日志解Native层Bug

对Android开发者来说,尤为是使用NDK编写Native层代码的开发者,在编码过程当中一般会碰到各类各样的问题。追踪问题的方式有不少,除了在代码中添加日志,来观察程序运行过程当中产生的异常外,对崩溃后产生的日志进行分析也是一种重要的定位问题的方式。html

 

Android系统自带一个很是实用的Native层代码崩溃监测进程debuggerd。该进程能够监听到应用程序的崩溃,并将崩溃后的信息输出到文件中,供开发人员调试分析。在开发过程当中,咱们能够经过logcat来查看debuggerd为咱们生成的应用程序崩溃日志。java

 

接下来,就跟你们来探讨一下如何利用debuggerd为咱们生成的应用程序崩溃日志来定位并解决程序中存在的问题。安全

 

首先经过这个例子来介绍如何使用系统提供的崩溃日志。代码如图1所示。服务器

 

图1  代码示例网络

 

能够看到,JNI_OnLoad函数中除了作一些常规性的操做之外,有这样两行特殊的代码:eclipse

[代码]java代码:

?函数

12 int *p = 0;*p = 1;

p”是个int*类型的空指针,然后面的这个赋值操做是向这个空指针的位置写入1。毫无疑问,这个典型的空指针赋值操做会形成应用程序直接崩溃。工具

 

将以上代码编译成SO文件,并运行APP。发现程序产生了崩溃,经过logcat就能够看到如图2所示的崩溃日志:学习

 

图2  系统生成的崩溃日志测试

 

从这一段崩溃日志中,咱们能够看到:

 

(1)崩溃手机的Build fingerprint是:

'Huawei/H30-T00/hwH30-T00:4.4.2/HuaweiH30-T00/C00B246SP02:user/ota-rel-keys,release-keys'。

 

(2)崩溃发生的进程进程号pid为14077,线程号tid为14077,进程名称为com.example.nativecrash。

(3)signal告诉咱们:崩溃信号为SIGSEGV,当进程中执行了一个无效的内存引用时会触发这个类型的崩溃信号。fault addr表明发生崩溃的地址为0,这与代码中的空指针赋值相吻合。

 

(4)signal下面的4行信息其实就是进程崩溃时全部寄存器的一个快照。

 

(5)最后是backtrace,这部分对于定位产生崩溃的缘由是很是重要的,它反应了进程崩溃时的函数调用栈,经过它,就能够知道在哪里触发了代码崩溃,稍后会详细分析一下这个部分。

 

简单地解析了崩溃日志中的信息以后,咱们就来看看怎么定位崩溃产生的位置?从上面的分析能够知道backtrace是接下来的分析重点。

图3  backtrace中函数调用过程

 

如图3所示,backtrace其实就是一个函数调用栈。最上面一行是崩溃发生的地方。从第一行能够看出:崩溃发生在本身so中的JNI_OnLoad函数里面,崩溃点是在so的偏移为0x47d2的地方(须要注意的是这个偏移是指二进制文件中的偏移,并不是源码中的偏移)。

 

那么JNI_OnLoad函数是由谁调用的呢?从第二行就能够知道是系统的libdvm.so中的dvmLoadNativeCode这个函数调用了该so中的JNI_OnLoad函数。综上能够看出,backtrace中的函数调用关系实际上是由下而上,如图3中的箭头所示。

 

虽然已经定位崩溃发生在so的JNI_OnLoad函数中,可是依然不知道具体发生在源码文件的哪一行。为了可以定位到崩溃发生在源码文件的哪一行,故须要利用Android提供的工具:addr2line。利用该工具能够将backtrace中显示的崩溃点与源码联系起来,这样就能还原崩溃在源码中的位置。具体的还原步骤以下:

 

(1)取obj目录下的libtest.so

咱们知道,在利用ndk-build编译so的时候会在jni的同级目录下产生libs、obj两个目录,如图4所示:

图4  libs、obj目录

这两个目录下面各有一个so,可是为何要取obj目录的,而不取libs目录里面的呢?这是由于ndk-build在生成so的时候,会生成两份,一份是包含调试信息的so,放在obj目录下面;一份是不包含调试信息的so,放在libs目录下面。为了利用addr2line工具还原崩溃点在源码中的位置,咱们必须使用包含调试信息的so,因此须要obj目录中的so。

 

(2)在cmd中运行下面的命令

[代码]java代码:

?

1 addr2line  -f  -e  libtest.so  0x47d2

其中,0x47d2就是咱们以前所看到的崩溃点。

 

运行完能够看到如图5所示的结果:

图5  addr2line运行结果

从以上结果中能够看到:崩溃发生在JNI_OnLoad函数中,崩溃点对应的源码位置在test.cpp的第17行。那么结果然的是在17行吗,咱们能够验证一下:

 

图6  C源码中的崩溃点

如图6所示,空指针赋值的操做正好就是在第17行,正是这个操做致使了崩溃。

 

至此,咱们就基本知道了如何利用系统提供的崩溃日志来定位和解决Native层代码的崩溃了。可是实际的状况比咱们想象要复杂得多。以上方式只适用于开发者在调试或测试阶段来获取崩溃日志,但当开发者将APP分发出去以后,APP运行在用户手机上时发生了崩溃,开发者是看不到日志的。因此一般开发者经过本身搭建崩溃日志服务平台,或集成第三方SDK的形式获取应用崩溃信息。每种方式各有利弊,今天介绍一个免SDK集成的工具——360加固保

360加固保推出了“崩溃日志”功能主要特色有:

 

(1)免SDK集成

目前有很多第三方Crash Report SDK,开发者须要在本身的apk源码中集成SDK,那么做为一个开发者,他的开发成本就相应的增长了不少:

首先,开发者必须学会如何使用SDK,阅读SDK文档,了解其中的API接口,以后才能调用SDK中的API。除此以外,开发者必须得在Android Studio或者eclipse等IDE中配置好SDK的一些使用参数等,可是,这有时并非一件简单的事,须要必定开发成本。

 

再次,因为SDK自己也会存在一些问题(好比Bug,须要优化等),因此必然须要升级更新,那么开发者为了可以使用更优质的服务,就必须紧跟SDK的版本升级,不断在本身的源码中更改SDK,这实际上是比较麻烦的事。

 

为了免去开发者的开发成本,360加固保推出免SDK应用崩溃日志分析服务。无需任何开发过程,只需上传APP进行应用加固,2分钟左右,便可掌握最全面的应用崩溃信息。同时,APP具有了防反编译、防破解的能力,轻松提高APP安全性。

 

(2)提供Native层崩溃日志收集功能,且兼容性强

因为Native层崩溃日志收集的功能涉及Android系统较低层的一些系统机制,其内容较复杂,实现难度较大。因此目前市场上可以提供针对Native层的崩溃收集功能的厂商并很少。即便可以提供Native层的崩溃日志收集,在兼容性方面也存在各类问题。

 

360加固保本身实现了一套收集崩溃日志的接口,并不依赖系统自己提供的崩溃日志相关接口。这样,即使某款手机上的Android系统是基于手机厂商特殊定制的,不提供崩溃日志相关接口,360加固保也能正常收集到此款手机上面的崩溃信息。

 

(3)Native层收集的崩溃数据更加全面

与其余第三方应用崩溃信息厂商相比,360加固保收集的Native层崩溃日志数据更全面,更方便开发者根据这些崩溃信息进行Bug追踪和修复。360加固保收集的崩溃日志信息见图7至图11。

 

图8  加固保收集的应用崩溃信息

 

图8  加固保收集的应用崩溃信息

 

图9  加固保收集的应用崩溃信息

 

图10  加固保收集的应用崩溃信息

 

图11  360加固保收集的应用崩溃信息

 

(4)Native层崩溃日志模拟Android系统收集的崩溃日志,开发者阅读时更方便

Android系统自己自带崩溃日志收集功能,图12至图14是Android系统为崩溃进程收集的崩溃日志详情:

图12  Android系统收集的崩溃日志详情

 

图13  Android系统收集的崩溃日志详情

 

 

图14  Android系统收集的崩溃日志详情

经过与360加固保收集到的崩溃信息对比,能够发现,360加固保提供的崩溃日志详情和Android系统收集的基本没有区别,甚至比某些手机系统上面收集的崩溃日志还要详细。因为开发者在平时调试Native层代码时,习惯看到的是Android系统打出来的Log,因此若是与Android系统收集上来崩溃日志详情的类似,能够说开发者看上去会很是亲切,免去开发者从新学习如何查看的烦恼。

 

(5)所须要获取的apk权限最少

由于收集到的应用崩溃日志须要上传至服务器,因此APP必须有一些网络相关权限。图15是360加固保所需获取的apk权限,只有三个。更少的权限对用户来说,就意味着少了不少的安全风险;对于开发者来说,也没必要由于收集崩溃信息而添加过多的apk自己并不使用的权限。

 

图14   360加固保所需获取的apk权限

 

(6)Native层支持多进程的崩溃日志收集

360加固保提供的崩溃日志分析服务,不管是Android中动态连接库so中fork出来的进程,仍是Service组件的进程,凡是Native层出现了崩溃,都会被Native层崩溃信息收集功能察觉,并生成相应的崩溃信息。

原文连接:http://www.apkbus.com/blog-705730-62583.html

做者:白衣染霜花 连接:http://www.imooc.com/article/247064 来源:慕课网

相关文章
相关标签/搜索