// The shared foreground thread is the main checker. It is where we // will also dispatch monitor checks and do other work. mMonitorChecker = newHandlerChecker(FgThread.getHandler(), "foreground thread", DEFAULT_TIMEOUT); mHandlerCheckers.add(mMonitorChecker); // Add checker for main thread. We only do a quick check since there // can be UI running on the thread. mHandlerCheckers.add(newHandlerChecker(newHandler(Looper.getMainLooper()), "main thread", DEFAULT_TIMEOUT)); // Add checker for shared UI thread. mHandlerCheckers.add(newHandlerChecker(UiThread.getHandler(), "ui thread", DEFAULT_TIMEOUT)); // And also check IO thread. mHandlerCheckers.add(newHandlerChecker(IoThread.getHandler(), "i/o thread", DEFAULT_TIMEOUT)); // And the display thread. mHandlerCheckers.add(newHandlerChecker(DisplayThread.getHandler(), "display thread", DEFAULT_TIMEOUT));
// Initialize monitor for Binder threads. addMonitor(newBinderThreadMonitor()); }
/* * Catches fatal signals so we can ask debuggerd to ptrace us before * we crash. */ staticvoiddebuggerd_signal_handler(int signal_number, siginfo_t* info, void*){ // It's possible somebody cleared the SA_SIGINFO flag, which would mean // our "info" arg holds an undefined value. if (!have_siginfo(signal_number)) { info = nullptr; }
staticvoidsend_debuggerd_packet(siginfo_t* info){ // Mutex to prevent multiple crashing threads from trying to talk // to debuggerd at the same time. staticpthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER; int ret = pthread_mutex_trylock(&crash_mutex); ... // 连接debuggerd int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM | SOCK_CLOEXEC); if (s == -1) { __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s", strerror(errno)); return; }
// debuggerd knows our pid from the credentials on the // local socket but we need to tell it the tid of the crashing thread. // debuggerd will be paranoid and verify that we sent a tid // that's actually in our process. debugger_msg_t msg; // crash msg.action = DEBUGGER_ACTION_CRASH; msg.tid = gettid(); msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_abort_message); msg.original_si_code = (info != nullptr) ? info->si_code : 0; // 向socket写入数据 ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg))); if (ret == sizeof(msg)) { char debuggerd_ack; ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1)); int saved_errno = errno; notify_gdb_of_libraries(); errno = saved_errno; } else { // read or write failed -- broken connection? __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s", strerror(errno)); } // 关闭socket close(s); }
staticintdo_server(){ // debuggerd crashes can't be reported to debuggerd. // Reset all of the crash handlers. signal(SIGABRT, SIG_DFL); signal(SIGBUS, SIG_DFL); signal(SIGFPE, SIG_DFL); signal(SIGILL, SIG_DFL); signal(SIGSEGV, SIG_DFL); #ifdef SIGSTKFLT signal(SIGSTKFLT, SIG_DFL); #endif signal(SIGTRAP, SIG_DFL);
// Ignore failed writes to closed sockets signal(SIGPIPE, SIG_IGN); .... // 创建服务端socket int s = socket_local_server(SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM | SOCK_CLOEXEC);
// Fork a process that stays root, and listens on a pipe to pause and resume the target.(具体什么作用,没看明白) if (!start_signal_sender()) { ALOGE("debuggerd: failed to fork signal sender"); return1; } // 监听并处理客户端进程请求 for (;;) { sockaddr_storage ss; sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss); socklen_t alen = sizeof(ss);
ALOGV("waiting for connection\n"); int fd = accept4(s, addrp, &alen, SOCK_CLOEXEC); if (fd == -1) { continue; }
staticvoidworker_process(int fd, debugger_request_t& request){ // Open the tombstone file if we need it. std::string tombstone_path; int tombstone_fd = -1; switch (request.action) { case DEBUGGER_ACTION_DUMP_TOMBSTONE: case DEBUGGER_ACTION_CRASH: tombstone_fd = open_tombstone(&tombstone_path); if (tombstone_fd == -1) { ALOGE("debuggerd: failed to open tombstone file: %s\n", strerror(errno)); exit(1); } break; .... }
// Don't attach to the sibling threads if we want to attach gdb. // Supposedly, it makes the process less reliable. bool attach_gdb = should_attach_gdb(request); .... std::set<pid_t> siblings; if (!attach_gdb) { ptrace_siblings(request.pid, request.tid, siblings); }
int amfd = -1; std::unique_ptr<std::string> amfd_data; if (request.action == DEBUGGER_ACTION_CRASH) { // 连接AMS amfd = activity_manager_connect(); amfd_data.reset(new std::string); }
bool succeeded = false; .... int crash_signal = SIGKILL; // 保存DUMP LOG succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings, &crash_signal, amfd_data.get()); if (succeeded) { if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) { if (!tombstone_path.empty()) { android::base::WriteFully(fd, tombstone_path.c_str(), tombstone_path.length()); } } } .... if (!attach_gdb) { // Tell the Activity Manager about the crashing process. If we are // waiting for gdb to attach, do not send this or Activity Manager // might kill the process before anyone can attach. activity_manager_write(request.pid, crash_signal, amfd, *amfd_data.get()); } ....
structsockaddr_un address; memset(&address, 0, sizeof(address)); address.sun_family = AF_UNIX; // The path used here must match the value defined in NativeCrashListener.java. strncpy(address.sun_path, "/data/system/ndebugsocket", sizeof(address.sun_path)); if (TEMP_FAILURE_RETRY(connect(amfd.get(), reinterpret_cast<struct sockaddr*>(&address), sizeof(address))) == -1) { return-1; }
// The file system entity for this socket is created with 0700 perms, owned // by system:system. debuggerd runs as root, so is capable of connecting to // it, but 3rd party apps cannot. .... try { FileDescriptorserverFd= Os.socket(AF_UNIX, SOCK_STREAM, 0); finalUnixSocketAddresssockAddr= UnixSocketAddress.createFileSystem( DEBUGGERD_SOCKET_PATH); Os.bind(serverFd, sockAddr); Os.listen(serverFd, 1);
while (true) { FileDescriptorpeerFd=null; try { // 等待客户端连接 peerFd = Os.accept(serverFd, null/* peerAddress */); if (MORE_DEBUG) Slog.v(TAG, "Got debuggerd socket " + peerFd); if (peerFd != null) { // Only the superuser is allowed to talk to us over this socket StructUcredcredentials= Os.getsockoptUcred(peerFd, SOL_SOCKET, SO_PEERCRED); if (credentials.uid == 0) { // 处理Crash数据 consumeNativeCrashData(peerFd); } } } catch (Exception e) { Slog.w(TAG, "Error handling connection", e); } finally { .... } } } catch (Exception e) { Slog.e(TAG, "Unable to init native debug socket!", e); } }
// first, the pid and signal number intheaderBytes= readExactly(fd, buf, 0, 8); if (headerBytes != 8) { // protocol failure; give up Slog.e(TAG, "Unable to read from debuggerd"); return; }
// now the text of the dump if (pid > 0) { final ProcessRecord pr; synchronized (mAm.mPidsSelfLocked) { pr = mAm.mPidsSelfLocked.get(pid); } if (pr != null) { // Don't attempt crash reporting for persistent apps if (pr.persistent) { return; }
int bytes; do { // get some data bytes = Os.read(fd, buf, 0, buf.length); if (bytes > 0) { // did we just get the EOD null byte? if (buf[bytes-1] == 0) { os.write(buf, 0, bytes-1); // exclude the EOD token break; } // no EOD, so collect it and read more os.write(buf, 0, bytes); } } while (bytes > 0); .... // 启动另一个线程NativeCrashReporter通知AMS finalStringreportString=newString(os.toByteArray(), "UTF-8"); (newNativeCrashReporter(pr, signal, reportString)).start(); } else { Slog.w(TAG, "Couldn't find ProcessRecord for pid " + pid); } } else { Slog.e(TAG, "Bogus pid!"); } } catch (Exception e) { Slog.e(TAG, "Exception dealing with report", e); // ugh, fail. } }