diff options
Diffstat (limited to 'debuggerd/utility.cpp')
-rw-r--r-- | debuggerd/utility.cpp | 95 |
1 files changed, 53 insertions, 42 deletions
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp index d4c252f..2baf9de 100644 --- a/debuggerd/utility.cpp +++ b/debuggerd/utility.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "DEBUG" + #include "utility.h" #include <errno.h> @@ -25,10 +27,9 @@ #include <backtrace/Backtrace.h> #include <log/log.h> -#include <log/logd.h> -const int sleep_time_usec = 50000; // 0.05 seconds -const int max_total_sleep_usec = 10000000; // 10 seconds +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; @@ -36,7 +37,7 @@ static int write_to_am(int fd, const char* buf, int len) { int written = TEMP_FAILURE_RETRY(write(fd, buf + len - to_write, to_write)); if (written < 0) { // hard failure - LOG("AM write failure (%d / %s)\n", errno, strerror(errno)); + ALOGE("AM write failure (%d / %s)\n", errno, strerror(errno)); return -1; } to_write -= written; @@ -44,10 +45,24 @@ static int write_to_am(int fd, const char* buf, int len) { return len; } -void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) { - bool want_tfd_write = log && log->tfd >= 0; - bool want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet); - bool want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0; +// Whitelist output desired in the logcat output. +bool is_allowed_in_logcat(enum logtype ltype) { + if ((ltype == ERROR) + || (ltype == HEADER) + || (ltype == REGISTERS) + || (ltype == BACKTRACE)) { + return true; + } + return false; +} + +void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) { + bool write_to_tombstone = (log->tfd != -1); + bool write_to_logcat = is_allowed_in_logcat(ltype) + && log->crashed_tid != -1 + && log->current_tid != -1 + && (log->crashed_tid == log->current_tid); + bool write_to_activitymanager = (log->amfd != -1); char buf[512]; va_list ap; @@ -60,13 +75,13 @@ void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) { return; } - if (want_tfd_write) { + if (write_to_tombstone) { TEMP_FAILURE_RETRY(write(log->tfd, buf, len)); } - if (want_log_write) { - __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_INFO, "DEBUG", buf); - if (want_amfd_write) { + if (write_to_logcat) { + __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_INFO, LOG_TAG, buf); + if (write_to_activitymanager) { int written = write_to_am(log->amfd, buf, len); if (written <= 0) { // timeout or other failure on write; stop informing the activity manager @@ -76,48 +91,44 @@ void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) { } } -int wait_for_signal(pid_t tid, int* total_sleep_time_usec) { +int wait_for_sigstop(pid_t tid, int* total_sleep_time_usec, bool* detach_failed) { + bool allow_dead_tid = false; for (;;) { int status; - pid_t n = waitpid(tid, &status, __WALL | WNOHANG); - if (n < 0) { - if (errno == EAGAIN) - continue; - LOG("waitpid failed: %s\n", strerror(errno)); - return -1; - } else if (n > 0) { - XLOG("waitpid: n=%d status=%08x\n", n, status); + pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG)); + if (n == -1) { + ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno)); + break; + } else if (n == tid) { if (WIFSTOPPED(status)) { return WSTOPSIG(status); } else { - LOG("unexpected waitpid response: n=%d, status=%08x\n", n, status); - return -1; + ALOGE("unexpected waitpid response: n=%d, status=%08x\n", n, status); + // This is the only circumstance under which we can allow a detach + // to fail with ESRCH, which indicates the tid has exited. + allow_dead_tid = true; + break; } } - if (*total_sleep_time_usec > max_total_sleep_usec) { - LOG("timed out waiting for tid=%d to die\n", tid); - return -1; + if (*total_sleep_time_usec > MAX_TOTAL_SLEEP_USEC) { + ALOGE("timed out waiting for stop signal: tid=%d", tid); + break; } - // not ready yet - XLOG("not ready yet\n"); - usleep(sleep_time_usec); - *total_sleep_time_usec += sleep_time_usec; + usleep(SLEEP_TIME_USEC); + *total_sleep_time_usec += SLEEP_TIME_USEC; } -} -void wait_for_stop(pid_t tid, int* total_sleep_time_usec) { - siginfo_t si; - while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) < 0 && errno == ESRCH) { - if (*total_sleep_time_usec > max_total_sleep_usec) { - LOG("timed out waiting for tid=%d to stop\n", tid); - break; + if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { + if (allow_dead_tid && errno == ESRCH) { + ALOGE("tid exited before attach completed: tid %d", tid); + } else { + *detach_failed = true; + ALOGE("detach failed: tid %d, %s", tid, strerror(errno)); } - - usleep(sleep_time_usec); - *total_sleep_time_usec += sleep_time_usec; } + return -1; } #if defined (__mips__) @@ -126,7 +137,7 @@ void wait_for_stop(pid_t tid, int* total_sleep_time_usec) { #define DUMP_MEMORY_AS_ASCII 0 #endif -void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) { +void dump_memory(log_t* log, pid_t tid, uintptr_t addr) { char code_buffer[64]; char ascii_buffer[32]; uintptr_t p, end; @@ -190,6 +201,6 @@ void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scope_flags) { p += sizeof(long); } *asc_out = '\0'; - _LOG(log, scope_flags, " %s %s\n", code_buffer, ascii_buffer); + _LOG(log, logtype::MEMORY, " %s %s\n", code_buffer, ascii_buffer); } } |