Changing how debuggerd filters log messages to different locations.
The system by which debuggerd filters its output to different locations
is now based on an enum called logtype with easy to understand
categories for log messages (like THREAD, MEMORY, etc.) instead of the
old, fairly esoteric scope_flags variable. Now much of the output that
previously went to logcat does not show up on the screen, but all output
can be found in the tombstone file. In addition, the tombstone's
location is now printed so it can be located easily.
Bug: 15341747
Change-Id: Ia2f2051d1dfdea934d0e6ed220f24345e35ba6a2
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 @@
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 @@
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 @@
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 @@
}
}
- _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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
} 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 @@
// 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 @@
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 @@
// 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";
+ 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;
+ 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;
- uintptr_t addr = R(r.regs[reg]);
+ uintptr_t addr = R(r.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 >= 0x80000000) {
- 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 >= 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 @@
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 @@
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 @@
}
}
- if (IS_AT_FAULT(scope_flags)) {
- char procnamebuf[1024];
- char* procname = NULL;
+ 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);
- }
-
- _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 @@
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(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 @@
}
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 @@
} 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 @@
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 @@
}
// 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 @@
// 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 @@
// 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 @@
}
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 @@
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 @@
++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 @@
}
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
*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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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);
}