Merge "Enhance debuggerd memory dumps"

This commit is contained in:
Andy McFadden 2011-10-18 17:12:21 -07:00 committed by Android (Google) Code Review
commit 05a28e1cd4
1 changed files with 108 additions and 59 deletions

View File

@ -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, ""));