做安卓开发的同学对于tombstone问题应该是很熟悉了,但是对于如何排查和分析值得总结和整理的,这篇文章对入门安卓开发的技术来说是个入门指导,同时对安卓开发的中高级开发也有借鉴。
首先我们来说下什么是tombstone :
当一个动态库(native 程序)开始执行时,系统会注册一些连接到 debuggerd 的 signal handlers,当系统 crash 的时候,会保存一个 tombstone 文件到/data/tombstones目录下(Logcat中也会有相应的信息),文件的确就像墓碑一样记录了死亡了的进程的基本信息(例如进程的进程 号,线程号),死亡的地址(在哪个地址上发生了 Crash),死亡时的现场是什么样的(记录了一系列的堆栈调用信息)等等。
举例来看一个tombstone文件:
一个tombstone文件大概包含以下信息
--------- beginning of crash
F/libc ( 244): invalid address or address of corrupt block 0xb82f54a0 passed to dlfree
I/libc ( 244): debuggerd_signal_handler called: signal=11, fn=0xb6fbdaa1
F/libc ( 244): Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 244 (mediaserver)
I/libc ( 244): exit from debuggerd_signal_handler
W/NativeCrashListener( 916): Couldn't find ProcessRecord for pid 244
I/DEBUG ( 241): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
E/DEBUG ( 241): AM write failure (32 / Broken pipe)
I/DEBUG ( 241): Build fingerprint: XXXXXXXXX
I/DEBUG ( 241): Revision: '0'
I/DEBUG ( 241): ABI: 'arm'
I/DEBUG ( 241): pid: 244, tid: 244, name: mediaserver >>> /system/bin/mediaserver <<<
I/DEBUG ( 241): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdeadbaad
I/art ( 3078): now dumpable=1
I/DEBUG ( 241): Abort message: 'invalid address or address of corrupt block 0xb82f54a0 passed to dlfree'
I/DEBUG ( 241): r0 00000000 r1 b6f20dec r2 deadbaad r3 00000000
I/DEBUG ( 241): r4 b82f54a0 r5 b6f220f8 r6 00000000 r7 42424242
I/DEBUG ( 241): r8 ffffffff r9 b82f5460 sl 00000030 fp 00000000
I/DEBUG ( 241): ip 00000000 sp beb2c020 lr b6ef1fa7 pc b6ef1fa8 cpsr 600e0030
I/DEBUG ( 241): d0 0000000000000000 d1 6f2073736572646c
I/DEBUG ( 241): d2 707572726f632066 d3 206b636f6c622072
I/DEBUG ( 241): d4 4242424242424242 d5 4242424242424242
I/DEBUG ( 241): d6 4242424242424242 d7 3ecccccd42424242
I/DEBUG ( 241): d8 0000000000000000 d9 0000000000000000
I/DEBUG ( 241): d10 0000000000000000 d11 0000000000000000
I/DEBUG ( 241): d12 0000000000000000 d13 0000000000000000
I/DEBUG ( 241): d14 0000000000000000 d15 0000000000000000
I/DEBUG ( 241): d16 0000000000000000 d17 3ff0000000000000
I/DEBUG ( 241): d18 7e37e43c8800759c d19 bfd5f3f082400000
I/DEBUG ( 241): d20 3e66376972bea4d0 d21 bf66b12699b6468f
I/DEBUG ( 241): d22 3fc54aa75950670f d23 bfd73498f0a5ef3a
I/DEBUG ( 241): d24 3fe0000000000000 d25 bfaaf3ec933c988f
I/DEBUG ( 241): d26 0000000000000000 d27 4000000000000000
I/DEBUG ( 241): d28 4002e6931e14bde7 d29 3faaf3ec9198f99c
I/DEBUG ( 241): d30 3ff0000000000000 d31 3fd29572efd86cee
I/DEBUG ( 241): scr 20000010
I/DEBUG ( 241):
I/DEBUG ( 241): backtrace:
I/DEBUG ( 241): #00 pc 00028fa8 /system/lib/libc.so (dlfree+1239)
I/DEBUG ( 241): #01 pc 0000f2cb /system/lib/libc.so (free+10)
I/DEBUG ( 241): #02 pc 0000a1cb /system/lib/libstagefright_foundation.so (_ZN7android7ABufferD2Ev+42)
I/DEBUG ( 241): #03 pc 0000a211 /system/lib/libstagefright_foundation.so (_ZN7android7ABufferD0Ev+4)
I/DEBUG ( 241): #04 pc 0000d68d /system/lib/libutils.so (_ZNK7android7RefBase9decStrongEPKv+40)
I/DEBUG ( 241): #05 pc 0005adfd /system/lib/libstagefright.so (_ZN7android2spINS_13GraphicBufferEED2Ev+10)
I/DEBUG ( 241): #06 pc 0007cd0f /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+634)
I/DEBUG ( 241): #07 pc 0007d43d /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+2472)
I/DEBUG ( 241): #08 pc 0007e873 /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor12readMetaDataEv+58)
I/DEBUG ( 241): #09 pc 0007eaa1 /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor11countTracksEv+4)
I/DEBUG ( 241): #10 pc 000acf9d /system/lib/libstagefright.so (_ZN7android13ExtendedUtils29MediaExtractor_CreateIfNeededENS_2spINS_14MediaExtractorEEERKNS1_INS_10DataSourceEEEPKc+60)
I/DEBUG ( 241): #11 pc 0008e3f5 /system/lib/libstagefright.so (_ZN7android14MediaExtractor6CreateERKNS_2spINS_10DataSourceEEEPKc+624)
I/DEBUG ( 241): #12 pc 0006ace9 /system/lib/libstagefright.so (_ZN7android13AwesomePlayer15setDataSource_lERKNS_2spINS_10DataSourceEEE+12)
I/DEBUG ( 241): #13 pc 0006c0dd /system/lib/libstagefright.so (_ZN7android13AwesomePlayer13setDataSourceEixx+228)
I/DEBUG ( 241): #14 pc 0003d647 /system/lib/libmediaplayerservice.so (_ZN7android18MediaPlayerService6Client13setDataSourceEixx+362)
I/DEBUG ( 241): #15 pc 0005ea03 /system/lib/libmedia.so (_ZN7android13BnMediaPlayer10onTransactEjRKNS_6ParcelEPS1_j+478)
I/DEBUG ( 241): #16 pc 00017fad /system/lib/libbinder.so (_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j+60)
I/DEBUG ( 241): #17 pc 0001cfdb /system/lib/libbinder.so (_ZN7android14IPCThreadState14executeCommandEi+562)
I/DEBUG ( 241): #18 pc 0001d12f /system/lib/libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+38)
I/DEBUG ( 241): #19 pc 0001d171 /system/lib/libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+48)
I/DEBUG ( 241): #20 pc 00001721 /system/bin/mediaserver
I/DEBUG ( 241): #21 pc 0000f411 /system/lib/libc.so (__libc_init+44)
I/DEBUG ( 241): #22 pc 00001998 /system/bin/mediaserver
I/DEBUG ( 241):
I/DEBUG ( 241): stack:
I/DEBUG ( 241): beb2bfe0 00000000
I/DEBUG ( 241): beb2bfe4 29ec038f
I/DEBUG ( 241): beb2bfe8 0009eb34
I/DEBUG ( 241): beb2bfec b82f54a0 [heap]
I/DEBUG ( 241): beb2bff0 b6f220f8
I/DEBUG ( 241): beb2bff4 00000000
I/DEBUG ( 241): beb2bff8 42424242
I/DEBUG ( 241): beb2bffc b6edb3d1 /system/lib/libc.so (__libc_fatal_no_abort+16)
I/DEBUG ( 241): beb2c000 b6f12f97 /system/lib/libc.so
I/DEBUG ( 241): beb2c004 beb2c014 [stack]
I/DEBUG ( 241): beb2c008 b6f167be /system/lib/libc.so
I/DEBUG ( 241): beb2c00c b6ef1fa7 /system/lib/libc.so (dlfree+1238)
I/DEBUG ( 241): beb2c010 b6f12f97 /system/lib/libc.so
I/DEBUG ( 241): beb2c014 b82f54a0 [heap]
I/DEBUG ( 241): beb2c018 b6f167be /system/lib/libc.so
I/DEBUG ( 241): beb2c01c b82f54b0 [heap]
I/DEBUG ( 241): #00 beb2c020 b82f5460 [heap]
......
它包含了发生问题的进程ID信息
I/DEBUG ( 241): pid: 244, tid: 244, name: mediaserver >>> /system/bin/mediaserver <<<
当 tid == pid 时,问题发生在父进程,反之问题发生在子进程,从上面的日志信息可以看出发生问题的进程是mediaserver的子进程。
Terminated signal 和 fault address 信息
F/libc ( 244): Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 244 (mediaserver)
这里的信息说明出现进程 Crash 的原因是因为程序产生了段错误的信号,访问了非法的内存空间,而访问的非法地址是 0xdeadbaad。
当然这个是比较简单的,稍微复杂一些的,需要查看崩溃的堆栈所在文件和代码行,那么我们可以借鉴addr2line工具来分析。
addr2line工具是一个可以将指令的地址和可执行映像转换为文件名、函数名和源代码行数的工具。这在内核执行过程中出现崩溃时,可用于快速定位出出错的位置,进而找出代码的bug。
用法:
addr2line [-a| --addresses ] [-b bfdname | --target=bfdname] [-C | --demangle[=style]] [-e filename | --exe=filename] [-f | --function] [-s | --basename] [-i | --inlines] [-p | --pretty-print] [-j | --section=name] [-H | --help] [-V | --version] [addr addr ...]
这里对参数说明下:
-a --addresses:在函数名、文件和行号信息之前,显示地址,以十六进制形式。
-b --target=<bfdname>:指定目标文件的格式为bfdname。
-e --exe=<executable>:指定需要转换地址的可执行文件名。
-i --inlines : 如果需要转换的地址是一个内联函数,则输出的信息包括其最近范围内的一个非内联函数的信息。
-j --section=<name>:给出的地址代表指定section的偏移,而非绝对地址。
-p --pretty-print:使得该函数的输出信息更加人性化:每一个地址的信息占一行。
-s --basenames:仅仅显示每个文件名的基址(即不显示文件的具体路径,只显示文件名)。
-f --functions:在显示文件名、行号输出信息的同时显示函数名信息。
-C --demangle[=style]:将低级别的符号名解码为用户级别的名字。
-h --help:输出帮助信息。
-v --version:输出版本号。
所以对于上边的tombstone文件我们借助工具来分析: addr2line -Cfse so动态库/exe路径 地址address
就能根据输出来看到对应的cpp文件 和对应行数来分析。
转载:https://blog.csdn.net/pbymw8iwm/article/details/102537230