特别申明:本文仅供自己学习记录使用,所写内容来自各网页,如需转载自己去查找内容出处。如有侵权请联系在下,评论、私信等不论。
目录
一、tombstone
Android APP在运行过程中如出现crash异常,会产生tombstone文件,存放在/data/tombstones目录下。思路之一:我们可以通过分析tombstone来定位问题原因。
crash异常日志如下:
11-06 09:26:19.495 F/libc ( 993): Fatal signal 6 (SIGABRT), code -6 in tid 1046 (RenderThread)
11-06 09:26:19.496 W/ ( 191): debuggerd: handling request: pid=993 uid=1000 gid=1000 tid=1046
11-06 09:26:19.577 F/DEBUG ( 7490): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-06 09:26:19.577 F/DEBUG ( 7490): Build fingerprint: 'Android/rk3288/rk3288:7.1.2/NHG47K/wf06232042:userdebug/test-keys'
11-06 09:26:19.577 F/DEBUG ( 7490): Revision: '0'
11-06 09:26:19.577 F/DEBUG ( 7490): ABI: 'arm'
11-06 09:26:19.577 F/DEBUG ( 7490): pid: 993, tid: 1046, name: RenderThread >>> com.test.Digi <<<
11-06 09:26:19.577 F/DEBUG ( 7490): signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
11-06 09:26:19.584 F/DEBUG ( 7490): Abort message: 'Encountered EGL error 12291 EGL_BAD_ALLOC during rendering'
11-06 09:26:19.584 F/DEBUG ( 7490): r0 00000000 r1 00000416 r2 00000006 r3 00000008
11-06 09:26:19.584 F/DEBUG ( 7490): r4 967df978 r5 00000006 r6 967df920 r7 0000010c
11-06 09:26:19.584 F/DEBUG ( 7490): r8 03fb7340 r9 00000000 sl b2f3453c fp b2f34538
11-06 09:26:19.584 F/DEBUG ( 7490): ip 00000016 sp 967def10 lr b511d857 pc b51200c0 cpsr 680f0010
11-06 09:26:19.594 F/DEBUG ( 7490):
11-06 09:26:19.594 F/DEBUG ( 7490): backtrace:
11-06 09:26:19.594 F/DEBUG ( 7490): #00 pc 0004a0c0 /system/lib/libc.so (tgkill+12)
11-06 09:26:19.594 F/DEBUG ( 7490): #01 pc 00047853 /system/lib/libc.so (pthread_kill+34)
11-06 09:26:19.594 F/DEBUG ( 7490): #02 pc 0001d8b5 /system/lib/libc.so (raise+10)
11-06 09:26:19.595 F/DEBUG ( 7490): #03 pc 00019401 /system/lib/libc.so (__libc_android_abort+34)
11-06 09:26:19.595 F/DEBUG ( 7490): #04 pc 00017048 /system/lib/libc.so (abort+4)
11-06 09:26:19.595 F/DEBUG ( 7490): #05 pc 0000c3cf /system/lib/libcutils.so (__android_log_assert+114)
11-06 09:26:19.595 F/DEBUG ( 7490): #06 pc 000269b7 /system/lib/libhwui.so
分析思路如下:
第一步
从设备中拷贝出tombstone文件,文件打开后,内容大致如下
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Android/rk3288/rk3288:7.1.2/NHG47K/wf06232042:userdebug/test-keys'
Revision: '0'
ABI: 'arm'
pid: 993, tid: 1046, name: RenderThread >>> com.test.Digi <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'Encountered EGL error 12291 EGL_BAD_ALLOC during rendering'
r0 00000000 r1 00000416 r2 00000006 r3 00000008
r4 967df978 r5 00000006 r6 967df920 r7 0000010c
r8 03fb7340 r9 00000000 sl b2f3453c fp b2f34538
ip 00000016 sp 967def10 lr b511d857 pc b51200c0 cpsr 680f0010
d0 697265646e657220 d1 204c474520646569
d2 000000000000006e d3 b1d7a5ecb1d7a567
d4 6968636b636f725f d5 28636f6c6c615f70
d6 6720746375727473 d7 645f636f6c6c6172
d8 0000000000000000 d9 0000000000000000
d10 0000000000000000 d11 0000000000000000
d12 0000000000000000 d13 0000000000000000
d14 0000000000000000 d15 0000000000000000
d16 2e74736973726570 d17 2e6761742e676f6c
d18 00000005431ed428 d19 000000083917b698
d20 0000000000000000 d21 0000000000000000
d22 03000040000a0003 d23 070000e0003a0007
d24 0004000400020001 d25 0000000000000000
d26 0000000000000000 d27 0000000000000000
d28 0000000000000000 d29 0000000000000000
d30 0000000000000000 d31 0000000000000000
scr 60000091
backtrace:
#00 pc 0004a0c0 /system/lib/libc.so (tgkill+12)
#01 pc 00047853 /system/lib/libc.so (pthread_kill+34)
#02 pc 0001d8b5 /system/lib/libc.so (raise+10)
#03 pc 00019401 /system/lib/libc.so (__libc_android_abort+34)
#04 pc 00017048 /system/lib/libc.so (abort+4)
#05 pc 0000c3cf /system/lib/libcutils.so (__android_log_assert+114)
#06 pc 000269b7 /system/lib/libhwui.so
#07 pc 00023fbd /system/lib/libhwui.so
#08 pc 00025b43 /system/lib/libhwui.so
#09 pc 00029139 /system/lib/libhwui.so (_ZN7android10uirenderer12renderthread12RenderThread10threadLoopEv+80)
#10 pc 0000e325 /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+144)
#11 pc 00067f31 /system/lib/libandroid_runtime.so (_ZN7android14AndroidRuntime15javaThreadShellEPv+80)
#12 pc 00047323 /system/lib/libc.so (_ZL15__pthread_startPv+22)
#13 pc 00019e5d /system/lib/libc.so (__start_thread+6)
stack:
967deed0 5fa4a63a [anon:libc_malloc]
967deed4 229e48e5 /dev/ashmem/dalvik-main space (deleted)
967deed8 bdb4dc9e /dev/dri/renderD128
967deedc 967def70
967deee0 00000000
967deee4 b54d0adb /system/lib/libhwui.so
967deee8 00000007
967deeec 03fb7340 [anon:libc_malloc]
967deef0 00001204
967deef4 00000000
967deef8 ffffffdf
967deefc 00000000
967def00 000003ff
967def04 bdb4dc9e /dev/dri/renderD128
967def08 967df978
967def0c b511d847 /system/lib/libc.so (pthread_kill+22)
#00 967def10 ffffffdf
........ ........
#01 967def10 ffffffdf
967def14 00000006
967def18 00000000
967def1c b2f1cb80 [anon:libc_malloc]
从日志中,可以看出是一个内存申请异常错误
Abort message: 'Encountered EGL error 12291 EGL_BAD_ALLOC during rendering'
异常名 | 解释说明 | |
---|---|---|
(SIGABRT) EGL_BAD_ALLOC | 内存申请异常 | |
(SEGV_MAPERR) fault addr 0x10 | 指针地址异常出错 |
第二步 addr2line
使用addr2line,我们从backstrace中拿到了出错时的指令地址,它对应我们程序中某个函数的某行操作。我们需要addr2line将对应文件和对应行数打出来。
命令的格式是 addr2line -e exefile addr
在NDK中找到对应的addr2line命令,出错APP程序文件取出来,执行命令
使用示例:
addr2line -C -e -f app 0004a0c0
结果如下:
testGetEntryById
/home/***/***/***/test.c:220
通过此方式,我们能得到错误具体位置,对照源码分析即可
以上方式,如果还不能分析出问题,可以参考第三步方法,查看汇编代码
第三步 objdump
进一步定位问题,我们需要将出错函数的汇编取到,这就用到了objdump工具。我们使用objdump将testapp反汇编重定向到文件中。然后查看对应函数的汇编代码。
000a3e54 <testGetEntryById>:
a3e54: e92d4800 push {fp, lr}
a3e58: e1a0b00d mov fp, sp
a3e5c: e24dd018 sub sp, sp, #24
a3e60: e59f10d0 ldr r1, [pc, #208] ; a3f38 <testGetEntryById+0xe4>
a3e64: e08f1001 add r1, pc, r1
a3e68: e2811004 add r1, r1, #4
a3e6c: e14b00b2 strh r0, [fp, #-2]
...//省略
a3f08: e50b0008 str r0, [fp, #-8]
a3f0c: e51b0008 ldr r0, [fp, #-8]
a3f10: e5900018 ldr r0, [r0, #24] //问题发生位置
对照源码和汇编,我们fp-2位置存放了入参Id,我们在tombstone中可以找到fp(即r11)为e16ff848,在stack中可以找到fp-2的值为0x8014。
//tombstone 截取
e16ff844 80140000 //fp-4,所以fp-2是0x8014(注意这里是小端字节序)
e16ff848 e16ff8b8 <anonymous:e1603000> //fp地址
Id = 32768, 右移9bit后是64,即blockId是64。但是g_Table.EntryBlock[]数组大小为64, index范围 0~63。64超出数组范围,造成访问溢出,取到了错误的block地址。从而导致的最终的问题发生。
总结
- 获取并查看tombstone,获知问题的基本信息
- 通过addr2line找到问题发生的具体位置。对照源码分析问题原因。
- 如果任然不能确认问题原因,我们可以对问题函数进行反汇编,对照tombstone中的寄存器,异常栈来模拟当时的执行过程。最终找到问题的根本原因