diff --git a/debuggerd/arm/machine.c b/debuggerd/arm/machine.c
index 58a7839bc..fb0d6baa5 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 @@ static void show_nearby_maps(int tfd, int pid, mapinfo *map)
     }
 }
 
+/*
+ * 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",
+                &REG_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 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map,
     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 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map,
         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, ""));