本文是基于Android 7.0源码,来分析Native Crash流程。
一、Native Crash
从系统全局来说,Crash分为Framework/App Crash, Native Crash,以及Kernel Crash。
- 对于framework层或者app层的Crash(即Java层面Crash),那么往往是通过抛出未捕获异常而导致的Crash,这个内容在本文的姊妹篇理解Android Crash处理流程已详细介绍过。
- 至于Kernel Crash,很多情况是发生Kernel panic,对于内核崩溃往往是驱动或者硬件出现故障。
- Native Crash,即C/C++层面的Crash,这是介于系统framework层与Linux层之间的一层,这是本文接下来要讲解的内容。
如果你是从事Android系统开发或者架构相关工作,或者遇到需要解系统性的疑难杂症,再或者需要写JNI代码,则就有可能遇到Native Crash,了解系统Native Crash处理流程就很有必要。
接下来介绍介绍Android N
的Native Crash处理流程,你没有看错,本文就是针对最新Android Nouget来分析的。Native crash的工作核心是由debuggerd守护进程来完成,在文章调试系列4:debuggerd源码篇),已经介绍过Debuggerdd的工作原理。
要了解Native Crash,首先从应用程序入口位于begin.S
中的__linker_init
入手。
1.1 begin.S
[-> arch/arm/begin.S]
1 2 3 4 5 6 7 |
ENTRY(_start) mov r0, sp //入口地址 【见小节1.2】 bl __linker_init /* linker init returns the _entry address in the main image */ mov pc, r0 END(_start) |
1.2 __linker_init
[-> linker.cpp]
1 2 3 4 5 6 7 8 |
extern "C" ElfW(Addr) __linker_init(void* raw_args) { KernelArgumentBlock args(raw_args); ElfW(Addr) linker_addr = args.getauxval(AT_BASE); ... //【见小节1.3】 ElfW(Addr) start_address = __linker_init_post_relocation(args, linker_addr); return start_address; } |
1.3 __linker_init_post_relocation
[-> linker.cpp]
1 2 3 4 5 6 7 8 9 10 |
static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(Addr) linker_base) { ... // Sanitize the environment. __libc_init_AT_SECURE(args); // Initialize system properties __system_properties_init(); //【见小节1.4】 debuggerd_init(); ... } |
1.4 debuggerd_init
[-> linker/debugger.cpp]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
__LIBC_HIDDEN__ void debuggerd_init() { struct sigaction action; memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); //【见小节1.5】 action.sa_sigaction = debuggerd_signal_handler; //SA_RESTART代表中断某个syscall,则会自动重新调用该syscall //SA_SIGINFO代表信号附带参数siginfo_t结构体可传送到signal_handler函数 action.sa_flags = SA_RESTART | SA_SIGINFO; //使用备用signal栈(如果可用),以便我们能捕获栈溢出 action.sa_flags |= SA_ONSTACK; sigaction(SIGABRT, &action, nullptr); sigaction(SIGBUS, &action, nullptr); sigaction(SIGFPE, &action, nullptr); sigaction(SIGILL, &action, nullptr); sigaction(SIGPIPE, &action, nullptr); sigaction(SIGSEGV, &action, nullptr); #if defined(SIGSTKFLT) sigaction(SIGSTKFLT, &action, nullptr); #endif sigaction(SIGTRAP, &action, nullptr); } |
1.5 debuggerd_signal_handler
连接到bionic上的native程序(C/C++)出现异常时,kernel会发送相应的signal; 当进程捕获致命的signal,通知debuggerd调用ptrace来获取有价值的信息(发生crash之前)。
[-> linker/debugger.cpp]