Commit 7716aef1 authored by Christopher Tate's avatar Christopher Tate
Browse files

Uploaded native crash dumps do not include memory contents

Also fixed the LOG() macro to actually write to the log again, tracking
the change in _LOG() argument semantics.

Bug 8322568

Change-Id: I79330c85c26d3ffb734315b6d0f2c0bb80bd234a
parent e5f8a692
......@@ -42,7 +42,7 @@
#endif
#endif
static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scopeFlags) {
char code_buffer[64]; /* actual 8+1+((8+1)*4) + 1 == 45 */
char ascii_buffer[32]; /* actual 16 + 1 == 17 */
uintptr_t p, end;
......@@ -102,7 +102,7 @@ static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
p += 4;
}
*asc_out = '\0';
_LOG(log, !at_fault, " %s %s\n", code_buffer, ascii_buffer);
_LOG(log, scopeFlags, " %s %s\n", code_buffer, ascii_buffer);
}
}
......@@ -117,6 +117,8 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
return;
}
int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
if (at_fault && DUMP_MEMORY_FOR_ALL_REGISTERS) {
static const char REG_NAMES[] = "r0r1r2r3r4r5r6r7r8r9slfpipsp";
......@@ -132,17 +134,18 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
continue;
}
_LOG(log, false, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
dump_memory(log, tid, addr, at_fault);
_LOG(log, scopeFlags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
dump_memory(log, tid, addr, scopeFlags | SCOPE_SENSITIVE);
}
}
_LOG(log, !at_fault, "\ncode around pc:\n");
dump_memory(log, tid, (uintptr_t)regs.ARM_pc, at_fault);
/* explicitly allow upload of code dump logging */
_LOG(log, scopeFlags, "\ncode around pc:\n");
dump_memory(log, tid, (uintptr_t)regs.ARM_pc, scopeFlags);
if (regs.ARM_pc != regs.ARM_lr) {
_LOG(log, !at_fault, "\ncode around lr:\n");
dump_memory(log, tid, (uintptr_t)regs.ARM_lr, at_fault);
_LOG(log, scopeFlags, "\ncode around lr:\n");
dump_memory(log, tid, (uintptr_t)regs.ARM_lr, scopeFlags);
}
}
......@@ -150,20 +153,20 @@ void dump_registers(const ptrace_context_t* context __attribute((unused)),
log_t* log, pid_t tid, bool at_fault)
{
struct pt_regs r;
bool only_in_tombstone = !at_fault;
int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
_LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
_LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
return;
}
_LOG(log, only_in_tombstone, " r0 %08x r1 %08x r2 %08x r3 %08x\n",
_LOG(log, scopeFlags, " r0 %08x r1 %08x r2 %08x r3 %08x\n",
(uint32_t)r.ARM_r0, (uint32_t)r.ARM_r1, (uint32_t)r.ARM_r2, (uint32_t)r.ARM_r3);
_LOG(log, only_in_tombstone, " r4 %08x r5 %08x r6 %08x r7 %08x\n",
_LOG(log, scopeFlags, " r4 %08x r5 %08x r6 %08x r7 %08x\n",
(uint32_t)r.ARM_r4, (uint32_t)r.ARM_r5, (uint32_t)r.ARM_r6, (uint32_t)r.ARM_r7);
_LOG(log, only_in_tombstone, " r8 %08x r9 %08x sl %08x fp %08x\n",
_LOG(log, scopeFlags, " r8 %08x r9 %08x sl %08x fp %08x\n",
(uint32_t)r.ARM_r8, (uint32_t)r.ARM_r9, (uint32_t)r.ARM_r10, (uint32_t)r.ARM_fp);
_LOG(log, only_in_tombstone, " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
_LOG(log, scopeFlags, " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
(uint32_t)r.ARM_ip, (uint32_t)r.ARM_sp, (uint32_t)r.ARM_lr,
(uint32_t)r.ARM_pc, (uint32_t)r.ARM_cpsr);
......@@ -172,14 +175,14 @@ void dump_registers(const ptrace_context_t* context __attribute((unused)),
int i;
if(ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
_LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
_LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
return;
}
for (i = 0; i < NUM_VFP_REGS; i += 2) {
_LOG(log, only_in_tombstone, " d%-2d %016llx d%-2d %016llx\n",
_LOG(log, scopeFlags, " d%-2d %016llx d%-2d %016llx\n",
i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
}
_LOG(log, only_in_tombstone, " scr %08lx\n", vfp_regs.fpscr);
_LOG(log, scopeFlags, " scr %08lx\n", vfp_regs.fpscr);
#endif
}
......@@ -51,15 +51,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, false, "\n\n----- pid %d at %s -----\n", pid, timestr);
_LOG(log, SCOPE_AT_FAULT, "\n\n----- pid %d at %s -----\n", pid, timestr);
if (procname) {
_LOG(log, false, "Cmd line: %s\n", procname);
_LOG(log, SCOPE_AT_FAULT, "Cmd line: %s\n", procname);
}
}
static void dump_process_footer(log_t* log, pid_t pid) {
_LOG(log, false, "\n----- end %d -----\n", pid);
_LOG(log, SCOPE_AT_FAULT, "\n----- end %d -----\n", pid);
}
static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool attached,
......@@ -81,10 +81,11 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a
}
}
_LOG(log, false, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid);
_LOG(log, SCOPE_AT_FAULT, "\n\"%s\" sysTid=%d\n",
threadname ? threadname : "<unknown>", tid);
if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
_LOG(log, false, "Could not attach to thread: %s\n", strerror(errno));
_LOG(log, SCOPE_AT_FAULT, "Could not attach to thread: %s\n", strerror(errno));
return;
}
......@@ -93,7 +94,7 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a
backtrace_frame_t backtrace[STACK_DEPTH];
ssize_t frames = unwind_backtrace_ptrace(tid, context, backtrace, 0, STACK_DEPTH);
if (frames <= 0) {
_LOG(log, false, "Could not obtain stack trace for thread.\n");
_LOG(log, SCOPE_AT_FAULT, "Could not obtain stack trace for thread.\n");
} else {
backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
......@@ -101,7 +102,7 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a
char line[MAX_BACKTRACE_LINE_LENGTH];
format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
line, MAX_BACKTRACE_LINE_LENGTH);
_LOG(log, false, " %s\n", line);
_LOG(log, SCOPE_AT_FAULT, " %s\n", line);
}
free_backtrace_symbols(backtrace_symbols, frames);
}
......
......@@ -36,7 +36,7 @@
#define R(x) ((unsigned int)(x))
static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scopeFlags) {
char code_buffer[64]; /* actual 8+1+((8+1)*4) + 1 == 45 */
char ascii_buffer[32]; /* actual 16 + 1 == 17 */
uintptr_t p, end;
......@@ -92,7 +92,7 @@ static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
p += 4;
}
*asc_out = '\0';
_LOG(log, !at_fault, " %s %s\n", code_buffer, ascii_buffer);
_LOG(log, scopeFlags, " %s %s\n", code_buffer, ascii_buffer);
}
}
......@@ -107,6 +107,7 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
return;
}
int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
if (at_fault && DUMP_MEMORY_FOR_ALL_REGISTERS) {
static const char REG_NAMES[] = "$0atv0v1a0a1a2a3t0t1t2t3t4t5t6t7s0s1s2s3s4s5s6s7t8t9k0k1gpsps8ra";
......@@ -129,20 +130,20 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
continue;
}
_LOG(log, false, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
dump_memory(log, tid, addr, at_fault);
_LOG(log, scopeFlags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
dump_memory(log, tid, addr, scopeFlags | SCOPE_SENSITIVE);
}
}
unsigned int pc = R(r.cp0_epc);
unsigned int ra = R(r.regs[31]);
_LOG(log, !at_fault, "\ncode around pc:\n");
dump_memory(log, tid, (uintptr_t)pc, at_fault);
_LOG(log, scopeFlags, "\ncode around pc:\n");
dump_memory(log, tid, (uintptr_t)pc, scopeFlags);
if (pc != ra) {
_LOG(log, !at_fault, "\ncode around ra:\n");
dump_memory(log, tid, (uintptr_t)ra, at_fault);
_LOG(log, scopeFlags, "\ncode around ra:\n");
dump_memory(log, tid, (uintptr_t)ra, scopeFlags);
}
}
......@@ -150,29 +151,29 @@ void dump_registers(const ptrace_context_t* context __attribute((unused)),
log_t* log, pid_t tid, bool at_fault)
{
pt_regs_mips_t r;
bool only_in_tombstone = !at_fault;
int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
_LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
_LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
return;
}
_LOG(log, only_in_tombstone, " zr %08x at %08x v0 %08x v1 %08x\n",
_LOG(log, scopeFlags, " 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, only_in_tombstone, " a0 %08x a1 %08x a2 %08x a3 %08x\n",
_LOG(log, scopeFlags, " 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, only_in_tombstone, " t0 %08x t1 %08x t2 %08x t3 %08x\n",
_LOG(log, scopeFlags, " 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, only_in_tombstone, " t4 %08x t5 %08x t6 %08x t7 %08x\n",
_LOG(log, scopeFlags, " 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, only_in_tombstone, " s0 %08x s1 %08x s2 %08x s3 %08x\n",
_LOG(log, scopeFlags, " 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, only_in_tombstone, " s4 %08x s5 %08x s6 %08x s7 %08x\n",
_LOG(log, scopeFlags, " 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, only_in_tombstone, " t8 %08x t9 %08x k0 %08x k1 %08x\n",
_LOG(log, scopeFlags, " 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, only_in_tombstone, " gp %08x sp %08x s8 %08x ra %08x\n",
_LOG(log, scopeFlags, " 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, only_in_tombstone, " hi %08x lo %08x bva %08x epc %08x\n",
_LOG(log, scopeFlags, " hi %08x lo %08x bva %08x epc %08x\n",
R(r.hi), R(r.lo), R(r.cp0_badvaddr), R(r.cp0_epc));
}
......@@ -163,7 +163,7 @@ static void dump_revision_info(log_t* log)
property_get("ro.revision", revision, "unknown");
_LOG(log, false, "Revision: '%s'\n", revision);
_LOG(log, SCOPE_AT_FAULT, "Revision: '%s'\n", revision);
}
static void dump_build_info(log_t* log)
......@@ -172,7 +172,7 @@ static void dump_build_info(log_t* log)
property_get("ro.build.fingerprint", fingerprint, "unknown");
_LOG(log, false, "Build fingerprint: '%s'\n", fingerprint);
_LOG(log, SCOPE_AT_FAULT, "Build fingerprint: '%s'\n", fingerprint);
}
static void dump_fault_addr(log_t* log, pid_t tid, int sig)
......@@ -180,15 +180,15 @@ static void dump_fault_addr(log_t* log, pid_t tid, int sig)
siginfo_t si;
memset(&si, 0, sizeof(si));
if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
_LOG(log, false, "cannot get siginfo: %s\n", strerror(errno));
if(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
_LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno));
} else if (signal_has_address(sig)) {
_LOG(log, false, "signal %d (%s), code %d (%s), fault addr %08x\n",
_LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %08x\n",
sig, get_signame(sig),
si.si_code, get_sigcode(sig, si.si_code),
(uintptr_t) si.si_addr);
} else {
_LOG(log, false, "signal %d (%s), code %d (%s), fault addr --------\n",
_LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n",
sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
}
}
......@@ -221,19 +221,20 @@ static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, bool at_fault) {
fclose(fp);
}
_LOG(log, false, "pid: %d, tid: %d, name: %s >>> %s <<<\n", pid, tid,
_LOG(log, SCOPE_AT_FAULT, "pid: %d, tid: %d, name: %s >>> %s <<<\n", pid, tid,
threadname ? threadname : "UNKNOWN",
procname ? procname : "UNKNOWN");
} else {
_LOG(log, true, "pid: %d, tid: %d, name: %s\n", pid, tid,
threadname ? threadname : "UNKNOWN");
_LOG(log, 0, "pid: %d, tid: %d, name: %s\n",
pid, tid, threadname ? threadname : "UNKNOWN");
}
}
static void dump_backtrace(const ptrace_context_t* context __attribute((unused)),
log_t* log, pid_t tid __attribute((unused)), bool at_fault,
const backtrace_frame_t* backtrace, size_t frames) {
_LOG(log, !at_fault, "\nbacktrace:\n");
int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
_LOG(log, scopeFlags, "\nbacktrace:\n");
backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
......@@ -241,13 +242,13 @@ static void dump_backtrace(const ptrace_context_t* context __attribute((unused))
char line[MAX_BACKTRACE_LINE_LENGTH];
format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
line, MAX_BACKTRACE_LINE_LENGTH);
_LOG(log, !at_fault, " %s\n", line);
_LOG(log, scopeFlags, " %s\n", line);
}
free_backtrace_symbols(backtrace_symbols, frames);
}
static void dump_stack_segment(const ptrace_context_t* context, log_t* log, pid_t tid,
bool only_in_tombstone, uintptr_t* sp, size_t words, int label) {
int scopeFlags, uintptr_t* sp, size_t words, int label) {
for (size_t i = 0; i < words; i++) {
uint32_t stack_content;
if (!try_get_word_ptrace(tid, *sp, &stack_content)) {
......@@ -264,28 +265,28 @@ static void dump_stack_segment(const ptrace_context_t* context, log_t* log, pid_
uint32_t offset = stack_content - (mi->start + symbol->start);
if (!i && label >= 0) {
if (offset) {
_LOG(log, only_in_tombstone, " #%02d %08x %08x %s (%s+%u)\n",
_LOG(log, scopeFlags, " #%02d %08x %08x %s (%s+%u)\n",
label, *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
} else {
_LOG(log, only_in_tombstone, " #%02d %08x %08x %s (%s)\n",
_LOG(log, scopeFlags, " #%02d %08x %08x %s (%s)\n",
label, *sp, stack_content, mi ? mi->name : "", symbol_name);
}
} else {
if (offset) {
_LOG(log, only_in_tombstone, " %08x %08x %s (%s+%u)\n",
_LOG(log, scopeFlags, " %08x %08x %s (%s+%u)\n",
*sp, stack_content, mi ? mi->name : "", symbol_name, offset);
} else {
_LOG(log, only_in_tombstone, " %08x %08x %s (%s)\n",
_LOG(log, scopeFlags, " %08x %08x %s (%s)\n",
*sp, stack_content, mi ? mi->name : "", symbol_name);
}
}
free(demangled_name);
} else {
if (!i && label >= 0) {
_LOG(log, only_in_tombstone, " #%02d %08x %08x %s\n",
_LOG(log, scopeFlags, " #%02d %08x %08x %s\n",
label, *sp, stack_content, mi ? mi->name : "");
} else {
_LOG(log, only_in_tombstone, " %08x %08x %s\n",
_LOG(log, scopeFlags, " %08x %08x %s\n",
*sp, stack_content, mi ? mi->name : "");
}
}
......@@ -311,28 +312,28 @@ static void dump_stack(const ptrace_context_t* context, log_t* log, pid_t tid, b
return;
}
_LOG(log, !at_fault, "\nstack:\n");
int scopeFlags = SCOPE_SENSITIVE | (at_fault ? SCOPE_AT_FAULT : 0);
_LOG(log, scopeFlags, "\nstack:\n");
// Dump a few words before the first frame.
bool only_in_tombstone = !at_fault;
uintptr_t sp = backtrace[first].stack_top - STACK_WORDS * sizeof(uint32_t);
dump_stack_segment(context, log, tid, only_in_tombstone, &sp, STACK_WORDS, -1);
dump_stack_segment(context, log, tid, scopeFlags, &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_t* frame = &backtrace[i];
if (sp != frame->stack_top) {
_LOG(log, only_in_tombstone, " ........ ........\n");
_LOG(log, scopeFlags, " ........ ........\n");
sp = frame->stack_top;
}
if (i - first == 3) {
only_in_tombstone = true;
scopeFlags &= (~SCOPE_AT_FAULT);
}
if (i == last) {
dump_stack_segment(context, log, tid, only_in_tombstone, &sp, STACK_WORDS, i);
dump_stack_segment(context, log, tid, scopeFlags, &sp, STACK_WORDS, i);
if (sp < frame->stack_top + frame->stack_size) {
_LOG(log, only_in_tombstone, " ........ ........\n");
_LOG(log, scopeFlags, " ........ ........\n");
}
} else {
size_t words = frame->stack_size / sizeof(uint32_t);
......@@ -341,7 +342,7 @@ static void dump_stack(const ptrace_context_t* context, log_t* log, pid_t tid, b
} else if (words > STACK_WORDS) {
words = STACK_WORDS;
}
dump_stack_segment(context, log, tid, only_in_tombstone, &sp, words, i);
dump_stack_segment(context, log, tid, scopeFlags, &sp, words, i);
}
}
}
......@@ -358,13 +359,13 @@ static void dump_backtrace_and_stack(const ptrace_context_t* context, log_t* log
static void dump_map(log_t* log, map_info_t* m, const char* what) {
if (m != NULL) {
_LOG(log, false, " %08x-%08x %c%c%c %s\n", m->start, m->end,
_LOG(log, SCOPE_SENSITIVE, " %08x-%08x %c%c%c %s\n", m->start, m->end,
m->is_readable ? 'r' : '-',
m->is_writable ? 'w' : '-',
m->is_executable ? 'x' : '-',
m->name);
} else {
_LOG(log, false, " (no %s)\n", what);
_LOG(log, SCOPE_SENSITIVE, " (no %s)\n", what);
}
}
......@@ -372,7 +373,7 @@ static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t
siginfo_t si;
memset(&si, 0, sizeof(si));
if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
_LOG(log, false, "cannot get siginfo for %d: %s\n",
_LOG(log, SCOPE_SENSITIVE, "cannot get siginfo for %d: %s\n",
tid, strerror(errno));
return;
}
......@@ -386,7 +387,7 @@ static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t
return;
}
_LOG(log, false, "\nmemory map around fault addr %08x:\n", (int)si.si_addr);
_LOG(log, SCOPE_SENSITIVE, "\nmemory map around fault addr %08x:\n", (int)si.si_addr);
/*
* Search for a match, or for a hole where the match would be. The list
......@@ -464,7 +465,7 @@ static bool dump_sibling_thread_report(const ptrace_context_t* context,
continue;
}
_LOG(log, true, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
_LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
dump_thread_info(log, pid, new_tid, false);
dump_thread(context, log, new_tid, false, total_sleep_time_usec);
......@@ -517,12 +518,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, true, "Error while reading log: %s\n",
_LOG(log, 0, "Error while reading log: %s\n",
strerror(errno));
break;
}
} else if (actual == 0) {
_LOG(log, true, "Got zero bytes while reading log: %s\n",
_LOG(log, 0, "Got zero bytes while reading log: %s\n",
strerror(errno));
break;
}
......@@ -542,7 +543,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
}
if (first) {
_LOG(log, true, "--------- %slog %s\n",
_LOG(log, 0, "--------- %slog %s\n",
tailOnly ? "tail end of " : "", filename);
first = false;
}
......@@ -584,7 +585,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
shortLogCount++;
} else {
_LOG(log, true, "%s.%03d %5d %5d %c %-8s: %s\n",
_LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n",
timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
prioChar, tag, msg);
}
......@@ -604,7 +605,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
}
for (i = 0; i < shortLogCount; i++) {
_LOG(log, true, "%s\n", shortLog[shortLogNext]);
_LOG(log, 0, "%s\n", shortLog[shortLogNext]);
shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
}
}
......@@ -654,7 +655,7 @@ static void dump_abort_message(log_t* log, pid_t tid, uintptr_t address) {
}
msg[sizeof(msg) - 1] = '\0';
_LOG(log, false, "Abort message: '%s'\n", msg);
_LOG(log, SCOPE_AT_FAULT, "Abort message: '%s'\n", msg);
}
/*
......@@ -680,7 +681,7 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
}
_LOG(log, false,
_LOG(log, SCOPE_AT_FAULT,
"*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
dump_build_info(log);
dump_revision_info(log);
......
......@@ -39,6 +39,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));
return -1;
}
to_write -= written;
......@@ -46,20 +47,20 @@ static int write_to_am(int fd, const char* buf, int len) {
return len;
}
void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...) {
void _LOG(log_t* log, int scopeFlags, const char *fmt, ...) {
char buf[512];
bool want_tfd_write;
bool want_log_write;
bool want_amfd_write;
int len;
int len = 0;
va_list ap;
va_start(ap, fmt);
// where is the information going to go?
want_tfd_write = log && log->tfd >= 0; // write to the tombstone fd?
want_log_write = !in_tombstone_only && (!log || !log->quiet);
want_amfd_write = log && log->amfd >= 0; // only used when want_log_write is true
want_tfd_write = log && log->tfd >= 0;
want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
// if we're going to need the literal string, generate it once here
if (want_tfd_write || want_amfd_write) {
......@@ -78,7 +79,6 @@ void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...) {
int written = write_to_am(log->amfd, buf, len);
if (written <= 0) {
// timeout or other failure on write; stop informing the activity manager
LOG("AM write failure, giving up\n");
log->amfd = -1;
}
}
......
......@@ -30,22 +30,32 @@ typedef struct {
bool quiet;
} log_t;
/* Log information onto the tombstone. */
void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...)
/* Log information onto the tombstone. scopeFlags is a bitmask of the flags defined
* here. */
void _LOG(log_t* log, int scopeFlags, const char *fmt, ...)
__attribute__ ((format(printf, 3, 4)));
#define LOG(fmt...) _LOG(NULL, 0, fmt)
/* 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, 0, fmt)
#define XLOG(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt)
#else
#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, 0, fmt)
#define XLOG2(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt)
#else
#define XLOG2(fmt...) do {} while(0)
#endif
......
......@@ -38,21 +38,21 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
void dump_registers(const ptrace_context_t* context __attribute((unused)),
log_t* log, pid_t tid, bool at_fault) {
struct pt_regs_x86 r;
bool only_in_tombstone = !at_fault;
int scopeFlags = (at_fault ? SCOPE_AT_FAULT : 0);
if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
_LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
_LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
return;
}
//if there is no stack, no print just like arm
if(!r.ebp)
return;
_LOG(log, only_in_tombstone, " eax %08x ebx %08x ecx %08x edx %08x\n",
_LOG(log, scopeFlags, " eax %08x ebx %08x ecx %08x edx %08x\n",
r.eax, r.ebx, r.ecx, r.edx);
_LOG(log, only_in_tombstone, " esi %08x edi %08x\n",
_LOG(log, scopeFlags, " esi %08x edi %08x\n",
r.esi, r.edi);
_LOG(log, only_in_tombstone, " xcs %08x xds %08x xes %08x xfs %08x xss %08x\n",
_LOG(log, scopeFlags, " xcs %08x xds %08x xes %08x xfs %08x xss %08x\n",
r.xcs, r.xds, r.xes, r.xfs, r.xss);
_LOG(log, only_in_tombstone, " eip %08x ebp %08x esp %08x flags %08x\n",
_LOG(log, scopeFlags, " eip %08x ebp %08x esp %08x flags %08x\n",
r.eip, r.ebp, r.esp, r.eflags);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment