diff options
Diffstat (limited to 'debuggerd')
-rw-r--r-- | debuggerd/arm/machine.cpp | 52 | ||||
-rw-r--r-- | debuggerd/arm64/machine.cpp | 52 | ||||
-rw-r--r-- | debuggerd/backtrace.cpp | 20 | ||||
-rw-r--r-- | debuggerd/backtrace.h | 3 | ||||
-rw-r--r-- | debuggerd/debuggerd.cpp | 35 | ||||
-rw-r--r-- | debuggerd/machine.h | 4 | ||||
-rw-r--r-- | debuggerd/mips/machine.cpp | 71 | ||||
-rwxr-xr-x | debuggerd/tombstone.cpp | 163 | ||||
-rw-r--r-- | debuggerd/utility.cpp | 45 | ||||
-rw-r--r-- | debuggerd/utility.h | 47 | ||||
-rw-r--r-- | debuggerd/x86/machine.cpp | 14 | ||||
-rwxr-xr-x | debuggerd/x86_64/machine.cpp | 18 |
12 files changed, 263 insertions, 261 deletions
diff --git a/debuggerd/arm/machine.cpp b/debuggerd/arm/machine.cpp index fd2f69b..839d47a 100644 --- a/debuggerd/arm/machine.cpp +++ b/debuggerd/arm/machine.cpp @@ -40,57 +40,55 @@ // If configured to do so, dump memory around *all* registers // for the crashing thread. -void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) { +void dump_memory_and_code(log_t* log, pid_t tid) { struct pt_regs regs; if (ptrace(PTRACE_GETREGS, tid, 0, ®s)) { return; } - if (IS_AT_FAULT(scope_flags) && DUMP_MEMORY_FOR_ALL_REGISTERS) { - static const char REG_NAMES[] = "r0r1r2r3r4r5r6r7r8r9slfpipsp"; + static const char REG_NAMES[] = "r0r1r2r3r4r5r6r7r8r9slfpipsp"; - for (int reg = 0; reg < 14; reg++) { - // this may not be a valid way to access, but it'll do for now - uintptr_t addr = regs.uregs[reg]; + for (int reg = 0; reg < 14; reg++) { + // this may not be a valid way to access, but it'll do for now + uintptr_t addr = regs.uregs[reg]; - // Don't bother if it looks like a small int or ~= null, or if - // it's in the kernel area. - if (addr < 4096 || addr >= 0xc0000000) { - continue; - } - - _LOG(log, scope_flags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", ®_NAMES[reg * 2]); - dump_memory(log, tid, addr, scope_flags | SCOPE_SENSITIVE); + // Don't bother if it looks like a small int or ~= null, or if + // it's in the kernel area. + if (addr < 4096 || addr >= 0xc0000000) { + continue; } + + _LOG(log, logtype::MEMORY, "\nmemory near %.2s:\n", ®_NAMES[reg * 2]); + dump_memory(log, tid, addr); } // explicitly allow upload of code dump logging - _LOG(log, scope_flags, "\ncode around pc:\n"); - dump_memory(log, tid, static_cast<uintptr_t>(regs.ARM_pc), scope_flags); + _LOG(log, logtype::MEMORY, "\ncode around pc:\n"); + dump_memory(log, tid, static_cast<uintptr_t>(regs.ARM_pc)); if (regs.ARM_pc != regs.ARM_lr) { - _LOG(log, scope_flags, "\ncode around lr:\n"); - dump_memory(log, tid, static_cast<uintptr_t>(regs.ARM_lr), scope_flags); + _LOG(log, logtype::MEMORY, "\ncode around lr:\n"); + dump_memory(log, tid, static_cast<uintptr_t>(regs.ARM_lr)); } } -void dump_registers(log_t* log, pid_t tid, int scope_flags) { +void dump_registers(log_t* log, pid_t tid) { struct pt_regs r; if (ptrace(PTRACE_GETREGS, tid, 0, &r)) { - _LOG(log, scope_flags, "cannot get registers: %s\n", strerror(errno)); + _LOG(log, logtype::REGISTERS, "cannot get registers: %s\n", strerror(errno)); return; } - _LOG(log, scope_flags, " r0 %08x r1 %08x r2 %08x r3 %08x\n", + _LOG(log, logtype::REGISTERS, " r0 %08x r1 %08x r2 %08x r3 %08x\n", static_cast<uint32_t>(r.ARM_r0), static_cast<uint32_t>(r.ARM_r1), static_cast<uint32_t>(r.ARM_r2), static_cast<uint32_t>(r.ARM_r3)); - _LOG(log, scope_flags, " r4 %08x r5 %08x r6 %08x r7 %08x\n", + _LOG(log, logtype::REGISTERS, " r4 %08x r5 %08x r6 %08x r7 %08x\n", static_cast<uint32_t>(r.ARM_r4), static_cast<uint32_t>(r.ARM_r5), static_cast<uint32_t>(r.ARM_r6), static_cast<uint32_t>(r.ARM_r7)); - _LOG(log, scope_flags, " r8 %08x r9 %08x sl %08x fp %08x\n", + _LOG(log, logtype::REGISTERS, " r8 %08x r9 %08x sl %08x fp %08x\n", static_cast<uint32_t>(r.ARM_r8), static_cast<uint32_t>(r.ARM_r9), static_cast<uint32_t>(r.ARM_r10), static_cast<uint32_t>(r.ARM_fp)); - _LOG(log, scope_flags, " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", + _LOG(log, logtype::REGISTERS, " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", static_cast<uint32_t>(r.ARM_ip), static_cast<uint32_t>(r.ARM_sp), static_cast<uint32_t>(r.ARM_lr), static_cast<uint32_t>(r.ARM_pc), static_cast<uint32_t>(r.ARM_cpsr)); @@ -100,14 +98,14 @@ void dump_registers(log_t* log, pid_t tid, int scope_flags) { int i; if (ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) { - _LOG(log, scope_flags, "cannot get registers: %s\n", strerror(errno)); + _LOG(log, logtype::REGISTERS, "cannot get registers: %s\n", strerror(errno)); return; } for (i = 0; i < NUM_VFP_REGS; i += 2) { - _LOG(log, scope_flags, " d%-2d %016llx d%-2d %016llx\n", + _LOG(log, logtype::REGISTERS, " d%-2d %016llx d%-2d %016llx\n", i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]); } - _LOG(log, scope_flags, " scr %08lx\n", vfp_regs.fpscr); + _LOG(log, logtype::REGISTERS, " scr %08lx\n", vfp_regs.fpscr); #endif } diff --git a/debuggerd/arm64/machine.cpp b/debuggerd/arm64/machine.cpp index 2413d5e..f3409d5 100644 --- a/debuggerd/arm64/machine.cpp +++ b/debuggerd/arm64/machine.cpp @@ -37,68 +37,66 @@ * If configured to do so, dump memory around *all* registers * for the crashing thread. */ -void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) { +void dump_memory_and_code(log_t* log, pid_t tid) { struct user_pt_regs regs; struct iovec io; io.iov_base = ®s; io.iov_len = sizeof(regs); if (ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, &io) == -1) { - _LOG(log, scope_flags, "%s: ptrace failed to get registers: %s\n", + LOG_ERROR("%s: ptrace failed to get registers: %s\n", __func__, strerror(errno)); return; } - if (IS_AT_FAULT(scope_flags) && DUMP_MEMORY_FOR_ALL_REGISTERS) { - for (int reg = 0; reg < 31; reg++) { - uintptr_t addr = regs.regs[reg]; + for (int reg = 0; reg < 31; reg++) { + uintptr_t addr = regs.regs[reg]; - /* - * Don't bother if it looks like a small int or ~= null, or if - * it's in the kernel area. - */ - if (addr < 4096 || addr >= (1UL<<63)) { - continue; - } - - _LOG(log, scope_flags | SCOPE_SENSITIVE, "\nmemory near x%d:\n", reg); - dump_memory(log, tid, addr, scope_flags | SCOPE_SENSITIVE); + /* + * Don't bother if it looks like a small int or ~= null, or if + * it's in the kernel area. + */ + if (addr < 4096 || addr >= (1UL<<63)) { + continue; } + + _LOG(log, logtype::MEMORY, "\nmemory near x%d:\n", reg); + dump_memory(log, tid, addr); } - _LOG(log, scope_flags, "\ncode around pc:\n"); - dump_memory(log, tid, (uintptr_t)regs.pc, scope_flags); + _LOG(log, logtype::MEMORY, "\ncode around pc:\n"); + dump_memory(log, tid, (uintptr_t)regs.pc); if (regs.pc != regs.sp) { - _LOG(log, scope_flags, "\ncode around sp:\n"); - dump_memory(log, tid, (uintptr_t)regs.sp, scope_flags); + _LOG(log, logtype::MEMORY, "\ncode around sp:\n"); + dump_memory(log, tid, (uintptr_t)regs.sp); } } -void dump_registers(log_t* log, pid_t tid, int scope_flags) -{ +void dump_registers(log_t* log, pid_t tid) { struct user_pt_regs r; struct iovec io; io.iov_base = &r; io.iov_len = sizeof(r); if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRSTATUS, (void*) &io) == -1) { - _LOG(log, scope_flags, "ptrace error: %s\n", strerror(errno)); + LOG_ERROR("ptrace error: %s\n", strerror(errno)); return; } for (int i = 0; i < 28; i += 4) { - _LOG(log, scope_flags, " x%-2d %016lx x%-2d %016lx x%-2d %016lx x%-2d %016lx\n", + _LOG(log, logtype::REGISTERS, + " x%-2d %016lx x%-2d %016lx x%-2d %016lx x%-2d %016lx\n", i, (uint64_t)r.regs[i], i+1, (uint64_t)r.regs[i+1], i+2, (uint64_t)r.regs[i+2], i+3, (uint64_t)r.regs[i+3]); } - _LOG(log, scope_flags, " x28 %016lx x29 %016lx x30 %016lx\n", + _LOG(log, logtype::REGISTERS, " x28 %016lx x29 %016lx x30 %016lx\n", (uint64_t)r.regs[28], (uint64_t)r.regs[29], (uint64_t)r.regs[30]); - _LOG(log, scope_flags, " sp %016lx pc %016lx\n", + _LOG(log, logtype::REGISTERS, " sp %016lx pc %016lx\n", (uint64_t)r.sp, (uint64_t)r.pc); @@ -107,12 +105,12 @@ void dump_registers(log_t* log, pid_t tid, int scope_flags) io.iov_len = sizeof(f); if (ptrace(PTRACE_GETREGSET, tid, (void*) NT_PRFPREG, (void*) &io) == -1) { - _LOG(log, scope_flags, "ptrace error: %s\n", strerror(errno)); + LOG_ERROR("ptrace error: %s\n", strerror(errno)); return; } for (int i = 0; i < 32; i += 4) { - _LOG(log, scope_flags, " v%-2d %016lx v%-2d %016lx v%-2d %016lx v%-2d %016lx\n", + _LOG(log, logtype::REGISTERS, " v%-2d %016lx v%-2d %016lx v%-2d %016lx v%-2d %016lx\n", i, (uint64_t)f.vregs[i], i+1, (uint64_t)f.vregs[i+1], i+2, (uint64_t)f.vregs[i+2], diff --git a/debuggerd/backtrace.cpp b/debuggerd/backtrace.cpp index d388348..d08242e 100644 --- a/debuggerd/backtrace.cpp +++ b/debuggerd/backtrace.cpp @@ -30,6 +30,7 @@ #include <UniquePtr.h> #include "backtrace.h" + #include "utility.h" static void dump_process_header(log_t* log, pid_t pid) { @@ -49,15 +50,15 @@ static void dump_process_header(log_t* log, pid_t pid) { localtime_r(&t, &tm); char timestr[64]; strftime(timestr, sizeof(timestr), "%F %T", &tm); - _LOG(log, SCOPE_AT_FAULT, "\n\n----- pid %d at %s -----\n", pid, timestr); + _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, timestr); if (procname) { - _LOG(log, SCOPE_AT_FAULT, "Cmd line: %s\n", procname); + _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", procname); } } static void dump_process_footer(log_t* log, pid_t pid) { - _LOG(log, SCOPE_AT_FAULT, "\n----- end %d -----\n", pid); + _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); } static void dump_thread( @@ -79,10 +80,10 @@ static void dump_thread( } } - _LOG(log, SCOPE_AT_FAULT, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid); + _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid); if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) { - _LOG(log, SCOPE_AT_FAULT, "Could not attach to thread: %s\n", strerror(errno)); + _LOG(log, logtype::BACKTRACE, "Could not attach to thread: %s\n", strerror(errno)); return; } @@ -90,11 +91,11 @@ static void dump_thread( UniquePtr<Backtrace> backtrace(Backtrace::Create(tid, BACKTRACE_CURRENT_THREAD)); if (backtrace->Unwind(0)) { - dump_backtrace_to_log(backtrace.get(), log, SCOPE_AT_FAULT, " "); + dump_backtrace_to_log(backtrace.get(), log, " "); } if (!attached && ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { - LOG("ptrace detach from %d failed: %s\n", tid, strerror(errno)); + LOG_ERROR("ptrace detach from %d failed: %s\n", tid, strerror(errno)); *detach_failed = true; } } @@ -133,9 +134,8 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, dump_process_footer(&log, pid); } -void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, - int scope_flags, const char* prefix) { +void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix) { for (size_t i = 0; i < backtrace->NumFrames(); i++) { - _LOG(log, scope_flags, "%s%s\n", prefix, backtrace->FormatFrameData(i).c_str()); + _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, backtrace->FormatFrameData(i).c_str()); } } diff --git a/debuggerd/backtrace.h b/debuggerd/backtrace.h index 2ec8afb..da14cd4 100644 --- a/debuggerd/backtrace.h +++ b/debuggerd/backtrace.h @@ -29,7 +29,6 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, int* total_sleep_time_usec); /* Dumps the backtrace in the backtrace data structure to the log. */ -void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, - int scope_flags, const char* prefix); +void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix); #endif // _DEBUGGERD_BACKTRACE_H diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 3726c38..dde8f90 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -30,7 +30,6 @@ #include <sys/stat.h> #include <sys/poll.h> -#include <log/logd.h> #include <log/logger.h> #include <cutils/sockets.h> @@ -62,7 +61,7 @@ static void wait_for_user_action(pid_t pid) { char exe[PATH_MAX]; int count; if ((count = readlink(path, exe, sizeof(exe) - 1)) == -1) { - LOG("readlink('%s') failed: %s", path, strerror(errno)); + LOG_ERROR("readlink('%s') failed: %s", path, strerror(errno)); strlcpy(exe, "unknown", sizeof(exe)); } else { exe[count] = '\0'; @@ -79,7 +78,7 @@ static void wait_for_user_action(pid_t pid) { } // Explain how to attach the debugger. - LOG( "********************************************************\n" + LOG_ERROR( "********************************************************\n" "* Process %d has been suspended while crashing.\n" "* To attach gdbserver for a gdb connection on port 5039\n" "* and start gdbclient:\n" @@ -104,7 +103,7 @@ static void wait_for_user_action(pid_t pid) { uninit_getevent(); } - LOG("debuggerd resuming process %d", pid); + LOG_ERROR("debuggerd resuming process %d", pid); } static int get_process_info(pid_t tid, pid_t* out_pid, uid_t* out_uid, uid_t* out_gid) { @@ -140,7 +139,7 @@ static int read_request(int fd, debugger_request_t* out_request) { socklen_t len = sizeof(cr); int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); if (status != 0) { - LOG("cannot get credentials\n"); + LOG_ERROR("cannot get credentials\n"); return -1; } @@ -153,7 +152,7 @@ static int read_request(int fd, debugger_request_t* out_request) { pollfds[0].revents = 0; status = TEMP_FAILURE_RETRY(poll(pollfds, 1, 3000)); if (status != 1) { - LOG("timed out reading tid (from pid=%d uid=%d)\n", cr.pid, cr.uid); + LOG_ERROR("timed out reading tid (from pid=%d uid=%d)\n", cr.pid, cr.uid); return -1; } @@ -161,14 +160,14 @@ static int read_request(int fd, debugger_request_t* out_request) { memset(&msg, 0, sizeof(msg)); status = TEMP_FAILURE_RETRY(read(fd, &msg, sizeof(msg))); if (status < 0) { - LOG("read failure? %s (pid=%d uid=%d)\n", strerror(errno), cr.pid, cr.uid); + LOG_ERROR("read failure? %s (pid=%d uid=%d)\n", strerror(errno), cr.pid, cr.uid); return -1; } if (status == sizeof(debugger_msg_t)) { XLOG("crash request of size %d abort_msg_address=0x%" PRIPTR "\n", status, msg.abort_msg_address); } else { - LOG("invalid crash request of size %d (from pid=%d uid=%d)\n", status, cr.pid, cr.uid); + LOG_ERROR("invalid crash request of size %d (from pid=%d uid=%d)\n", status, cr.pid, cr.uid); return -1; } @@ -186,7 +185,7 @@ static int read_request(int fd, debugger_request_t* out_request) { struct stat s; snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid); if (stat(buf, &s)) { - LOG("tid %d does not exist in pid %d. ignoring debug request\n", + LOG_ERROR("tid %d does not exist in pid %d. ignoring debug request\n", out_request->tid, out_request->pid); return -1; } @@ -197,7 +196,7 @@ static int read_request(int fd, debugger_request_t* out_request) { status = get_process_info(out_request->tid, &out_request->pid, &out_request->uid, &out_request->gid); if (status < 0) { - LOG("tid %d does not exist. ignoring explicit dump request\n", out_request->tid); + LOG_ERROR("tid %d does not exist. ignoring explicit dump request\n", out_request->tid); return -1; } } else { @@ -238,12 +237,12 @@ static void handle_request(int fd) { // See details in bionic/libc/linker/debugger.c, in function // debugger_signal_handler(). if (ptrace(PTRACE_ATTACH, request.tid, 0, 0)) { - LOG("ptrace attach failed: %s\n", strerror(errno)); + LOG_ERROR("ptrace attach failed: %s\n", strerror(errno)); } else { bool detach_failed = false; bool attach_gdb = should_attach_gdb(&request); if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) { - LOG("failed responding to client: %s\n", strerror(errno)); + LOG_ERROR("failed responding to client: %s\n", strerror(errno)); } else { char* tombstone_path = NULL; @@ -275,7 +274,7 @@ static void handle_request(int fd) { XLOG("stopped -- continuing\n"); status = ptrace(PTRACE_CONT, request.tid, 0, 0); if (status) { - LOG("ptrace continue failed: %s\n", strerror(errno)); + LOG_ERROR("ptrace continue failed: %s\n", strerror(errno)); } continue; // loop again } @@ -307,7 +306,7 @@ static void handle_request(int fd) { default: XLOG("stopped -- unexpected signal\n"); - LOG("process stopped due to unexpected signal %d\n", signal); + LOG_ERROR("process stopped due to unexpected signal %d\n", signal); break; } break; @@ -330,7 +329,7 @@ static void handle_request(int fd) { // detach so we can attach gdbserver if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { - LOG("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); + LOG_ERROR("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); detach_failed = true; } @@ -342,7 +341,7 @@ static void handle_request(int fd) { } else { // just detach if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) { - LOG("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); + LOG_ERROR("ptrace detach from %d failed: %s\n", request.tid, strerror(errno)); detach_failed = true; } } @@ -354,7 +353,7 @@ static void handle_request(int fd) { // actual parent won't receive a death notification via wait(2). At this point // there's not much we can do about that. if (detach_failed) { - LOG("debuggerd committing suicide to free the zombie!\n"); + LOG_ERROR("debuggerd committing suicide to free the zombie!\n"); kill(getpid(), SIGKILL); } } @@ -400,7 +399,7 @@ static int do_server() { return 1; fcntl(s, F_SETFD, FD_CLOEXEC); - LOG("debuggerd: " __DATE__ " " __TIME__ "\n"); + LOG_ERROR("debuggerd: " __DATE__ " " __TIME__ "\n"); for (;;) { sockaddr addr; diff --git a/debuggerd/machine.h b/debuggerd/machine.h index 2f1e201..fca9fbe 100644 --- a/debuggerd/machine.h +++ b/debuggerd/machine.h @@ -21,7 +21,7 @@ #include "utility.h" -void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags); -void dump_registers(log_t* log, pid_t tid, int scope_flags); +void dump_memory_and_code(log_t* log, pid_t tid); +void dump_registers(log_t* log, pid_t tid); #endif // _DEBUGGERD_MACHINE_H diff --git a/debuggerd/mips/machine.cpp b/debuggerd/mips/machine.cpp index 5c82d4d..605275b 100644 --- a/debuggerd/mips/machine.cpp +++ b/debuggerd/mips/machine.cpp @@ -27,9 +27,6 @@ #include "../utility.h" #include "../machine.h" -// enable to dump memory pointed to by every register -#define DUMP_MEMORY_FOR_ALL_REGISTERS 1 - #define R(x) (static_cast<unsigned int>(x)) // The MIPS uapi ptrace.h has the wrong definition for pt_regs. PTRACE_GETREGS @@ -46,72 +43,70 @@ struct pt_regs_mips_t { // If configured to do so, dump memory around *all* registers // for the crashing thread. -void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) { +void dump_memory_and_code(log_t* log, pid_t tid) { pt_regs_mips_t r; if (ptrace(PTRACE_GETREGS, tid, 0, &r)) { return; } - if (IS_AT_FAULT(scope_flags) && DUMP_MEMORY_FOR_ALL_REGISTERS) { - static const char REG_NAMES[] = "$0atv0v1a0a1a2a3t0t1t2t3t4t5t6t7s0s1s2s3s4s5s6s7t8t9k0k1gpsps8ra"; - - for (int reg = 0; reg < 32; reg++) { - // skip uninteresting registers - if (reg == 0 // $0 - || reg == 26 // $k0 - || reg == 27 // $k1 - || reg == 31 // $ra (done below) - ) - continue; + static const char REG_NAMES[] = "$0atv0v1a0a1a2a3t0t1t2t3t4t5t6t7s0s1s2s3s4s5s6s7t8t9k0k1gpsps8ra"; - uintptr_t addr = R(r.regs[reg]); + for (int reg = 0; reg < 32; reg++) { + // skip uninteresting registers + if (reg == 0 // $0 + || reg == 26 // $k0 + || reg == 27 // $k1 + || reg == 31 // $ra (done below) + ) + continue; - // Don't bother if it looks like a small int or ~= null, or if - // it's in the kernel area. - if (addr < 4096 || addr >= 0x80000000) { - continue; - } + uintptr_t addr = R(r.regs[reg]); - _LOG(log, scope_flags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", ®_NAMES[reg * 2]); - dump_memory(log, tid, addr, scope_flags | SCOPE_SENSITIVE); + // Don't bother if it looks like a small int or ~= null, or if + // it's in the kernel area. + if (addr < 4096 || addr >= 0x80000000) { + continue; } + + _LOG(log, logtype::MEMORY, "\nmemory near %.2s:\n", ®_NAMES[reg * 2]); + dump_memory(log, tid, addr); } unsigned int pc = R(r.cp0_epc); unsigned int ra = R(r.regs[31]); - _LOG(log, scope_flags, "\ncode around pc:\n"); - dump_memory(log, tid, (uintptr_t)pc, scope_flags); + _LOG(log, logtype::MEMORY, "\ncode around pc:\n"); + dump_memory(log, tid, (uintptr_t)pc); if (pc != ra) { - _LOG(log, scope_flags, "\ncode around ra:\n"); - dump_memory(log, tid, (uintptr_t)ra, scope_flags); + _LOG(log, logtype::MEMORY, "\ncode around ra:\n"); + dump_memory(log, tid, (uintptr_t)ra); } } -void dump_registers(log_t* log, pid_t tid, int scope_flags) { +void dump_registers(log_t* log, pid_t tid) { pt_regs_mips_t r; if(ptrace(PTRACE_GETREGS, tid, 0, &r)) { - _LOG(log, scope_flags, "cannot get registers: %s\n", strerror(errno)); + LOG_ERROR("cannot get registers: %s\n", strerror(errno)); return; } - _LOG(log, scope_flags, " zr %08x at %08x v0 %08x v1 %08x\n", + _LOG(log, logtype::REGISTERS, " zr %08x at %08x v0 %08x v1 %08x\n", R(r.regs[0]), R(r.regs[1]), R(r.regs[2]), R(r.regs[3])); - _LOG(log, scope_flags, " a0 %08x a1 %08x a2 %08x a3 %08x\n", + _LOG(log, logtype::REGISTERS, " a0 %08x a1 %08x a2 %08x a3 %08x\n", R(r.regs[4]), R(r.regs[5]), R(r.regs[6]), R(r.regs[7])); - _LOG(log, scope_flags, " t0 %08x t1 %08x t2 %08x t3 %08x\n", + _LOG(log, logtype::REGISTERS, " t0 %08x t1 %08x t2 %08x t3 %08x\n", R(r.regs[8]), R(r.regs[9]), R(r.regs[10]), R(r.regs[11])); - _LOG(log, scope_flags, " t4 %08x t5 %08x t6 %08x t7 %08x\n", + _LOG(log, logtype::REGISTERS, " t4 %08x t5 %08x t6 %08x t7 %08x\n", R(r.regs[12]), R(r.regs[13]), R(r.regs[14]), R(r.regs[15])); - _LOG(log, scope_flags, " s0 %08x s1 %08x s2 %08x s3 %08x\n", + _LOG(log, logtype::REGISTERS, " s0 %08x s1 %08x s2 %08x s3 %08x\n", R(r.regs[16]), R(r.regs[17]), R(r.regs[18]), R(r.regs[19])); - _LOG(log, scope_flags, " s4 %08x s5 %08x s6 %08x s7 %08x\n", + _LOG(log, logtype::REGISTERS, " s4 %08x s5 %08x s6 %08x s7 %08x\n", R(r.regs[20]), R(r.regs[21]), R(r.regs[22]), R(r.regs[23])); - _LOG(log, scope_flags, " t8 %08x t9 %08x k0 %08x k1 %08x\n", + _LOG(log, logtype::REGISTERS, " t8 %08x t9 %08x k0 %08x k1 %08x\n", R(r.regs[24]), R(r.regs[25]), R(r.regs[26]), R(r.regs[27])); - _LOG(log, scope_flags, " gp %08x sp %08x s8 %08x ra %08x\n", + _LOG(log, logtype::REGISTERS, " gp %08x sp %08x s8 %08x ra %08x\n", R(r.regs[28]), R(r.regs[29]), R(r.regs[30]), R(r.regs[31])); - _LOG(log, scope_flags, " hi %08x lo %08x bva %08x epc %08x\n", + _LOG(log, logtype::REGISTERS, " hi %08x lo %08x bva %08x epc %08x\n", R(r.hi), R(r.lo), R(r.cp0_badvaddr), R(r.cp0_epc)); } diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index fb5f02a..a06effc 100755 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "DEBUG" + #include <dirent.h> #include <errno.h> #include <fcntl.h> @@ -179,16 +181,16 @@ static void dump_header_info(log_t* log) { property_get("ro.build.fingerprint", fingerprint, "unknown"); property_get("ro.revision", revision, "unknown"); - _LOG(log, SCOPE_AT_FAULT, "Build fingerprint: '%s'\n", fingerprint); - _LOG(log, SCOPE_AT_FAULT, "Revision: '%s'\n", revision); - _LOG(log, SCOPE_AT_FAULT, "ABI: '%s'\n", ABI_STRING); + _LOG(log, logtype::HEADER, "Build fingerprint: '%s'\n", fingerprint); + _LOG(log, logtype::HEADER, "Revision: '%s'\n", revision); + _LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING); } static void dump_signal_info(log_t* log, pid_t tid, int signal, int si_code) { siginfo_t si; memset(&si, 0, sizeof(si)); if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si) == -1) { - _LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno)); + _LOG(log, logtype::HEADER, "cannot get siginfo: %s\n", strerror(errno)); return; } @@ -202,11 +204,11 @@ static void dump_signal_info(log_t* log, pid_t tid, int signal, int si_code) { snprintf(addr_desc, sizeof(addr_desc), "--------"); } - _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %s\n", + _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n", signal, get_signame(signal), si.si_code, get_sigcode(signal, si.si_code), addr_desc); } -static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, int scope_flags) { +static void dump_thread_info(log_t* log, pid_t pid, pid_t tid) { char path[64]; char threadnamebuf[1024]; char* threadname = NULL; @@ -224,25 +226,21 @@ static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, int scope_flags) } } - if (IS_AT_FAULT(scope_flags)) { - char procnamebuf[1024]; - char* procname = NULL; - - snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); - if ((fp = fopen(path, "r"))) { - procname = fgets(procnamebuf, sizeof(procnamebuf), fp); - fclose(fp); - } + char procnamebuf[1024]; + char* procname = NULL; - _LOG(log, SCOPE_AT_FAULT, "pid: %d, tid: %d, name: %s >>> %s <<<\n", pid, tid, - threadname ? threadname : "UNKNOWN", procname ? procname : "UNKNOWN"); - } else { - _LOG(log, 0, "pid: %d, tid: %d, name: %s\n", pid, tid, threadname ? threadname : "UNKNOWN"); + snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); + if ((fp = fopen(path, "r"))) { + procname = fgets(procnamebuf, sizeof(procnamebuf), fp); + fclose(fp); } + + _LOG(log, logtype::THREAD, "pid: %d, tid: %d, name: %s >>> %s <<<\n", pid, tid, + threadname ? threadname : "UNKNOWN", procname ? procname : "UNKNOWN"); } static void dump_stack_segment( - Backtrace* backtrace, log_t* log, int scope_flags, uintptr_t* sp, size_t words, int label) { + Backtrace* backtrace, log_t* log, uintptr_t* sp, size_t words, int label) { for (size_t i = 0; i < words; i++) { word_t stack_content; if (!backtrace->ReadWord(*sp, &stack_content)) { @@ -261,27 +259,27 @@ static void dump_stack_segment( if (!func_name.empty()) { if (!i && label >= 0) { if (offset) { - _LOG(log, scope_flags, " #%02d %" PRIPTR " %" PRIPTR " %s (%s+%" PRIuPTR ")\n", + _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR " %s (%s+%" PRIuPTR ")\n", label, *sp, stack_content, map_name, func_name.c_str(), offset); } else { - _LOG(log, scope_flags, " #%02d %" PRIPTR " %" PRIPTR " %s (%s)\n", + _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR " %s (%s)\n", label, *sp, stack_content, map_name, func_name.c_str()); } } else { if (offset) { - _LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s (%s+%" PRIuPTR ")\n", + _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR " %s (%s+%" PRIuPTR ")\n", *sp, stack_content, map_name, func_name.c_str(), offset); } else { - _LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s (%s)\n", + _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR " %s (%s)\n", *sp, stack_content, map_name, func_name.c_str()); } } } else { if (!i && label >= 0) { - _LOG(log, scope_flags, " #%02d %" PRIPTR " %" PRIPTR " %s\n", + _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR " %s\n", label, *sp, stack_content, map_name); } else { - _LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s\n", + _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR " %s\n", *sp, stack_content, map_name); } } @@ -290,7 +288,7 @@ static void dump_stack_segment( } } -static void dump_stack(Backtrace* backtrace, log_t* log, int scope_flags) { +static void dump_stack(Backtrace* backtrace, log_t* log) { size_t first = 0, last; for (size_t i = 0; i < backtrace->NumFrames(); i++) { const backtrace_frame_data_t* frame = backtrace->GetFrame(i); @@ -306,27 +304,22 @@ static void dump_stack(Backtrace* backtrace, log_t* log, int scope_flags) { } first--; - scope_flags |= SCOPE_SENSITIVE; - // Dump a few words before the first frame. word_t sp = backtrace->GetFrame(first)->sp - STACK_WORDS * sizeof(word_t); - dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, -1); + dump_stack_segment(backtrace, log, &sp, STACK_WORDS, -1); // Dump a few words from all successive frames. // Only log the first 3 frames, put the rest in the tombstone. for (size_t i = first; i <= last; i++) { const backtrace_frame_data_t* frame = backtrace->GetFrame(i); if (sp != frame->sp) { - _LOG(log, scope_flags, " ........ ........\n"); + _LOG(log, logtype::STACK, " ........ ........\n"); sp = frame->sp; } - if (i - first == 3) { - scope_flags &= (~SCOPE_AT_FAULT); - } if (i == last) { - dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, i); + dump_stack_segment(backtrace, log, &sp, STACK_WORDS, i); if (sp < frame->sp + frame->stack_size) { - _LOG(log, scope_flags, " ........ ........\n"); + _LOG(log, logtype::STACK, " ........ ........\n"); } } else { size_t words = frame->stack_size / sizeof(word_t); @@ -335,37 +328,36 @@ static void dump_stack(Backtrace* backtrace, log_t* log, int scope_flags) { } else if (words > STACK_WORDS) { words = STACK_WORDS; } - dump_stack_segment(backtrace, log, scope_flags, &sp, words, i); + dump_stack_segment(backtrace, log, &sp, words, i); } } } -static void dump_backtrace_and_stack(Backtrace* backtrace, log_t* log, int scope_flags) { +static void dump_backtrace_and_stack(Backtrace* backtrace, log_t* log) { if (backtrace->NumFrames()) { - _LOG(log, scope_flags, "\nbacktrace:\n"); - dump_backtrace_to_log(backtrace, log, scope_flags, " "); + _LOG(log, logtype::BACKTRACE, "\nbacktrace:\n"); + dump_backtrace_to_log(backtrace, log, " "); - _LOG(log, scope_flags, "\nstack:\n"); - dump_stack(backtrace, log, scope_flags); + _LOG(log, logtype::STACK, "\nstack:\n"); + dump_stack(backtrace, log); } } -static void dump_map(log_t* log, const backtrace_map_t* map, const char* what, int scope_flags) { +static void dump_map(log_t* log, const backtrace_map_t* map, const char* what) { if (map != NULL) { - _LOG(log, scope_flags, " %" PRIPTR "-%" PRIPTR " %c%c%c %s\n", map->start, map->end, + _LOG(log, logtype::MAPS, " %" PRIPTR "-%" PRIPTR " %c%c%c %s\n", map->start, map->end, (map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-', (map->flags & PROT_EXEC) ? 'x' : '-', map->name.c_str()); } else { - _LOG(log, scope_flags, " (no %s)\n", what); + _LOG(log, logtype::MAPS, " (no %s)\n", what); } } -static void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid, int scope_flags) { - scope_flags |= SCOPE_SENSITIVE; +static void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid) { siginfo_t si; memset(&si, 0, sizeof(si)); if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) { - _LOG(log, scope_flags, "cannot get siginfo for %d: %s\n", tid, strerror(errno)); + _LOG(log, logtype::MAPS, "cannot get siginfo for %d: %s\n", tid, strerror(errno)); return; } if (!signal_has_si_addr(si.si_signo)) { @@ -378,7 +370,7 @@ static void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid, int scope return; } - _LOG(log, scope_flags, "\nmemory map around fault addr %" PRIPTR ":\n", + _LOG(log, logtype::MAPS, "\nmemory map around fault addr %" PRIPTR ":\n", reinterpret_cast<uintptr_t>(si.si_addr)); // Search for a match, or for a hole where the match would be. The list @@ -400,27 +392,28 @@ static void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid, int scope } // Show the map address in ascending order (like /proc/pid/maps). - dump_map(log, prev_map, "map below", scope_flags); - dump_map(log, cur_map, "map for address", scope_flags); - dump_map(log, next_map, "map above", scope_flags); + dump_map(log, prev_map, "map below"); + dump_map(log, cur_map, "map for address"); + dump_map(log, next_map, "map above"); } static void dump_thread( - Backtrace* backtrace, log_t* log, int scope_flags, int* total_sleep_time_usec) { + Backtrace* backtrace, log_t* log, int* total_sleep_time_usec) { + wait_for_stop(backtrace->Tid(), total_sleep_time_usec); - dump_registers(log, backtrace->Tid(), scope_flags); - dump_backtrace_and_stack(backtrace, log, scope_flags); - if (IS_AT_FAULT(scope_flags)) { - dump_memory_and_code(log, backtrace->Tid(), scope_flags); - dump_nearby_maps(backtrace->GetMap(), log, backtrace->Tid(), scope_flags); - } + dump_registers(log, backtrace->Tid()); + dump_backtrace_and_stack(backtrace, log); + + dump_memory_and_code(log, backtrace->Tid()); + dump_nearby_maps(backtrace->GetMap(), log, backtrace->Tid()); } // Return true if some thread is not detached cleanly static bool dump_sibling_thread_report( log_t* log, pid_t pid, pid_t tid, int* total_sleep_time_usec, BacktraceMap* map) { char task_path[64]; + snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); DIR* d = opendir(task_path); @@ -447,19 +440,24 @@ static bool dump_sibling_thread_report( // Skip this thread if cannot ptrace it if (ptrace(PTRACE_ATTACH, new_tid, 0, 0) < 0) { + LOG_ERROR("ptrace attach to %d failed: %s\n", new_tid, strerror(errno)); continue; } - _LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n"); - dump_thread_info(log, pid, new_tid, 0); + _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n"); + dump_thread_info(log, pid, new_tid); + + log->current_tid = new_tid; UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map)); if (backtrace->Unwind(0)) { - dump_thread(backtrace.get(), log, 0, total_sleep_time_usec); + dump_thread(backtrace.get(), log, total_sleep_time_usec); } + log->current_tid = log->crashed_tid; + if (ptrace(PTRACE_DETACH, new_tid, 0, 0) != 0) { - LOG("ptrace detach from %d failed: %s\n", new_tid, strerror(errno)); + LOG_ERROR("ptrace detach from %d failed: %s\n", new_tid, strerror(errno)); detach_failed = true; } } @@ -500,12 +498,12 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename, // non-blocking EOF; we're done break; } else { - _LOG(log, 0, "Error while reading log: %s\n", + LOG_ERROR("Error while reading log: %s\n", strerror(-actual)); break; } } else if (actual == 0) { - _LOG(log, 0, "Got zero bytes while reading log: %s\n", + LOG_ERROR("Got zero bytes while reading log: %s\n", strerror(errno)); break; } @@ -522,7 +520,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename, } if (first) { - _LOG(log, 0, "--------- %slog %s\n", + _LOG(log, logtype::HEADER, "--------- %slog %s\n", tail ? "tail end of " : "", filename); first = false; } @@ -552,7 +550,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename, AndroidLogEntry e; char buf[512]; android_log_processBinaryLogBuffer(entry, &e, g_eventTagMap, buf, sizeof(buf)); - _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n", + _LOG(log, logtype::LOGS, "%s.%03d %5d %5d %c %-8s: %s\n", timeBuf, entry->nsec / 1000000, entry->pid, entry->tid, 'I', e.tag, e.message); continue; @@ -579,7 +577,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename, ++nl; } - _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n", + _LOG(log, logtype::LOGS, "%s.%03d %5d %5d %c %-8s: %s\n", timeBuf, entry->nsec / 1000000, entry->pid, entry->tid, prioChar, tag, msg); @@ -619,7 +617,7 @@ static void dump_abort_message(Backtrace* backtrace, log_t* log, uintptr_t addre } msg[sizeof(msg) - 1] = '\0'; - _LOG(log, SCOPE_AT_FAULT, "Abort message: '%s'\n", msg); + _LOG(log, logtype::HEADER, "Abort message: '%s'\n", msg); } // Dumps all information about the specified pid to the tombstone. @@ -641,10 +639,11 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, int si_code TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) ); } - _LOG(log, SCOPE_AT_FAULT, + _LOG(log, logtype::HEADER, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); dump_header_info(log); - dump_thread_info(log, pid, tid, SCOPE_AT_FAULT); + dump_thread_info(log, pid, tid); + if (signal) { dump_signal_info(log, tid, signal, si_code); } @@ -653,7 +652,7 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, int si_code UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get())); if (backtrace->Unwind(0)) { dump_abort_message(backtrace.get(), log, abort_msg_address); - dump_thread(backtrace.get(), log, SCOPE_AT_FAULT, total_sleep_time_usec); + dump_thread(backtrace.get(), log, total_sleep_time_usec); } if (want_logs) { @@ -715,7 +714,7 @@ static char* find_and_open_tombstone(int* fd) { } if (oldest < 0) { - LOG("Failed to find a valid tombstone, default to using tombstone 0.\n"); + LOG_ERROR("Failed to find a valid tombstone, default to using tombstone 0.\n"); oldest = 0; } @@ -723,7 +722,7 @@ static char* find_and_open_tombstone(int* fd) { snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, oldest); *fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (*fd < 0) { - LOG("failed to open tombstone file '%s': %s\n", path, strerror(errno)); + LOG_ERROR("failed to open tombstone file '%s': %s\n", path, strerror(errno)); return NULL; } fchown(*fd, AID_SYSTEM, AID_SYSTEM); @@ -763,12 +762,17 @@ static int activity_manager_connect() { char* engrave_tombstone(pid_t pid, pid_t tid, int signal, int original_si_code, uintptr_t abort_msg_address, bool dump_sibling_threads, bool quiet, bool* detach_failed, int* total_sleep_time_usec) { + + log_t log; + log.current_tid = tid; + log.crashed_tid = tid; + if ((mkdir(TOMBSTONE_DIR, 0755) == -1) && (errno != EEXIST)) { - LOG("failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno)); + LOG_ERROR("failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno)); } if (chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM) == -1) { - LOG("failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno)); + LOG_ERROR("failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno)); } int fd = -1; @@ -776,16 +780,15 @@ char* engrave_tombstone(pid_t pid, pid_t tid, int signal, int original_si_code, if (selinux_android_restorecon(TOMBSTONE_DIR, 0) == 0) { path = find_and_open_tombstone(&fd); } else { - LOG("Failed to restore security context, not writing tombstone.\n"); + LOG_ERROR("Failed to restore security context, not writing tombstone.\n"); } if (fd < 0 && quiet) { - LOG("Skipping tombstone write, nothing to do.\n"); + LOG_ERROR("Skipping tombstone write, nothing to do.\n"); *detach_failed = false; return NULL; } - log_t log; log.tfd = fd; // Preserve amfd since it can be modified through the calls below without // being closed. @@ -795,6 +798,8 @@ char* engrave_tombstone(pid_t pid, pid_t tid, int signal, int original_si_code, *detach_failed = dump_crash(&log, pid, tid, signal, original_si_code, abort_msg_address, dump_sibling_threads, total_sleep_time_usec); + ALOGI("\nTombstone written to: %s\n", path); + // Either of these file descriptors can be -1, any error is ignored. close(amfd); close(fd); diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp index d4c252f..a3acddf 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,7 +27,6 @@ #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 @@ -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)); + LOG_ERROR("AM write failure (%d / %s)\n", errno, strerror(errno)); return -1; } to_write -= written; @@ -44,10 +45,22 @@ 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 && log->tfd; + bool write_to_logcat = (!log || !log->quiet) && is_allowed_in_logcat(ltype) + && (log && log->crashed_tid == log->current_tid); + bool write_to_activitymanager = log && log->amfd >= 0 && is_allowed_in_logcat(ltype); char buf[512]; va_list ap; @@ -60,13 +73,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 @@ -83,20 +96,20 @@ int wait_for_signal(pid_t tid, int* total_sleep_time_usec) { if (n < 0) { if (errno == EAGAIN) continue; - LOG("waitpid failed: %s\n", strerror(errno)); + LOG_ERROR("waitpid failed: %s\n", strerror(errno)); return -1; } else if (n > 0) { XLOG("waitpid: n=%d status=%08x\n", n, status); if (WIFSTOPPED(status)) { return WSTOPSIG(status); } else { - LOG("unexpected waitpid response: n=%d, status=%08x\n", n, status); + LOG_ERROR("unexpected waitpid response: n=%d, status=%08x\n", n, status); return -1; } } if (*total_sleep_time_usec > max_total_sleep_usec) { - LOG("timed out waiting for tid=%d to die\n", tid); + LOG_ERROR("timed out waiting for tid=%d to die\n", tid); return -1; } @@ -111,7 +124,7 @@ 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); + LOG_ERROR("timed out waiting for tid=%d to stop\n", tid); break; } @@ -126,7 +139,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 +203,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); } } diff --git a/debuggerd/utility.h b/debuggerd/utility.h index 0f88605..fdfb2ec 100644 --- a/debuggerd/utility.h +++ b/debuggerd/utility.h @@ -28,41 +28,36 @@ typedef struct { int amfd; /* if true, does not log anything to the Android logcat or Activity Manager */ bool quiet; + // The tid of the thread that crashed. + pid_t crashed_tid; + // The tid of the thread we are currently working with. + pid_t current_tid; } log_t; -/* Log information onto the tombstone. scopeFlags is a bitmask of the flags defined - * here. */ -void _LOG(log_t* log, int scopeFlags, const char *fmt, ...) +// List of types of logs to simplify the logging decision in _LOG +enum logtype { + ERROR, + HEADER, + THREAD, + REGISTERS, + BACKTRACE, + MAPS, + MEMORY, + STACK, + LOGS +}; + +/* Log information onto the tombstone. */ +void _LOG(log_t* log, logtype ltype, const char *fmt, ...) __attribute__ ((format(printf, 3, 4))); -/* The message pertains specifically to the faulting thread / process */ -#define SCOPE_AT_FAULT (1 << 0) -/* The message contains sensitive information such as RAM contents */ -#define SCOPE_SENSITIVE (1 << 1) - -#define IS_AT_FAULT(x) (((x) & SCOPE_AT_FAULT) != 0) -#define IS_SENSITIVE(x) (((x) & SCOPE_SENSITIVE) != 0) - /* Further helpful macros */ -#define LOG(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt) - -/* Set to 1 for normal debug traces */ -#if 0 -#define XLOG(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt) -#else +#define LOG_ERROR(fmt...) _LOG(NULL, logtype::ERROR, fmt) #define XLOG(fmt...) do {} while(0) -#endif - -/* Set to 1 for chatty debug traces. Includes all resolved dynamic symbols */ -#if 0 -#define XLOG2(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt) -#else -#define XLOG2(fmt...) do {} while(0) -#endif int wait_for_signal(pid_t tid, int* total_sleep_time_usec); void wait_for_stop(pid_t tid, int* total_sleep_time_usec); -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); #endif // _DEBUGGERD_UTILITY_H diff --git a/debuggerd/x86/machine.cpp b/debuggerd/x86/machine.cpp index bcc217e..2d553fa 100644 --- a/debuggerd/x86/machine.cpp +++ b/debuggerd/x86/machine.cpp @@ -25,21 +25,21 @@ #include "../utility.h" #include "../machine.h" -void dump_memory_and_code(log_t*, pid_t, int) { +void dump_memory_and_code(log_t*, pid_t) { } -void dump_registers(log_t* log, pid_t tid, int scope_flags) { +void dump_registers(log_t* log, pid_t tid) { struct pt_regs r; if (ptrace(PTRACE_GETREGS, tid, 0, &r) == -1) { - _LOG(log, scope_flags, "cannot get registers: %s\n", strerror(errno)); + LOG_ERROR("cannot get registers: %s\n", strerror(errno)); return; } - _LOG(log, scope_flags, " eax %08lx ebx %08lx ecx %08lx edx %08lx\n", + _LOG(log, logtype::REGISTERS, " eax %08lx ebx %08lx ecx %08lx edx %08lx\n", r.eax, r.ebx, r.ecx, r.edx); - _LOG(log, scope_flags, " esi %08lx edi %08lx\n", + _LOG(log, logtype::REGISTERS, " esi %08lx edi %08lx\n", r.esi, r.edi); - _LOG(log, scope_flags, " xcs %08x xds %08x xes %08x xfs %08x xss %08x\n", + _LOG(log, logtype::REGISTERS, " xcs %08x xds %08x xes %08x xfs %08x xss %08x\n", r.xcs, r.xds, r.xes, r.xfs, r.xss); - _LOG(log, scope_flags, " eip %08lx ebp %08lx esp %08lx flags %08lx\n", + _LOG(log, logtype::REGISTERS, " eip %08lx ebp %08lx esp %08lx flags %08lx\n", r.eip, r.ebp, r.esp, r.eflags); } diff --git a/debuggerd/x86_64/machine.cpp b/debuggerd/x86_64/machine.cpp index c8c7aa9..6cb0e8d 100755 --- a/debuggerd/x86_64/machine.cpp +++ b/debuggerd/x86_64/machine.cpp @@ -27,25 +27,25 @@ #include "../utility.h" #include "../machine.h" -void dump_memory_and_code(log_t*, pid_t, int) { +void dump_memory_and_code(log_t*, pid_t) { } -void dump_registers(log_t* log, pid_t tid, int scope_flags) { +void dump_registers(log_t* log, pid_t tid) { struct user_regs_struct r; if (ptrace(PTRACE_GETREGS, tid, 0, &r) == -1) { - _LOG(log, scope_flags, "cannot get registers: %s\n", strerror(errno)); + LOG_ERROR("cannot get registers: %s\n", strerror(errno)); return; } - _LOG(log, scope_flags, " rax %016lx rbx %016lx rcx %016lx rdx %016lx\n", + _LOG(log, logtype::REGISTERS, " rax %016lx rbx %016lx rcx %016lx rdx %016lx\n", r.rax, r.rbx, r.rcx, r.rdx); - _LOG(log, scope_flags, " rsi %016lx rdi %016lx\n", + _LOG(log, logtype::REGISTERS, " rsi %016lx rdi %016lx\n", r.rsi, r.rdi); - _LOG(log, scope_flags, " r8 %016lx r9 %016lx r10 %016lx r11 %016lx\n", + _LOG(log, logtype::REGISTERS, " r8 %016lx r9 %016lx r10 %016lx r11 %016lx\n", r.r8, r.r9, r.r10, r.r11); - _LOG(log, scope_flags, " r12 %016lx r13 %016lx r14 %016lx r15 %016lx\n", + _LOG(log, logtype::REGISTERS, " r12 %016lx r13 %016lx r14 %016lx r15 %016lx\n", r.r12, r.r13, r.r14, r.r15); - _LOG(log, scope_flags, " cs %016lx ss %016lx\n", + _LOG(log, logtype::REGISTERS, " cs %016lx ss %016lx\n", r.cs, r.ss); - _LOG(log, scope_flags, " rip %016lx rbp %016lx rsp %016lx eflags %016lx\n", + _LOG(log, logtype::REGISTERS, " rip %016lx rbp %016lx rsp %016lx eflags %016lx\n", r.rip, r.rbp, r.rsp, r.eflags); } |