app产品定位如何分析析,定位Android Native Crash

debug(22)
有一句话叫做常在河边走,哪有不湿鞋。我们这些研究和开发的工程师正应了这句话,相必大家在调试的时候经常会遇到这么个东西吧
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'XXXXXXXXX'
pid: 1658, tid: 13086& &&& system_server &&&
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 64696f7e
&r0 & r1 & r2 ad12d1e8& r3 7373654d
&r4 64696f72& r5 & r6 & r7 40d14008
&r8 4b857b88& r9 4685adb4& 10 & fp 4b857ed8
&ip & sp 4b857b50& lr afd11108& pc ad115ebc& cpsr
&d0& 0000& d1& 0003
&d2& 4e72cd& d3& 00e81fe04b1b64d8
&d4& 3fbc71c& d5& 3fea
&d6& 0000& d7& 0000
&d8& 0000& d9& 0000
&d10 0000& d11 0000
&d12 0000& d13 0000
&d14 0000& d15 0000
&&&&&&&&&#00& pc & /system/lib/libc.so
&&&&&&&& #01& pc 0003724c& /system/lib/libxvi020.so
&&&&&&&& #02& pc 0000ce02& /system/lib/libxvi020.so
&&&&&&&& #03& pc & /system/lib/libxvi020.so
&&&&&&&& #04& pc 00010cce& /system/lib/libxvi020.so
&&&&&&&& #05& pc & /system/lib/libwimax_jni.so
&&&&&&&& #06& pc 00011e74& /system/lib/libdvm.so
&&&&&&&& #07& pc 0004354a& /system/lib/libdvm.so
&&&&&&&& #08& pc & /system/lib/libdvm.so
&&&&&&&& #09& pc & /system/lib/libdvm.so
&&&&&&&& #10& pc & /system/lib/libdvm.so
&&&&&&&& #11& pc 00059c24& /system/lib/libdvm.so
&&&&&&&& #12& pc 00059e3c& /system/lib/libdvm.so
&&&&&&&& #13& pc 0004e19e& /system/lib/libdvm.so
&&&&&&&& #14& pc 00011b94& /system/lib/libc.so
&&&&&&&& #15& pc 0001173c& /system/lib/libc.so
code around pc:
ad115e9c 4620eddc bf00bd70 01734e&
ad115eac c4c0a f7f4edc8&
ad115ebc 42ab68e3 68a0d103 f7fedd2&
ad115ecc d1f52c00
edbef7f4 bf00bd70&
ad115edc b51f &
code around lr:
afd110e8 ea404&
afd110f8 ea01 ebffed92&
afd10 a000001 ea000009&
afd11118 ebfffe50 e1a006 ebffed92&
afd105 ea000&
&&& 4b857b10& 40e43be8 &
&&& 4b857b14&
&&& 4b857b18&
&&& 4b857b1c& 034e8968 &
&&& 4b857b20& ad118ce9& /system/lib/libnativehelper.so
&&& 4b857b24&
&&& 4b857b28&
& & .....& &&&
&&& 初一看到直接崩溃,我的个妈,这么一大坨,啥玩意啊,完全搞不懂,没有头绪撒。这NND Android出了问题,冒出这么大堆的地址,搞毛呢。
&& 其实, 我可以很负责任的告诉你,兄弟这么多其实我也看不懂,在我眼里除了红色和蓝色的地方,其他全是废话。因为除了这两个地方意外,其他的我确实看不懂,一堆线性地址,外加寄存器,跟火星文一样。
&& 算了,废话不多少,直接分析:
&& 1 红色的地方,是让我们确认问题到底发生在那个线程中,是主线程还是子线程,这个的判断依据是:如果PID和TID相同,恭喜你问题出在父亲这边,看样子问题还比较好办。如果PID和TID不相同,那么您悲剧了,问题出在子线程中。根据我的经验,100的tombstone中,问题出现在父线程的概率,我还从来没发现,尤其是什么system_server, zygote这些,基本都是儿子的问题。唉,谁叫父亲英雄,儿狗熊呢。。。
& 2 确认了问题的基本点,下面就是开始看蓝色的部分了。
&&& 这个蓝色不分是从#00--&#XX 表面上看是从上往下的增长,其实坑爹啊,它所显示的程序的执行流程,恰恰是从下往上的也就是实际的执行顺序是#XX--&#00。
&& 所以一开始我们的目的是分析第一个出现问题的动态连接库
&& #15& pc 0001173c& /system/lib/libc.so
& a 首先按图索骥,找到你的目标,libc.so这个一般会在你编译完的目标目录下,也就是out/target/product/your_pro/system/lib这个目录下。
& b 一般你如果用的是还像样的linux系统,会有个地址解析的命令addr2line,负责解析动态连接库的(如果你是悲剧,没有这个命令,那好吧, google早就预料到会有象你这样的悲剧人,他们在prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-addr2line,给您准备了个,咋就用这个吧,功能一样,没啥区别)
&&&& addr2line -e -f&libc.so&0001173c& 红色是你的目标库,绿色是你出问题的地址,看看#15这行
&&& 结果出现:??pthread_create
&&&&&&&&&&&&&&&&&&&& ??:0
&&& 恩,好了问题应该出在这个函数中,认为大功告成了?我,呸,还早呢。这个只是告诉你函数入口,至于具体执行到这个函数的哪个地方挂了,还得再看。
c 找到了是哪个部分出了问题,下面就是开启显微镜,看看谁搞的东东。
&& 使用objdump -S -D libc.so & deassmble_libc.txt 反汇编下你的动态连接库文件,并且将它写入一个文件中。
&& 打开这个反汇编过后的重定向文件,在查询的时候输入1173c这个偏移地址,你会看到在茫茫人海中
&pthread_create&:
&& 11684:&&&&&& e92d4ff0&&&&&&& push&&& {r4, r5, r6, r7, r8, r9, sl, fp, lr}
&& 11688:&&&&&& e24dd01c&&&&&&& sub&&&& sp, sp, #28&&&& ; 0x1c
&& 1168c:&&&&&& e1a06001&&&&&&& mov&&&& r6, r1
&& 11690:&&&&&& e1a08002&&&&&&& mov&&&& r8, r2
&& 11694:&&&&&& e1a09003&&&&&&& mov&&&& r9, r3
&& 11698:&&&&&& e3a04001&&&&&&& mov&&&& r4, #1& ; 0x1
&& 1169c:&&&&&& e59f521c&&&&&&& ldr&&&& r5, [pc, #540]& ; 118c0 &pthread_create+0x23c&
&& 116a0:&&&&&& e58d000c&&&&&&& str&&&& r0, [sp, #12]
&& 116a4:&&&&&& eb009a35&&&&&&& bl&&&&& 37f80 &strncmp+0x20&
&& 116a8:&&&&&& e59f2214&&&&&&& ldr&&&& r2, [pc, #532]& ; 118c4 &pthread_create+0x240&
&& 116ac:&&&&&& e1a03000&&&&&&& mov&&&& r3, r0
&& 116b0:&&&&&& e1a01004&&&&&&& mov&&&& r1, r4
&& 116b4:&&&&&& e593c000&&&&&&& ldr&&&& ip, [r3]
&& 116b8:&&&&&& e3a0003c&&&&&&& mov&&&& r0, #60 ; 0x3c
&& 116bc:&&&&&& e08f3005&&&&&&& add&&&& r3, pc, r5
&& 116c0:&&&&&& e7933002&&&&&&& ldr&&&& r3, [r3, r2]
&& 116c4:&&&&&& e5834000&&&&&&& str&&&& r4, [r3]
&& 116c8:&&&&&& e58dc010&&&&&&& str&&&& ip, [sp, #16]
&& 116cc:&&&&&& eb009a3b&&&&&&& bl&&&&& 37fc0 &strncmp+0x60&
&&&1173c:&&&&&& ebffec2b&&&&&&& bl&&&&& c7f0 &__pthread_clone&--&就是他了,对你成功了。
这个是ARM汇编,需要你翻译成对应的C函数去看,这里我就不做解释了,照着前面的步骤,
对上面中#15--&#00 一共16行慢慢去找,直到找到#00行的问题函数,其实,最后一个#00行的是最重要的(前面不找也行,但是可以多给你提供问题信息,和流程),因为他是第一目击者,也是Crash前的第一现场。所以找到这个函数很重要,假设我们最后经过万里长针发现#00的出错的地方是pXX-&member挂了(MD,我经常遇到这种问题)。
那么你可以怀疑两个地方:
1 您的指针是空指针,但是现实与理想总是十万八千里,多数情况下很少出现,而且你分析代码后,也会对自己说怎么可能。绝大多数情况下,从我的经验来讲,很少会有空指针这种低级错误,但是不排除哪个2货出现了这么个问题。如果是这个问题,那么恭喜你,你很幸运。
2 还有就是怀疑越界和内存地址被挤占。就拿我以前的经验,指针不是空,但是根据汇编码看,是访问成员变量挂了,这个地址肯定是被占用了。
&& 针对第2种比较恶心的情况,就需要你看整个log的流程了,需要你看下主要的mainlog关于出现crash前的动作,看看是哪个孙子占用的,以最近原则为先,从下往上看,唉,说句实在话,李白的一句话可以形容整个过程:&蜀道难,难于上青天啊&。工作量大,而且要细致。我也没什么办法。。。
& 还有一种情况,就是内存不够,导致了您的地址被挤占了,出现low memory, no more ...这样的语句,以及大量出现GC_FOR_MALLOC关于GC的东西(如果是少量的,可以忽略,大量的话),呵呵表明你的某个进程在吞噬你的内存,存在内存泄漏。坑爹啊,这个问题,是最难查的,需要你花大量时间,去看内存的变化。一般看内存的情况是
cat /proc/meminfo&
空闲内存=buffer+cache+free这三个字段,Active字段是已经使用的内存,Total不用说,是总的物理内存。(记住 free不高,并不代表你的内存空闲不高,海水不可斗量,需要看全了3个字段的总和才是空闲内存)
如果你想具体跟踪每个进程的内存使用情况,还是在/proc下面,对应了N多的数字文件,那个其实是PID号,进去后cat status可以看到
VMRSS XXXKB就是你当前进程的使用内存量,此外还有一些其他的内存数据,包括页啊等等。。。里面还有很多有用的数据,如果你想跟踪所有的进程的内存情况,推介大家可以看看linux&ps命令的源码,看看人家是怎么在/proc下遍历进程,并且提取属性值的。
写个daemon,跟踪一段时间,记录下各进程内存的变化,然后就是通宵的分析。。。。
总之,这类问题,很难定位,也很难解决,需要花时间,精力去分析。但是如果你解了,那么相信所有人对你会刮目相看的。包括你的老板,量变引起质变,请记住。
我还在纠结中啊...分析ing
最后再说几句
#12 476e5eb8& 476e5ed8 &
&&& 476e5ebc& 476e5ed8 &
&&& 476e5ec0&
&&& 476e5ec4& 476e5ed8 &
&&& 476e5ec8& acaa4d38 &
&&& 476e5ecc& 005ec9b0 &
&&& 476e5ed0&&aca4e1a3& /system/lib/libdvm.so
&&& 476e5ed4& 476e5ed8 &
#13 476e5ed8& 005ec9b0 &
&&& 476e5edc& 005ecae8 &
&&& 476e5ee0& 476e5f00 &
&&& 476e5ee4&&aca4e109& /system/lib/libdvm.so
&&& 476e5ee8& 005ec9b0 &
&&& 476e5eec&&afd11b98& /system/lib/libc.so
#14 476e5ef0& 476e5f00 &
&&& 476e5ef4& 005ecae8 &
&&& 476e5ef8& 45b29b84 &
&&& 476e5efc&&afd11740& /system/lib/libc.so
#15 476e5f00& 476e5f00 &
&&& 476e5f04& 005ecae8 &
&&& 476e5f08&
&&& 476e5f0c&
&&& 476e5f10&
&&& 476e5f14& 005ec9b0 &
&&& 476e5f18&
&&& 476e5f1c&
红色的部分是基地址+偏移地址
比如afd +11740 这个afd你可以从prelink-linux-arm.map找到每个.so的基地址(比如&libc.so&&&&&&&&&&&&&&&& 0xAFD00000 # [~2M])11740可以从反汇编的文件中找到对应点,但是我不知道这些有什么用。
希望这偏小文章能帮助到大家,大家共同进步,有好的方法也欢迎您一起分享。谢谢!
下面是一个老外的摘录早期存于google论坛的内存分析文章(现在没了),我是在他基础上,又加了一些分析和经验之谈,希望上帝保佑让我早点定位到问题。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:101576次
积分:1584
积分:1584
排名:千里之外
原创:27篇
转载:216篇
(14)(5)(15)(3)(9)(4)(11)(12)(24)(13)(17)(8)(9)(10)(7)(2)(4)(7)(8)(21)(3)(1)(1)(11)(20)(4)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'android系统中出现的nativecrash反映的是系统哪一层的问题呀?是framework层的问题吗?_百度知道
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。
android系统中出现的nativecrash反映的是系统哪一层的问题呀?是framework层的问题吗?
Android平台程序崩溃的类型及原因列举ANR(可见ANR):发生场景:应用发生ANR。崩溃症状:系统弹出窗口询问用户选择“Force Close”或者“Wait”。&Force Close&将杀掉发生ANR的应用进程。&Wait&将会等待系统择机恢复此应用进程。发生原因:(1)应用主线程卡住,对其他请求响应超时。(2)死锁。(3)系统反应迟钝。(4)CPU负载过重。Force Close:发生场景:应用进程崩溃。崩溃症状:系统弹出窗口提示用户某进程崩溃。发生原因:空指向异常或者未捕捉的异常。Tombstones:发生场景:Native层崩溃崩溃症状:如果发生崩溃的native层和UI有关联(比如Browser),我们可以在UI上发现这个崩溃。如果发生崩溃的native层是在后台并且和UI没有直接联系,那么对于用户来说是不可见的,如果是debug版本可能会有Log打印出当时的底层现场。发生原因:各种各样,需要具体情况具体分析。系统服务崩溃(System Server Crash):发生场景:系统服务是Android核心进程,此服务进程发生崩溃。崩溃症状:手机重启到Android启动界面发生原因:(1)系统服务看门狗发现异常。(2)系统服务发生未捕获异常。(3)OOM。(4)系统服务Native发生Tombstone。Kernel Panics:发生场景:Linux内核发生严重错误崩溃症状:手机从bootloader开始完全重启发生原因:(1)Linux内核内存空间发生内存崩溃。(2)内核看门狗发现异常。(3)空指针操作内核。
中国IT职业教育领先品牌
主营:专注UI,HTML5,PHP,JavaEE,Python,VR/AR,大数据开发培训。
android framework分为java和native两层native运行于C的runtime,高效。一般java层只是封装,通过jni访问native不知道lz的nativecrash是何意?要说crash,底层HAL,driver的crash也会导致上层的crash
为您推荐:
其他类似问题
您可能关注的内容
android系统的相关知识
等待您来回答Android Crash 问题分析以及解决 - 简书
Android Crash 问题分析以及解决
Crash问题(Java与Native)
1.问题介绍
Crash问题,无论是java侧还是native侧,在日常测试中经常会遇到。Crash问题一般我们可以分为两类,一类是java侧的crash问题也就是抛出exception问题,这一类相对简单。另一类是native侧的问题,由于是c++或者是c,所以相对较为复杂。另外,kernel部分的crash暂且不提。
2.分析过程
分析过程主要分两部分,按照不同的问题来做分析。
(1).java侧问题
java侧出现exception抛出但是并没有栈上任何一层都没有一个地方catch住的话,最终将会使程序崩溃。这种exception一般最终将会在slog中体现,一般如下所示
12-28 23:32:27.143: D/AndroidRuntime(337): Shutting down VM
12-28 23:32:27.143: W/dalvikvm(337): threadid=1: thread exiting with uncaught exception (group=0x)
12-28 23:32:27.173: E/AndroidRuntime(337): FATAL EXCEPTION: main
12-28 23:32:27.173: E/AndroidRuntime(337): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.wtaylorjr2001.practice/com.wtaylorjr2001.practice.PracticeActivity}: java.lang.NullPointerException
12-28 23:32:27.173: E/AndroidRuntime(337): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
12-28 23:32:27.173: E/AndroidRuntime(337): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
12-28 23:32:27.173: E/AndroidRuntime(337): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
12-28 23:32:27.173: E/AndroidRuntime(337): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
12-28 23:32:27.173: E/AndroidRuntime(337): at android.os.Handler.dispatchMessage(Handler.java:99)
12-28 23:32:27.173: E/AndroidRuntime(337): at android.os.Looper.loop(Looper.java:123)
12-28 23:32:27.173: E/AndroidRuntime(337): at android.app.ActivityThread.main(ActivityThread.java:3683)
12-28 23:32:27.173: E/AndroidRuntime(337): at java.lang.reflect.Method.invokeNative(Native Method)
12-28 23:32:27.173: E/AndroidRuntime(337): at java.lang.reflect.Method.invoke(Method.java:507)
12-28 23:32:27.173: E/AndroidRuntime(337): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
12-28 23:32:27.173: E/AndroidRuntime(337): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
12-28 23:32:27.173: E/AndroidRuntime(337): at dalvik.system.NativeStart.main(Native Method)
12-28 23:32:27.173: E/AndroidRuntime(337): Caused by: java.lang.NullPointerException
12-28 23:32:27.173: E/AndroidRuntime(337): at com.wtaylorjr2001.practice.PracticeActivity.onCreate(PracticeActivity.java:24)
12-28 23:32:27.173: E/AndroidRuntime(337): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
12-28 23:32:27.173: E/AndroidRuntime(337): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
12-28 23:32:27.173: E/AndroidRuntime(337): ... 11 more
log中会将该exception的调用栈打出,我们可以跟踪该调用栈进行一步步分析。
此外,由于在一般代码中通常会多次迭代打包exception,比如
implementation = Class.forName(className, true, cl);
lastClassName = classN
} catch (Exception e) {
throw new NoSuchAlgorithmException(type + " " + algorithm + " implementation not found: " + e);
如果我们需要查看这个e的调用栈,我们可以在catch block中添加e.printStackTrace()即可打印Exception e的调用栈。
(2).natvie侧crash问题
native侧crash问题较为复杂。我们需要用到以下工具32bit:arm-eabi-addr2linearm-eabi-gdb64bit:aarch64-linux-android-addr2lineaarch64-linux-android-gdb
尽管32bit与64bit工具不同,实际上操作方法一致,我们以64bit为例。
我们举个实际例子来解释:现在出现一native crash问题,log中有如下错误报告:
Build fingerprint: 'SPRD/sp_native/sp:6.0/MRA58K/W16.12.1N15:userdebug/test-keys'Revision: '0'ABI: 'arm64'pid: 6695, tid: 6758, name: Chrome_InProcGp
&&& com.android.browser &&&signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), &font color="#FF0000"&fault addr 0x170cbeee0&/font&
ffffffffa91703af
pstate 0000
00003fdffffffffffe98
0ad8b79a5cc
0b02a48f03b
backtrace:
#00 pc 8cd8
/system/app/webview/webview.apk (offset 0x7fd000)
#01 pc ca66f4
/system/app/webview/webview.apk (offset 0x7fd000)
#02 pc ca7240
/system/app/webview/webview.apk (offset 0x7fd000)
#03 pc fc178
/system/app/webview/webview.apk (offset 0x7fd000)
#04 pc ff33c
/system/app/webview/webview.apk (offset 0x7fd000)
#05 pc 03fc
/system/app/webview/webview.apk (offset 0x7fd000)
#06 pc f934c
/system/app/webview/webview.apk (offset 0x7fd000)
#07 pc f879c
/system/app/webview/webview.apk (offset 0x7fd000)
#08 pc e21b0
/system/app/webview/webview.apk (offset 0x7fd000)
#09 pc fd00c
/system/app/webview/webview.apk (offset 0x7fd000)
#10 pc fd91c
/system/app/webview/webview.apk (offset 0x7fd000)
#11 pc fdeb8
/system/app/webview/webview.apk (offset 0x7fd000)
#12 pc fef1c
/system/app/webview/webview.apk (offset 0x7fd000)
#13 pc fd528
/system/app/webview/webview.apk (offset 0x7fd000)
#14 pc de38
/system/app/webview/webview.apk (offset 0x7fd000)
#15 pc fc380
/system/app/webview/webview.apk (offset 0x7fd000)
#16 pc a0c0
/system/app/webview/webview.apk (offset 0x7fd000)
#17 pc 6230
/system/app/webview/webview.apk (offset 0x7fd000)
#18 pc 6ca4
/system/lib64/libc.so (__pthread_start(void*)+52)
#19 pc eb84
/system/lib64/libc.so (__start_thread+16)
主要我们首先看该app是以什么abi运行的,这里显示是arm64,所以我们会使用64bit的一套工具。然后我们看到错误的地址为0x170cbeee0。这里还不是空指针问题,所以我们还需要通过推调用栈分析具体错误位置。
我们找到这个版本对应的带符号表的libwebviewchromium.so(这里说明下,系统级apk如果其中含有so lib,是不会主动将其解压到某一个目录的,故在最终的调用栈中显示的还是webview.apk,但是实际指的即是webview.apk中的libwebviewchromium.so。)
然后执行如下名令:
aarch64-linux-android-addr2line -i -f -e libwebviewchromium.so 0x8cd8 0xca66f4 0xca8 0xff33c 0x03fc 0xf934c 0xf879c 0xe21b0 0xfd00c 0xfd91c 0xfdeb8
命令后面的各个地址即是各层调用栈的地址,其中以空格分割。
过了一会儿,命令行即会显示:
ZN4base6Pickle16WriteBytesCommonEPKvm/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/pickle.cc:397_ZN4base6Pickle16WriteBytesStaticILm4EEEvPKv/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/pickle.cc:380_ZN4base6Pickle8WritePODIiEEbRKT
/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/pickle.h:306
ZN4base6Pickle8WriteIntEi/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/pickle.h:172_ZN3IPC11ParamTraitsIiE5WriteEPNS_7MessageERKi/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../ipc/ipc_message_utils.h:157WriteParam&int&/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../ipc/ipc_message_utils.h:103_ZN3IPC11ParamTraitsIN3gpu13CommandBuffer5StateEE5WriteEPNS_7MessageERKS3
/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../gpu/ipc/gpu_command_buffer_traits.cc:32WriteParam&gpu::CommandBuffer::State&/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../ipc/ipc_message_utils.h:103
ZN3IPC11ParamTraitsIN4base5TupleIJRN3gpu13CommandBuffer5StateEEEEE5WriteEPNS_7MessageERKS7
/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../ipc/ipc_message_utils.h:607WriteParam&base::Tuple&gpu::CommandBuffer::State&& &/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../ipc/ipc_message_utils.h:103
ZN3IPC17SyncMessageSchemaIN4base5TupleIJiiEEENS2_IJRN3gpu13CommandBuffer5StateEEEEE16WriteReplyParamsIJS6_EEEvPNS_7MessageEDpT
/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../ipc/ipc_message_utils.h:1061
ZN43GpuCommandBufferMsg_WaitForGetOffsetInRange16WriteReplyParamsIN3gpu13CommandBuffer5StateEEEvPN3IPC7MessageET
/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../content/common/gpu/gpu_messages.h:531
ZN7content20GpuCommandBufferStub18CheckCompleteWaitsEv/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../content/common/gpu/gpu_command_buffer_stub.cc:809_ZN7content20GpuCommandBufferStub17OnMessageReceivedERKN3IPC7MessageE/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../content/common/gpu/gpu_command_buffer_stub.cc:324_ZN7content13MessageRouter12RouteMessageERKN3IPC7MessageE/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../content/common/message_router.cc:54_ZN7content10GpuChannel13HandleMessageEv/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../content/common/gpu/gpu_channel.cc:847_ZN4base8internal15RunnableAdapterIMN7content10GpuChannelEFvvEE3RunEPS3
/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/bind_internal.h:176 (discriminator 4)
ZN4base8internal12InvokeHelperILb1EvNS0_15RunnableAdapterIMN7content10GpuChannelEFvvEEENS0_8TypeListIJRKNS_7WeakPtrIS4_EEEEEE8MakeItSoES7_SC
/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/bind_internal.h:303 (discriminator 4)_ZN4base8internal7InvokerINS_13IndexSequenceIJLm0EEEENS0_9BindStateINS0_15RunnableAdapterIMN7content10GpuChannelEFvvEEEFvPS7_ENS0_8TypeListIJNS_7WeakPtrIS7_EEEEEEENSD_IJNS0_12UnwrapTraitsISF_EEEEENS0_12InvokeHelperILb1EvSA_NSD_IJRKSF_EEEEEFvvEE3RunEPNS0_13BindStateBaseE/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/bind_internal.h:346 (discriminator 4)_ZNK4base8CallbackIFvvEE3RunEv/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/callback.h:396 (discriminator 1)_ZN4base5debug13TaskAnnotator7RunTaskEPKcRKNS_11PendingTaskE/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/debug/task_annotator.cc:51 (discriminator 1)_ZN4base11MessageLoop7RunTaskERKNS_11PendingTaskE/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/message_loop/message_loop.cc:481_ZN4base11MessageLoop21DeferOrRunPendingTaskERKNS_11PendingTaskE/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/message_loop/message_loop.cc:490_ZN4base11MessageLoop6DoWorkEv/home8/tianqichen/chromium_release_arm64/chromium/src/out/Release/../../base/message_loop/message_loop.cc:602
我们就可以知道大致错误的位置是哪里。/base/pickle.cc:397
一般来说基本的native crash问题在使用了addr2line工具之后都能够大致分别错误几何。
然而实际上我们去查看该段代码
inline void Pickle::WriteBytesCommon(const void* data, size_t length) {
DCHECK_NE(kCapacityReadOnly, capacity_after_header_)
&& "oops: pickle is readonly";
MSAN_CHECK_MEM_IS_INITIALIZED(data, length);
size_t data_len = bits::Align(length, sizeof(uint32));
DCHECK_GE(data_len, length);
#ifdef ARCH_CPU_64_BITS
DCHECK_LE(data_len, kuint32max);
DCHECK_LE(write_offset_, kuint32max - data_len);
size_t new_size = write_offset_ + data_
// &----------------------------------- This line.
if (new_size & capacity_after_header_) {
size_t new_capacity = capacity_after_header_ * 2;
const size_t kPickleHeapAlign = 4096;
if (new_capacity & kPickleHeapAlign)
new_capacity = bits::Align(new_capacity, kPickleHeapAlign) - kPayloadU
Resize(std::max(new_capacity, new_size));
char* write = mutable_payload() + write_offset_;
memcpy(write, data, length);
memset(write + length, 0, data_len - length);
header_-&payload_size = static_cast&uint32&(new_size);
write_offset_ = new_
size_t new_size = write_offset_ + data_这一段代码看上去并不涉及指针操作,所以一般非代码逻辑问题。因此我们需要进一步通过corefile,查看错误当时具体汇编代码在干什么,当时保存的寄存器以及内存现场是怎么样。
gdb调试corefile
首先如果手机上出现native crash问题,一般都会在手机中生成corefile来dump当时的内存信息。一般会在/data/corefile目录下生成。
分析corefile我们需要用到GDB工具,由于刚才已经从log信息中看到该apk运行在64bit下,故我们将使用aarch64-linux-android-gdb进行分析。
在此之前我们需要准备以下内容。
相应版本的symbols压缩包,并且解压
slog中找到corefile
在将symbols解压后(假设我们解压到了当前目录),使用aarch64-linux-android-gdb ./symbols/system/bin/app_process64 命令进入GDB。
进入之后我们可以先设置so的搜索路径,首先由于我们的webview.apk是已经打包好放入源码目录中参加编译的,故该symbols里的lib64目录下并不存在我们的libwebviewchromium.so。再者,由于GDB搜索加载的符号库时是通过名字严格判别,所以我们需要重命名我们的libwebviewchromium.so为webview.apk,然后放入./symbols/system/lib64/中。之后我们在GDB命令行下执行set solib-search-path ./symbols/system/lib64/即指明了so lib的搜索路径。
之后我们可以加载corefile,执行core-file ./core-file core-Chrome_InProcGp-6695即可。执行之后需要等一段时间。
待执行完毕后我们即可分析当时crash的现场。
GDB的基本名令有
bt 查看当前调用栈
f 后续带数字,跳到指定栈以查看寄存器或者汇编代码
disassemble 不带内存地址即反汇编当前栈代码,带内存地址即查看该内存地址所在代码段的汇编代码。
info registers 查看当前栈的寄存器信息
该问题,我们需要先查看f 0上的汇编代码
(gdb) disassembleDump of assembler code for function base::Pickle::WriteBytesStatic&4ul&(void const):
0x48cc0 &+0&:
x29, x30, [sp,#-48]!
0x48cc4 &+4&:
0x48cc8 &+8&:
x19, x20, [sp,#16]
0x48ccc &+12&:
x21, [sp,#32]
0x48cd0 &+16&:
0x48cd4 &+20&:
x21, x1=& 0x48cd8 &+24&:
x3, [x0,#32]
0x48cdc &+28&:
x2, [x0,#24]
0x48ce0 &+32&:
x20, x3, #0x4
0x48ce4 &+36&:
0x48ce8 &+40&:
0x7f90548d0c &base::Pickle::WriteBytesStatic&4ul&(void const)+76&
0x48cec &+44&:
x1, x2, #1
0x48cf0 &+48&:
x1, #0x1, lsl #12
0x48cf4 &+52&:
0x7f90548d3c &base::Pickle::WriteBytesStatic&4ul&(void const*)+124&
0x48cf8 &+56&:
0x48cfc &+60&:
所以错误的位置即为=& 0x48cd8 &+24&:
x3, [x0,#32]即读取x0 + 32这个地址的内容然后放到x 3里去
这时候我们通过info registers 查看x0地址为
(gdb) info registersx0
0x170cbeec0
目测或者严格来说查看map表可以发现这个值作为内存地址来使用应该是不正确的,接下来就是倒推汇编来查看到底这个值是怎么来的。这部分这个问题没有直接证据证明具体arm汇编指令可以查看
另外例子有:
依然我们先从log中找到crash的调用栈
00 pc 007a52b2
/system/lib/libwebviewchromium.so
#01 pc 00ac631b
/system/lib/libwebviewchromium.so
/system/lib/libwebviewchromium.so
#03 pc 007f2fdf
/system/lib/libwebviewchromium.so
#04 pc 007f603d
/system/lib/libwebviewchromium.so
/system/lib/libwebviewchromium.so
#06 pc 008099cd
/system/lib/libwebviewchromium.so
#07 pc 007f8043
/system/lib/libwebviewchromium.so
#08 pc 007de197
/system/lib/libwebviewchromium.so
#09 pc 007f8091
/system/lib/libwebviewchromium.so
#10 pc 007de197
/system/lib/libwebviewchromium.so
#11 pc 007f8091
/system/lib/libwebviewchromium.so
#12 pc 007de197
/system/lib/libwebviewchromium.so
#13 pc 007f8091
/system/lib/libwebviewchromium.so
#14 pc 007de197
/system/lib/libwebviewchromium.so
#15 pc 007f8091
/system/lib/libwebviewchromium.so
#16 pc 007de197
/system/lib/libwebviewchromium.so
#17 pc 007f8091
/system/lib/libwebviewchromium.so
#18 pc 007de197
/system/lib/libwebviewchromium.so
#19 pc 007f8091
/system/lib/libwebviewchromium.so
#20 pc 007de197
/system/lib/libwebviewchromium.so
#21 pc 007f8091
/system/lib/libwebviewchromium.so
#22 pc 007fe33b
/system/lib/libwebviewchromium.so
#23 pc 007f610b
/system/lib/libwebviewchromium.so
#24 pc 007f81db
/system/lib/libwebviewchromium.so
#25 pc 007df2e5
/system/lib/libwebviewchromium.so
#26 pc 007f824d
/system/lib/libwebviewchromium.so
#27 pc 007df2e5
/system/lib/libwebviewchromium.so
#28 pc 007f824d
/system/lib/libwebviewchromium.so
#29 pc 007df2e5
/system/lib/libwebviewchromium.so
#30 pc 007f824d
/system/lib/libwebviewchromium.so
#31 pc 007eb4ed
/system/lib/libwebviewchromium.so
#32 pc 007ee833
/system/lib/libwebviewchromium.so
#33 pc 007eea03
/system/lib/libwebviewchromium.so
#34 pc 007ef77f
/system/lib/libwebviewchromium.so
#35 pc 00987ceb
/system/lib/libwebviewchromium.so
#36 pc 00bc058d
/system/lib/libwebviewchromium.so
#37 pc 01288e3b
/system/lib/libwebviewchromium.so
#38 pc 010d9e51
/system/lib/libwebviewchromium.so
首先我们将其调用栈打印下
bswap32/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/wtf/ByteSwap.h:56bswapuintptrt/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/wtf/ByteSwap.h:72partitionFreelistMask/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/wtf/PartitionAlloc.h:329partitionBucketAlloc/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/wtf/PartitionAlloc.h:449partitionAllocGenericFlags/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/wtf/PartitionAlloc.h:546_ZN3WTF21partitionAllocGenericEPNS_20PartitionRootGenericEj/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/wtf/PartitionAlloc.h:554_ZN3WTF10fastMallocEj/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/wtf/FastMalloc.cpp:74_ZN3WTF10RefCountedIN5blink11RenderStyleEEnwEj/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/wtf/RefCounted.h:166_ZN5blink11RenderStyle6createEv/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/core/rendering/style/RenderStyle.cpp:78_ZN5blink13StyleResolver15styleForElementEPNS_7ElementEPNS_11RenderStyleENS_20StyleSharingBehaviorENS_20RuleMatchingBehaviorE/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp:582_ZN5blink7Element24originalStyleForRendererEv/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/core/dom/Element.cpp:1466_ZN5blink7Element16styleForRendererEv/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/core/dom/Element.cpp:1445_ZNK5blink17RenderTreeBuilder5styleEv/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/core/dom/RenderTreeBuilder.cpp:99_ZN5blink17RenderTreeBuilder32createRendererForElementIfNeededEv/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/core/dom/RenderTreeBuilder.cpp:111_ZN5blink7Element6attachERKNS_4Node13AttachContextE/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/core/dom/Element.cpp:1332_ZN5blink13ContainerNode14attachChildrenERKNS_4Node13AttachContextE/space/builder/repo/sprdroid5.1_trunk_volte/external/chromium_org/third_party/WebKit/Source/core/dom/ContainerNode.h:291
最后一栈来看ALWAYS_INLINE uint32_t bswap32(uint32_t x) { return __builtin_bswap32(x); }看不太出问题所在,总而言之和x有关这时候需要查看下汇编代码
和之前同样方法进行corefile加载局部汇编如下:
0xa85bf286 &+146&:
0xa85bf288 &+148&:
0xa85bf28a &+150&:
r2, r12, #112 0x70
0xa85bf28e &+154&:
0xa85bf292 &+158&:
r5, r0, [r2]
0xa85bf296 &+162&:
0xa85bf298 &+164&:
0xa85bf28e &WTF::fastMalloc(unsigned int)+154&
0xa85bf29a &+166&:
0xa85bf29e &+170&:
r1, 0xa85bf2ac &WTF::fastMalloc(unsigned int)+184&
0xa85bf2a0 &+172&:
r1, [pc, #92] (0xa85bf300 &WTF::fastMalloc(unsigned int)+268&)
0xa85bf2a2 &+174&:
0xa85bf2a4 &+176&:
r0, [r1, #112] 0x70
0xa85bf2a6 &+178&:
0xa85bf2a8 &+180&:
0xa85bf2a0 &WTF::fastMalloc(unsigned int)+172&
0xa85bf2aa &+182&:
0xa85bf282 &WTF::fastMalloc(unsigned int)+142&
0xa85bf2ac &+184&:
r2, [r3, #0]
0xa85bf2ae &+186&:
r1, [r2, #0]
0xa85bf2b0 &+188&:
r1, 0xa85bf2c4 &WTF::fastMalloc(unsigned int)+208&=& 0xa85bf2b2 &+190&:
r4, [r1, #0]
此时寄存器信息:
(gdb) info registers
0x4a6f8ef8
0x4b6017a0
0xa98fbefc
0xa56c5da0
0x57209fe4
0xa56c6034
0xa98dd62c
0x4b7180b4
0xa98fb7fc
0xa56c5ce8
0xa56c5ce8
0xa88e031f
0xa85bf2b2
0xa85bf2b2 &WTF::fastMalloc(unsigned int)+190&
0x680d0030
所以r1 0x4a6f8ef8这个值没办法读取出来从corefile对应的map来看,0x4a6f8ef8也确实不在可访问区域中
但是我们看看,其他的内存地址都是0x4b什么什么的,所以可以猜测是否出现读取内存或者写入内存时出现问题
我们假设实际上存着的应该是0x4b6f8ef8此时我们读取该内存地址的内存来看
(gdb) x /1xw 0x4b6f8ef80x4b6f8ef8:
0xc08e6f4b
此时需要结合代码来看,这个x究竟是干嘛用的结果我们可以发现这边是在做大小端转换工作__builtin_bswap32也就是说我们内存中读到的值必然是一个经过反转过的内存地址0xc08e6f4b经过反转为0x4b6f8ec0,按字节倒序,可以访问。
我们再看代码,看下这个传入的x代表什么,我们看到frame 2处
ALWAYS_INLINE PartitionFreelistEntry* partitionFreelistMask(PartitionFreelistEntry* ptr)
// We use bswap on little endian as a fast mask for two reasons:
// 1) If an object is freed and its vtable used where the attacker doesn't
// get the chance to run allocations between the free and use, the vtable
// dereference is likely to fault.
// 2) If the attacker has a linear buffer overflow and elects to try and
// corrupt a freelist pointer, partial pointer overwrite attacks are
// thwarted.
// For big endian, similar guarantees are arrived at with a negation.
#if CPU(BIG_ENDIAN)
uintptr_t masked = ~reinterpret_cast&uintptr_t&(ptr);
uintptr_t masked = bswapuintptrt(reinterpret_cast&uintptr_t&(ptr));
return reinterpret_cast&PartitionFreelistEntry*&(masked);
可以看到ptr实际是PartitionFreelistEntry*,也就是一个list的入口。本身PartitionFreelistEntry结构为
struct PartitionFreelistEntry {
PartitionFreelistEntry*
那就太简单了,我们只需要看下0x4b6f8ef8是否能够按照next一直下去由于我们知道是PartitionFreelistEntry*,所以可以使用p /x \*(PartitionFreelistEntry\*)[address]指令来强转查看于是
(gdb) p /x (PartitionFreelistEntry)0x4b6f8ef8$1 = {next = 0xc08e6f4b}(gdb) p /x (PartitionFreelistEntry)0x4b6f8ec0$2 = {next = 0x636f4b}(gdb) p /x (PartitionFreelistEntry)0x4b6f6300$3 = {next = 0x58626f4b}(gdb) p /x (PartitionFreelistEntry)0x4b6f6258$4 = {next = 0xa8636f4b}(gdb) p /x (PartitionFreelistEntry)0x4b6f63a8$5 = {next = 0x70636f4b}(gdb) p /x (PartitionFreelistEntry)0x4b6f6370$6 = {next = 0x38636f4b}(gdb) p /x (PartitionFreelistEntry)0x4b6f6338$7 = {next = 0xc8626f4b}(gdb) p /x (PartitionFreelistEntry)0x4b6f62c8$8 = {next = 0xa08f6f4b}(gdb) p /x (PartitionFreelistEntry)0x4b6f8fa0$9 = {next = 0xd88f6f4b}...
证明了9个node应该足够证明推论是正确的
3.调试技巧
相对来说调试技巧几乎没有,一般都是循序渐进循规蹈矩地按照步骤来查找问题。Java侧:一般多使用printStackTrace来查看具体exception的throw位置。C++侧:多使用GDB来熟练技巧。
4.解决思路及解决方案
Java侧:Java侧一般就两种解决办法:
把这个throw的exception catch住。
查看为何抛出这个exception然后解决。
查看是否存在代码逻辑漏洞导致访问空指针或类似错误,然后修改。
如果并不存在代码逻辑漏洞,可能存在内存读写问题,需要找到具体位置然后转交系统稳定性同事进行分析。}

我要回帖

更多关于 定位分析 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信