Crash类型:
Framework/App Crash:Java层崩溃
Native Crash:C/C++层崩溃
Kernel Crash:内核崩溃
tombstone文件的组成部分:
Build fingerprint
Crashed process and PIDS
Terminated signal and fault address
CPU registers
Call stack
Stack content of each call
1 2 3 4 5 6 7 8 9 10 11 12 13 --logversion:utracea Process Name: 'com.feiteng.lieyou' Thread Name: 'RenderThread' pid: 25031, tid: 25237 >>> com.feiteng.lieyou <<< killed by pid: 25031, comm: .feiteng.lieyou, uid: 10125. signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- r0 00000000 r1 00006295 r2 00000006 r3 00000008 r4 c587c978 r5 00000006 r6 c587c920 r7 0000010c r8 bf249bc8 r9 00000000 10 bf249bbc fp bf249bb8 ip 00000004 sp c587c3b0 lr eba21907 pc eba24188 cpsr 20070010 d0 0000000000000000 d1 0000000000000000 d2 0000000000000000 d3 0000000000000000
signal指定异常类型。如果pid等于tid,则说明程序是在主线程中崩溃。
signal下一行为寄存器快照
backtrace下面为异常调用堆栈
信号类型: 软中断信号(signal,又简称为信号)用来通知进程发生了事件。进程之间可以通过调用kill库函数发送软中断信号。Linux内核也可能给进程发送信号, 通知进程发生了某个事件(例如内存越界)。
信号只是用来通知某进程发生了什么事件,无法给进程传递任何数据,进程对信号的处理方法有三种:
第一种方法是,忽略某个信号,对该信号不做任何处理,就象未发生过一样。
第二种是设置中断的处理函数,收到信号后,由该函数来处理。
第三种方法是,对该信号的处理采用系统的默认操作,大部分的信号的默认操作是终止进程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 sighandler_t signal (int signum, sighandler_t handler) ;int kill (pid_t pid, int sig) ;#define SIGHUP 1 #define SIGINT 2 #define SIGQUIT 3 #define SIGILL 4 #define SIGTRAP 5 #define SIGABRT 6 #define SIGIOT 6 #define SIGBUS 7 #define SIGFPE 8 #define SIGKILL 9 #define SIGUSR1 10 #define SIGSEGV 11 #define SIGUSR2 12 #define SIGPIPE 13 #define SIGALRM 14 #define SIGTERM 15 #define SIGSTKFLT 16 #define SIGCHLD 17 #define SIGCONT 18 #define SIGSTOP 19 #define SIGTSTP 20 #define SIGTTIN 21 #define SIGTTOU 22 #define SIGURG 23 #define SIGXCPU 24 #define SIGXFSZ 25 #define SIGVTALRM 26 #define SIGPROF 27 #define SIGWINCH 28 #define SIGIO 29 #define SIGPOLL SIGIO #define SIGPWR 30 #define SIGSYS 31
tombstone 文件位于路径 /data/tombstones/下
调用栈信息 调用栈信息是分析程序崩溃的非常重要的一个信息,它主要记录了程序在 Crash 前的函数调用关系以及当前正在执行函数的信息,它对应的是我们tombstone 文件中 backtrace 符号开始的信息,上面例子中的 backtrace 的信息如下所示
1 2 3 4 5 6 7 8 9 10 backtrace: #00 pc 00006639 /system/lib/libui.so (android::Fence::waitForever(char const*)+41) #01 pc 00034b86 /system/lib/libsurfaceflinger.so #02 pc 0003229e /system/lib/libsurfaceflinger.so #03 pc 0002cb9c /system/lib/libgui.so (android::BufferQueue::ProxyConsumerListener::onFrameAvailable(android::BufferItem const&)+652) #04 pc 000342f4 /system/lib/libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+2580) ##00 等表示函数调用栈中栈帧的编号 pc 后面的16进制数表示当前函数正在执行语句在共享链接库或可执行文件的位置 最后一行表示当前指令在哪个文件
如何定位崩溃位置 完整的so文件包含代码和一些debug信息,release版的so文件需要经过一个strip操作,debug信息会被剥离,整个so文件的大小会变小。要定位具体位置,则需要使用debug版本的so文件
常用工具 nm 1 2 查看动态库的符号表 nm -D libName.so
addr2line 用来分析单个pc地址对应的源码行数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Usage: /Users/loneqd/Android/sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line [option(s)] [addr(s)] Convert addresses into line number/file name pairs. If no addresses are specified on the command line, they will be read from stdin The options are: @<file> Read options from <file> -a --addresses Show addresses -b --target=<bfdname> Set the binary file format -e --exe=<executable> Set the input file name (default is a.out) -i --inlines Unwind inlined functions -j --section=<name> Read section-relative offsets instead of addresses -p --pretty-print Make the output easier to read for humans -s --basenames Strip directory names -f --functions Show function names -C --demangle[=style] Demangle function names -h --help Display this information -v --version Display the program's version 实例:(需使用带symbol的动态库) addr2line -f -e libui.so 00006639 _ZN7android5Fence11waitForeverE
ndk-stack 将崩溃时的调用内存地址和C++代码对应起来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 usage: ndk-stack.py [-h] -sym SYMBOL_DIR [-i INPUT] Symbolizes Android crashes. optional arguments: -h, --help show this help message and exit -sym SYMBOL_DIR, --sym SYMBOL_DIR directory containing unstripped .so files -i INPUT, -dump INPUT, --dump INPUT input filename See <https://developer.android.com/ndk/guides/ndk-stack>. sym指项目编译成功之后,obj目录 dump指崩溃文件
xCrash的使用
native异常日志文件的格式
1 2 3 4 5 6 7 8 9 10 11 12 13 日志分为: 头部信息(为应用的基本信息) 异常信号部分。(哪个异常信号导致异常,信号参见Linux信号) backtrace so库的编译信息,build id 堆栈信息 内存信息 内存映射 logcat日志输出部分,包括main,system,event app应用进程打开的文件描述符 内存信息 app应用进程信息 异常回调填充信息
一般根据backtrace,再使用addr2line命令定位具体的错误代码位置。
参考