Merge "Enhance debuggerd memory dumps"
This commit is contained in:
commit
05a28e1cd4
|
@ -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",
|
||||
®_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, ""));
|
||||
|
|
Loading…
Reference in New Issue