Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85e06657 authored by Andy McFadden's avatar Andy McFadden Committed by Android Git Automerger
Browse files

am 05a28e1c: Merge "Enhance debuggerd memory dumps"

* commit '05a28e1c':
  Enhance debuggerd memory dumps
parents 942cfefc 05a28e1c
Loading
Loading
Loading
Loading
+103 −54
Original line number Diff line number Diff line
@@ -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)
    }
}


void dump_stack_and_code(int tfd, int pid, mapinfo *map,
                         int unwind_depth, unsigned int sp_list[],
                         bool at_fault)
/*
 * 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)
{
    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");
    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 = pc & ~3;
    p = addr & ~3;
    p -= 32;
    if (p > pc)
    if (p > addr) {
        /* catch underflow */
        p = 0;
    }
    end = p + 80;
    /* 'end - p' has to be multiples of 16 */
    /* catch overflow; '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
     *  addr     contents                             ascii
     *  00008d34 ef000000 e8bd0090 e1b00000 512fff1e  ............../Q
     *  00008d44 ea00b1f9 e92d0090 e3a070fc ef000000  ......-..p......
     */
    while (p < end) {
        int i;
        char* asc_out = ascii_buffer;

        sprintf(code_buffer, "%08x ", p);

        int i;
        for (i = 0; i < 4; i++) {
            data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
            sprintf(code_buffer + strlen(code_buffer), "%08x ", data);
            /*
             * 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;
        }
        _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
        *asc_out = '\0';
        _LOG(tfd, only_in_tombstone, "%s %s\n", code_buffer, ascii_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;
void dump_stack_and_code(int tfd, int pid, mapinfo *map,
                         int unwind_depth, unsigned int sp_list[],
                         bool at_fault)
{
    struct pt_regs r;
    int sp_depth;
    bool only_in_tombstone = !at_fault;

    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return;

        /* 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, "\nmem near %.2s:\n",
                &REG_NAMES[reg*2]);
            dump_memory(tfd, pid, addr, false);
        }
            _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
    } 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, ""));