android crash 流程分析

一 簡述

android crash分為兩類:一類是native crash,一類是java虛擬機的crash。

二 Native crash流程

1) native的crash是native的code運行異常,收到內(nèi)核發(fā)送的signal,進而crash的流程,常見的有abort等

static void __attribute__((__unused__)) debuggerd_register_handlers(struct sigaction* action) {
  char value[PROP_VALUE_MAX] = "";
  bool enabled =
      !(__system_property_get("ro.debuggable", value) > 0 && !strcmp(value, "1") &&
        __system_property_get("debug.debuggerd.disable", value) > 0 && !strcmp(value, "1"));
  if (enabled) {
    sigaction(SIGABRT, action, nullptr);
    sigaction(SIGBUS, action, nullptr);
    sigaction(SIGFPE, action, nullptr);
    sigaction(SIGILL, action, nullptr);
    sigaction(SIGSEGV, action, nullptr);
    sigaction(SIGSTKFLT, action, nullptr);
    sigaction(SIGSYS, action, nullptr);
    sigaction(SIGTRAP, action, nullptr);
  }

  sigaction(BIONIC_SIGNAL_DEBUGGER, action, nullptr);
}
void debuggerd_init(debuggerd_callbacks_t* callbacks) {
  if (callbacks) {
    g_callbacks = *callbacks;
  }

  size_t thread_stack_pages = 8;
  void* thread_stack_allocation = mmap(nullptr, PAGE_SIZE * (thread_stack_pages + 2), PROT_NONE,
                                       MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  if (thread_stack_allocation == MAP_FAILED) {
    fatal_errno("failed to allocate debuggerd thread stack");
  }

  char* stack = static_cast<char*>(thread_stack_allocation) + PAGE_SIZE;
  if (mprotect(stack, PAGE_SIZE * thread_stack_pages, PROT_READ | PROT_WRITE) != 0) {
    fatal_errno("failed to mprotect debuggerd thread stack");
  }

  // Stack grows negatively, set it to the last byte in the page...
  stack = (stack + thread_stack_pages * PAGE_SIZE - 1);
  // and align it.
  stack -= 15;
  pseudothread_stack = stack;

  struct sigaction action;
  memset(&action, 0, sizeof(action));
  sigfillset(&action.sa_mask);
  action.sa_sigaction = debuggerd_signal_handler;
  action.sa_flags = SA_RESTART | SA_SIGINFO;

  // Use the alternate signal stack if available so we can catch stack overflows.
  action.sa_flags |= SA_ONSTACK;
  debuggerd_register_handlers(&action);
}

在linker中進行初始化

void linker_debuggerd_init() {
  debuggerd_callbacks_t callbacks = {
    .get_abort_message = []() {
      return __libc_shared_globals()->abort_msg;
    },
    .post_dump = &notify_gdb_of_libraries,
    .get_gwp_asan_state = []() {
      return __libc_shared_globals()->gwp_asan_state;
    },
    .get_gwp_asan_metadata = []() {
      return __libc_shared_globals()->gwp_asan_metadata;
    },
  };
  debuggerd_init(&callbacks);
}

在runtime運行時:

Runtime::InitPlatformSignalHandlers

void InitPlatformSignalHandlersCommon(void (*newact)(int, siginfo_t*, void*),
                                      struct sigaction* oldact,
                                      bool handle_timeout_signal) {
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  sigemptyset(&action.sa_mask);
  action.sa_sigaction = newact;
  // Use the three-argument sa_sigaction handler.
  action.sa_flags |= SA_SIGINFO;
  // Use the alternate signal stack so we can catch stack overflows.
  action.sa_flags |= SA_ONSTACK;

  int rc = 0;
  rc += sigaction(SIGABRT, &action, oldact);
  rc += sigaction(SIGBUS, &action, oldact);
  rc += sigaction(SIGFPE, &action, oldact);
  rc += sigaction(SIGILL, &action, oldact);
  rc += sigaction(SIGPIPE, &action, oldact);
  rc += sigaction(SIGSEGV, &action, oldact);
#if defined(SIGSTKFLT)
  rc += sigaction(SIGSTKFLT, &action, oldact);
#endif
  rc += sigaction(SIGTRAP, &action, oldact);
  // Special dump-all timeout.
  if (handle_timeout_signal && GetTimeoutSignal() != -1) {
    rc += sigaction(GetTimeoutSignal(), &action, oldact);
  }
  CHECK_EQ(rc, 0);
}

上述流程執(zhí)行是在bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in)中初始化

傷處兩次注冊都運行的,如下:

void HandleUnexpectedSignalAndroid(int signal_number, siginfo_t* info, void* raw_context) {
  HandleUnexpectedSignalCommon(signal_number,
                               info,
                               raw_context,
                               /* handle_timeout_signal= */ false,
                               /* dump_on_stderr= */ false);

  // Run the old signal handler.
  old_action.sa_sigaction(signal_number, info, raw_context);
}

linker的action后執(zhí)行,HandleUnexpectedSignalCommon先執(zhí)行。
第一處打印主要是

libc    : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 21455 (RenderThread), pid 21455 (XXXX)

在linker注冊的運行二進制bin crash_dump64

I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
I tombstoned: received crash request for pid 21475
I crash_dump64: performing dump of process 21453 (target tid = 21475)

同時將app crash信息通知AMS

static bool activity_manager_notify(pid_t pid, int signal, const std::string& amfd_data) {

三 java層面crash執(zhí)行流程

java層面的異常一般是try-catch無法捕獲的異常,進入crash流程。
在RuntimeInit.java 設(shè)置default 異常處理

    @UnsupportedAppUsage
    protected static final void commonInit() {
        if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

        /*
         * set handlers; these apply to all threads in the VM. Apps can replace
         * the default handler, but not the pre handler.
         */
        LoggingHandler loggingHandler = new LoggingHandler();
        RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
        Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));

在異常被捕獲后,流程處理如下:

    private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler {


        @Override
        public void uncaughtException(Thread t, Throwable e) {
            try {
                ensureLogging(t, e);

                // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
                if (mCrashing) return;
                mCrashing = true;

                // Try to end profiling. If a profiler is running at this point, and we kill the
                // process (below), the in-memory buffer will be lost. So try to stop, which will
                // flush the buffer. (This makes method trace profiling useful to debug crashes.)
                if (ActivityThread.currentActivityThread() != null) {
                    ActivityThread.currentActivityThread().stopProfiling();
                }

                // Bring up crash dialog, wait for it to be dismissed
                ActivityManager.getService().handleApplicationCrash(
                        mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
            } catch (Throwable t2) {
                if (t2 instanceof DeadObjectException) {
                    // System process is dead; ignore
                } else {
                    try {
                        Clog_e(TAG, "Error reporting crash", t2);
                    } catch (Throwable t3) {
                        // Even Clog_e() fails!  Oh well.
                    }
                }
            } finally {
                // Try everything to make sure this process goes away.
                Process.killProcess(Process.myPid());
                System.exit(10);
            }
        }

主要執(zhí)行有兩步: 一個是通知AMS,另外一個是進程退出

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容