summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debuggerd/arm/machine.cpp52
-rw-r--r--debuggerd/arm64/machine.cpp52
-rw-r--r--debuggerd/backtrace.cpp20
-rw-r--r--debuggerd/backtrace.h3
-rw-r--r--debuggerd/debuggerd.cpp35
-rw-r--r--debuggerd/machine.h4
-rw-r--r--debuggerd/mips/machine.cpp71
-rwxr-xr-xdebuggerd/tombstone.cpp163
-rw-r--r--debuggerd/utility.cpp45
-rw-r--r--debuggerd/utility.h47
-rw-r--r--debuggerd/x86/machine.cpp14
-rwxr-xr-xdebuggerd/x86_64/machine.cpp18
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, &regs)) {
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", &REG_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", &REG_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 = &regs;
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", &REG_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", &REG_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);
}