Merge "liblog: do better checks of log messages."
diff --git a/debuggerd/arm/machine.c b/debuggerd/arm/machine.c
index 58a7839..fb0d6ba 100644
--- a/debuggerd/arm/machine.c
+++ b/debuggerd/arm/machine.c
@@ -36,6 +36,9 @@
#include "utility.h"
+/* enable to dump memory pointed to by every register */
+#define DUMP_MEM_FOR_ALL_REGS 0
+
#ifdef WITH_VFP
#ifdef WITH_VFP_D32
#define NUM_VFP_REGS 32
@@ -117,82 +120,128 @@
}
}
+/*
+ * Dumps a few bytes of memory, starting a bit before and ending a bit
+ * after the specified address.
+ */
+static void dump_memory(int tfd, int pid, uintptr_t addr,
+ bool only_in_tombstone)
+{
+ char code_buffer[64]; /* actual 8+1+((8+1)*4) + 1 == 45 */
+ char ascii_buffer[32]; /* actual 16 + 1 == 17 */
+ uintptr_t p, end;
+
+ p = addr & ~3;
+ p -= 32;
+ if (p > addr) {
+ /* catch underflow */
+ p = 0;
+ }
+ end = p + 80;
+ /* catch overflow; 'end - p' has to be multiples of 16 */
+ while (end < p)
+ end -= 16;
+
+ /* Dump the code around PC as:
+ * addr contents ascii
+ * 00008d34 ef000000 e8bd0090 e1b00000 512fff1e ............../Q
+ * 00008d44 ea00b1f9 e92d0090 e3a070fc ef000000 ......-..p......
+ */
+ while (p < end) {
+ char* asc_out = ascii_buffer;
+
+ sprintf(code_buffer, "%08x ", p);
+
+ int i;
+ for (i = 0; i < 4; i++) {
+ /*
+ * If we see (data == -1 && errno != 0), we know that the ptrace
+ * call failed, probably because we're dumping memory in an
+ * unmapped or inaccessible page. I don't know if there's
+ * value in making that explicit in the output -- it likely
+ * just complicates parsing and clarifies nothing for the
+ * enlightened reader.
+ */
+ long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
+ sprintf(code_buffer + strlen(code_buffer), "%08lx ", data);
+
+ int j;
+ for (j = 0; j < 4; j++) {
+ /*
+ * Our isprint() allows high-ASCII characters that display
+ * differently (often badly) in different viewers, so we
+ * just use a simpler test.
+ */
+ char val = (data >> (j*8)) & 0xff;
+ if (val >= 0x20 && val < 0x7f) {
+ *asc_out++ = val;
+ } else {
+ *asc_out++ = '.';
+ }
+ }
+ p += 4;
+ }
+ *asc_out = '\0';
+ _LOG(tfd, only_in_tombstone, "%s %s\n", code_buffer, ascii_buffer);
+ }
+
+}
void dump_stack_and_code(int tfd, int pid, mapinfo *map,
int unwind_depth, unsigned int sp_list[],
bool at_fault)
{
- unsigned int sp, pc, lr, p, end, data;
struct pt_regs r;
int sp_depth;
bool only_in_tombstone = !at_fault;
- char code_buffer[80];
if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return;
- sp = r.ARM_sp;
- pc = r.ARM_pc;
- lr = r.ARM_lr;
- _LOG(tfd, only_in_tombstone, "\ncode around pc:\n");
-
- p = pc & ~3;
- p -= 32;
- if (p > pc)
- p = 0;
- end = p + 80;
- /* 'end - p' has to be multiples of 16 */
- while (end < p)
- end -= 16;
-
- /* Dump the code around PC as:
- * addr contents
- * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c
- * 00008d44 f7ff18a0 490ced94 68035860 d0012b00
- */
- while (p < end) {
- int i;
-
- sprintf(code_buffer, "%08x ", p);
- for (i = 0; i < 4; i++) {
- data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
- sprintf(code_buffer + strlen(code_buffer), "%08x ", data);
- p += 4;
- }
- _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
- }
-
- if (lr != pc) {
- _LOG(tfd, only_in_tombstone, "\ncode around lr:\n");
-
- p = lr & ~3;
- p -= 32;
- if (p > lr)
- p = 0;
- end = p + 80;
- /* 'end - p' has to be multiples of 16 */
- while (end < p)
- end -= 16;
-
- /* Dump the code around LR as:
- * addr contents
- * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c
- * 00008d44 f7ff18a0 490ced94 68035860 d0012b00
+ if (DUMP_MEM_FOR_ALL_REGS && at_fault) {
+ /*
+ * If configured to do so, dump memory around *all* registers
+ * for the crashing thread.
+ *
+ * TODO: remove duplicates.
*/
- while (p < end) {
- int i;
+ static const char REG_NAMES[] = "R0R1R2R3R4R5R6R7R8R9SLFPIPSPLRPC";
- sprintf(code_buffer, "%08x ", p);
- for (i = 0; i < 4; i++) {
- data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
- sprintf(code_buffer + strlen(code_buffer), "%08x ", data);
- p += 4;
+ int reg;
+ for (reg = 0; reg < 16; reg++) {
+ /* this may not be a valid way to access, but it'll do for now */
+ uintptr_t addr = r.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(tfd, only_in_tombstone, "%s\n", code_buffer);
+
+ _LOG(tfd, only_in_tombstone, "\nmem near %.2s:\n",
+ ®_NAMES[reg*2]);
+ dump_memory(tfd, pid, addr, false);
+ }
+ } else {
+ unsigned int pc, lr;
+ pc = r.ARM_pc;
+ lr = r.ARM_lr;
+
+ _LOG(tfd, only_in_tombstone, "\ncode around pc:\n");
+ dump_memory(tfd, pid, (uintptr_t) pc, only_in_tombstone);
+
+ if (lr != pc) {
+ _LOG(tfd, only_in_tombstone, "\ncode around lr:\n");
+ dump_memory(tfd, pid, (uintptr_t) lr, only_in_tombstone);
}
}
show_nearby_maps(tfd, pid, map);
+ unsigned int p, end;
+ unsigned int sp = r.ARM_sp;
+
p = sp - 64;
if (p > sp)
p = 0;
@@ -227,7 +276,7 @@
while (p <= end) {
char *prompt;
char level[16];
- data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
+ long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
if (p == sp_list[sp_depth]) {
sprintf(level, "#%02d", sp_depth++);
prompt = level;
@@ -252,7 +301,7 @@
end = ~7;
while (p <= end) {
- data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
+ long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
_LOG(tfd, (sp_depth > 2) || only_in_tombstone,
" %08x %08x %s\n", p, data,
map_to_name(map, data, ""));