Linux信号机制
信号机制是Linux进程间通信的一种重要方式,Linux信号一方面用于正常的进程间通信和同步,另一方面它还负责监控系统异常及中断。当应用程序运行异常时,Linux内核将产生错误信号并通知当前进程。
常见崩溃信号列表:
信号 | 描述 |
SIGSEGV | 内存引用无效 |
SIGBUS | 访问内存对象的未定义部分 |
SIGFPE | 算术运算错误,除以零 |
SIGILL | 非法指令,如执行垃圾或特权指令 |
SIGSYS | 糟糕的系统调用 |
SIGXCPU | 超过CPU时间限制 |
SIGXFSZ | 文件大小限制 |
一般的出现崩溃信号,Android系统默认缺省操作是直接退出我们的程序。但是系统允许我们给某一个进程的某一个特定信号注册一个相应的处理函数(signal),即对该信号的默认处理动作进行修改。因此NDK Crash的监控可以采用这种信号机制,捕获崩溃信号执行我们自己的信号处理函数从而捕获NDKCrash
BreakPad
Google breakpad是一个跨平台的崩溃转储和分析框架和工具集合,其开源地址是:https://github.com/google/breakpad。breakpad在Linux中的实现就是借助了Linux信号捕获机制实现的。因为其实现为C++,因此在Android中使用,必须借助NDK工具
接入方式省略
crash后会议指定目录生成.dmp文件
Crash解析
采集到的Crash信息记录在minidump文件中。minidump是由微软开发的用于崩溃上传的文件格式。我们可以将此文件上传到服务器完成上报,但是此文件没有可读性可言,要将文件解析为可读的崩溃堆栈需要按照breakpad文档编译 minidump_stackwalk 工具,无论你是 Mac、windows还是ubuntu在 Android Studio 的安装目录下的 bin\lldb\bin 里面就存在一个对应平台的minidump_stackwalk
minidump_stackwalk xxxx.dump > crash.txt
打开 crash.txt 内容为:
Operating system: Android
0.0.0 Linux 4.4.124+ #1 SMP PREEMPT Wed Jan 30 07:13:09 UTC
2019 i686
CPU: x86 // abi类型
GenuineIntel family 6 model 31 stepping 1
3 CPUs
GPU: UNKNOWN
Crash reason: SIGSEGV //内存引用无效 信号
Crash address: 0x0
Process uptime: not available
Thread 0 (crashed) //crashed:出现crash的线程
0 libbugly.so + 0x1feab //crash的so与寄存器信息
eip = 0xd5929eab esp = 0xffa85f30 ebp = 0xffa85f38 ebx = 0x0000000c
esi = 0xd71a3f04 edi = 0xffa86128 eax = 0xffa85f5c ecx = 0xefb19400
edx = 0x00000000 efl = 0x00210286
Found by: given as instruction pointer in context
1 libart.so + 0x5f6a18
eip = 0xef92ea18 esp = 0xffa85f40 ebp = 0xffa85f60
Found by: previous frame's frame pointer
Thread 1
......
接下来使用 Android NDK 里面提供的 addr2line 工具将寄存器地址转换为对应符号。addr2line 要用和自己 so 的 ABI 匹配的目录,同时需要使用有符号信息的so(一般debug的就有)。
i686-linux-android-addr2line.exe -f -C -e libbugly.so 0x1feab