Loading debuggerd/backtrace.c +2 −1 Original line number Diff line number Diff line Loading @@ -112,10 +112,11 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a } } void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed, void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, int* total_sleep_time_usec) { log_t log; log.tfd = fd; log.amfd = amfd; log.quiet = true; ptrace_context_t* context = load_ptrace_context(tid); Loading debuggerd/backtrace.h +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ /* Dumps a backtrace using a format similar to what Dalvik uses so that the result * can be intermixed in a bug report. */ void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed, void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, int* total_sleep_time_usec); #endif // _DEBUGGERD_BACKTRACE_H debuggerd/debuggerd.c +2 −1 Original line number Diff line number Diff line Loading @@ -314,7 +314,8 @@ static void handle_request(int fd) { &total_sleep_time_usec); } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) { XLOG("stopped -- dumping to fd\n"); dump_backtrace(fd, request.pid, request.tid, &detach_failed, dump_backtrace(fd, -1, request.pid, request.tid, &detach_failed, &total_sleep_time_usec); } else { XLOG("stopped -- continuing\n"); Loading debuggerd/tombstone.c +59 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,9 @@ #include <corkscrew/demangle.h> #include <corkscrew/backtrace.h> #include <sys/socket.h> #include <linux/un.h> #include <selinux/android.h> #include "machine.h" Loading @@ -47,6 +50,9 @@ #define MAX_TOMBSTONES 10 #define TOMBSTONE_DIR "/data/tombstones" /* Must match the path defined in NativeCrashListener.java */ #define NCRASH_SOCKET_PATH "/data/system/ndebugsocket" #define typecheck(x,y) { \ typeof(x) __dummy1; \ typeof(y) __dummy2; \ Loading Loading @@ -627,6 +633,18 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, property_get("ro.debuggable", value, "0"); bool want_logs = (value[0] == '1'); if (log->amfd >= 0) { /* * Activity Manager protocol: binary 32-bit network-byte-order ints for the * pid and signal number, followed by the raw text of the dump, culminating * in a zero byte that marks end-of-data. */ uint32_t datum = htonl(pid); TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) ); datum = htonl(signal); TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) ); } _LOG(log, false, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); dump_build_info(log); Loading @@ -653,6 +671,16 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, if (want_logs) { dump_logs(log, pid, false); } /* send EOD to the Activity Manager, then wait for its ack to avoid racing ahead * and killing the target out from under it */ if (log->amfd >= 0) { uint8_t eodMarker = 0; TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) ); /* 3 sec timeout reading the ack; we're fine if that happens */ TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) ); } return detach_failed; } Loading Loading @@ -712,6 +740,35 @@ static char* find_and_open_tombstone(int* fd) return strdup(path); } static int activity_manager_connect() { int amfd = socket(PF_UNIX, SOCK_STREAM, 0); if (amfd >= 0) { struct sockaddr_un address; int err; memset(&address, 0, sizeof(address)); address.sun_family = AF_UNIX; strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path)); err = TEMP_FAILURE_RETRY( connect(amfd, (struct sockaddr*) &address, sizeof(address)) ); if (!err) { struct timeval tv; memset(&tv, 0, sizeof(tv)); tv.tv_sec = 1; // tight leash err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); if (!err) { tv.tv_sec = 3; // 3 seconds on handshake read err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); } } if (err) { close(amfd); amfd = -1; } } return amfd; } char* engrave_tombstone(pid_t pid, pid_t tid, int signal, bool dump_sibling_threads, bool quiet, bool* detach_failed, int* total_sleep_time_usec) { Loading @@ -732,10 +789,12 @@ char* engrave_tombstone(pid_t pid, pid_t tid, int signal, log_t log; log.tfd = fd; log.amfd = activity_manager_connect(); log.quiet = quiet; *detach_failed = dump_crash(&log, pid, tid, signal, dump_sibling_threads, total_sleep_time_usec); close(log.amfd); close(fd); return path; } debuggerd/utility.c +39 −3 Original line number Diff line number Diff line Loading @@ -25,27 +25,63 @@ #include <cutils/logd.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <arpa/inet.h> #include <assert.h> #include "utility.h" const int sleep_time_usec = 50000; /* 0.05 seconds */ const int max_total_sleep_usec = 10000000; /* 10 seconds */ static int write_to_am(int fd, const char* buf, int len) { int to_write = len; while (to_write > 0) { int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) ); if (written < 0) { /* hard failure */ return -1; } to_write -= written; } return len; } void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...) { char buf[512]; bool want_tfd_write; bool want_log_write; bool want_amfd_write; int len; va_list ap; va_start(ap, fmt); if (log && log->tfd >= 0) { int len; // where is the information going to go? want_tfd_write = log && log->tfd >= 0; // write to the tombstone fd? want_log_write = !in_tombstone_only && (!log || !log->quiet); want_amfd_write = log && log->amfd >= 0; // only used when want_log_write is true // if we're going to need the literal string, generate it once here if (want_tfd_write || want_amfd_write) { vsnprintf(buf, sizeof(buf), fmt, ap); len = strlen(buf); } if (want_tfd_write) { write(log->tfd, buf, len); } if (!in_tombstone_only && (!log || !log->quiet)) { if (want_log_write) { // whatever goes to logcat also goes to the Activity Manager __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap); if (want_amfd_write && len > 0) { int written = write_to_am(log->amfd, buf, len); if (written <= 0) { // timeout or other failure on write; stop informing the activity manager LOG("AM write failure, giving up\n"); log->amfd = -1; } } } va_end(ap); } Loading Loading
debuggerd/backtrace.c +2 −1 Original line number Diff line number Diff line Loading @@ -112,10 +112,11 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a } } void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed, void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, int* total_sleep_time_usec) { log_t log; log.tfd = fd; log.amfd = amfd; log.quiet = true; ptrace_context_t* context = load_ptrace_context(tid); Loading
debuggerd/backtrace.h +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ /* Dumps a backtrace using a format similar to what Dalvik uses so that the result * can be intermixed in a bug report. */ void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed, void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, int* total_sleep_time_usec); #endif // _DEBUGGERD_BACKTRACE_H
debuggerd/debuggerd.c +2 −1 Original line number Diff line number Diff line Loading @@ -314,7 +314,8 @@ static void handle_request(int fd) { &total_sleep_time_usec); } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) { XLOG("stopped -- dumping to fd\n"); dump_backtrace(fd, request.pid, request.tid, &detach_failed, dump_backtrace(fd, -1, request.pid, request.tid, &detach_failed, &total_sleep_time_usec); } else { XLOG("stopped -- continuing\n"); Loading
debuggerd/tombstone.c +59 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,9 @@ #include <corkscrew/demangle.h> #include <corkscrew/backtrace.h> #include <sys/socket.h> #include <linux/un.h> #include <selinux/android.h> #include "machine.h" Loading @@ -47,6 +50,9 @@ #define MAX_TOMBSTONES 10 #define TOMBSTONE_DIR "/data/tombstones" /* Must match the path defined in NativeCrashListener.java */ #define NCRASH_SOCKET_PATH "/data/system/ndebugsocket" #define typecheck(x,y) { \ typeof(x) __dummy1; \ typeof(y) __dummy2; \ Loading Loading @@ -627,6 +633,18 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, property_get("ro.debuggable", value, "0"); bool want_logs = (value[0] == '1'); if (log->amfd >= 0) { /* * Activity Manager protocol: binary 32-bit network-byte-order ints for the * pid and signal number, followed by the raw text of the dump, culminating * in a zero byte that marks end-of-data. */ uint32_t datum = htonl(pid); TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) ); datum = htonl(signal); TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) ); } _LOG(log, false, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); dump_build_info(log); Loading @@ -653,6 +671,16 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, if (want_logs) { dump_logs(log, pid, false); } /* send EOD to the Activity Manager, then wait for its ack to avoid racing ahead * and killing the target out from under it */ if (log->amfd >= 0) { uint8_t eodMarker = 0; TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) ); /* 3 sec timeout reading the ack; we're fine if that happens */ TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) ); } return detach_failed; } Loading Loading @@ -712,6 +740,35 @@ static char* find_and_open_tombstone(int* fd) return strdup(path); } static int activity_manager_connect() { int amfd = socket(PF_UNIX, SOCK_STREAM, 0); if (amfd >= 0) { struct sockaddr_un address; int err; memset(&address, 0, sizeof(address)); address.sun_family = AF_UNIX; strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path)); err = TEMP_FAILURE_RETRY( connect(amfd, (struct sockaddr*) &address, sizeof(address)) ); if (!err) { struct timeval tv; memset(&tv, 0, sizeof(tv)); tv.tv_sec = 1; // tight leash err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); if (!err) { tv.tv_sec = 3; // 3 seconds on handshake read err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); } } if (err) { close(amfd); amfd = -1; } } return amfd; } char* engrave_tombstone(pid_t pid, pid_t tid, int signal, bool dump_sibling_threads, bool quiet, bool* detach_failed, int* total_sleep_time_usec) { Loading @@ -732,10 +789,12 @@ char* engrave_tombstone(pid_t pid, pid_t tid, int signal, log_t log; log.tfd = fd; log.amfd = activity_manager_connect(); log.quiet = quiet; *detach_failed = dump_crash(&log, pid, tid, signal, dump_sibling_threads, total_sleep_time_usec); close(log.amfd); close(fd); return path; }
debuggerd/utility.c +39 −3 Original line number Diff line number Diff line Loading @@ -25,27 +25,63 @@ #include <cutils/logd.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <arpa/inet.h> #include <assert.h> #include "utility.h" const int sleep_time_usec = 50000; /* 0.05 seconds */ const int max_total_sleep_usec = 10000000; /* 10 seconds */ static int write_to_am(int fd, const char* buf, int len) { int to_write = len; while (to_write > 0) { int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) ); if (written < 0) { /* hard failure */ return -1; } to_write -= written; } return len; } void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...) { char buf[512]; bool want_tfd_write; bool want_log_write; bool want_amfd_write; int len; va_list ap; va_start(ap, fmt); if (log && log->tfd >= 0) { int len; // where is the information going to go? want_tfd_write = log && log->tfd >= 0; // write to the tombstone fd? want_log_write = !in_tombstone_only && (!log || !log->quiet); want_amfd_write = log && log->amfd >= 0; // only used when want_log_write is true // if we're going to need the literal string, generate it once here if (want_tfd_write || want_amfd_write) { vsnprintf(buf, sizeof(buf), fmt, ap); len = strlen(buf); } if (want_tfd_write) { write(log->tfd, buf, len); } if (!in_tombstone_only && (!log || !log->quiet)) { if (want_log_write) { // whatever goes to logcat also goes to the Activity Manager __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap); if (want_amfd_write && len > 0) { int written = write_to_am(log->amfd, buf, len); if (written <= 0) { // timeout or other failure on write; stop informing the activity manager LOG("AM write failure, giving up\n"); log->amfd = -1; } } } va_end(ap); } Loading