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

Commit 08df672a authored by Andy McFadden's avatar Andy McFadden Committed by Android Git Automerger
Browse files

am 90e6f931: Merge "Show maps near native fault address"

* commit '90e6f931':
  Show maps near native fault address
parents 42382429 90e6f931
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -50,6 +50,74 @@ extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map,
                                        int *frame0_pc_sane,
                                        bool at_fault);

/*
 * If this isn't clearly a null pointer dereference, dump the
 * /proc/maps entries near the fault address.
 */
static void show_nearby_maps(int tfd, int pid, mapinfo *map)
{
    siginfo_t si;

    memset(&si, 0, sizeof(si));
    if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) {
        _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno));
        return;
    }
    if (!signal_has_address(si.si_signo))
        return;

    uintptr_t addr = (uintptr_t) si.si_addr;
    addr &= ~0xfff;     /* round to 4K page boundary */
    if (addr == 0)      /* null-pointer deref */
        return;

    _LOG(tfd, false, "\nmemory map around addr %08x:\n", si.si_addr);

    /*
     * Search for a match, or for a hole where the match would be.  The list
     * is backward from the file content, so it starts at high addresses.
     */
    bool found = false;
    mapinfo *next = NULL;
    mapinfo *prev = NULL;
    while (map != NULL) {
        if (addr >= map->start && addr < map->end) {
            found = true;
            next = map->next;
            break;
        } else if (addr >= map->end) {
            /* map would be between "prev" and this entry */
            next = map;
            map = NULL;
            break;
        }

        prev = map;
        map = map->next;
    }

    /*
     * Show "next" then "match" then "prev" so that the addresses appear in
     * ascending order (like /proc/pid/maps).
     */
    if (next != NULL) {
        _LOG(tfd, false, "%08x-%08x %s\n", next->start, next->end, next->name);
    } else {
        _LOG(tfd, false, "(no map below)\n");
    }
    if (map != NULL) {
        _LOG(tfd, false, "%08x-%08x %s\n", map->start, map->end, map->name);
    } else {
        _LOG(tfd, false, "(no map for address)\n");
    }
    if (prev != NULL) {
        _LOG(tfd, false, "%08x-%08x %s\n", prev->start, prev->end, prev->name);
    } else {
        _LOG(tfd, false, "(no map above)\n");
    }
}


void dump_stack_and_code(int tfd, int pid, mapinfo *map,
                         int unwind_depth, unsigned int sp_list[],
                         bool at_fault)
@@ -123,6 +191,8 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map,
        }
    }

    show_nearby_maps(tfd, pid, map);

    p = sp - 64;
    if (p > sp)
        p = 0;
+20 −7
Original line number Diff line number Diff line
@@ -70,15 +70,18 @@ mapinfo *parse_maps_line(char *line)
    mapinfo *mi;
    int len = strlen(line);

    if(len < 1) return 0;
    if (len < 1) return 0;      /* not expected */
    line[--len] = 0;

    if(len < 50) return 0;
    if(line[20] != 'x') return 0;

    if (len < 50) {
        mi = malloc(sizeof(mapinfo) + 1);
    } else {
        mi = malloc(sizeof(mapinfo) + (len - 47));
    }
    if (mi == 0) return 0;

    mi->isExecutable = (line[20] == 'x');

    mi->start = strtoul(line, 0, 16);
    mi->end = strtoul(line + 9, 0, 16);
    /* To be filled in parse_elf_info if the mapped section starts with
@@ -87,7 +90,11 @@ mapinfo *parse_maps_line(char *line)
    mi->exidx_start = mi->exidx_end = 0;
    mi->symbols = 0;
    mi->next = 0;
    if (len < 50) {
        mi->name[0] = '\0';
    } else {
        strcpy(mi->name, line + 49);
    }

    return mi;
}
@@ -165,11 +172,14 @@ void dump_fault_addr(int tfd, int pid, int sig)
    memset(&si, 0, sizeof(si));
    if(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)){
        _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno));
    } else {
    } else if (signal_has_address(sig)) {
        _LOG(tfd, false, "signal %d (%s), code %d (%s), fault addr %08x\n",
             sig, get_signame(sig),
             si.si_code, get_sigcode(sig, si.si_code),
             si.si_addr);
    } else {
        _LOG(tfd, false, "signal %d (%s), code %d (%s), fault addr --------\n",
             sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
    }
}

@@ -199,6 +209,9 @@ static void parse_elf_info(mapinfo *milist, pid_t pid)
{
    mapinfo *mi;
    for (mi = milist; mi != NULL; mi = mi->next) {
        if (!mi->isExecutable)
            continue;

        Elf32_Ehdr ehdr;

        memset(&ehdr, 0, sizeof(Elf32_Ehdr));
+18 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

#include <sys/ptrace.h>
#include <sys/exec_elf.h>
#include <signal.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
@@ -82,3 +83,20 @@ const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc)
    }
    return NULL;
}

/*
 * Returns true if the specified signal has an associated address (i.e. it
 * sets siginfo_t.si_addr).
 */
bool signal_has_address(int sig)
{
    switch (sig) {
        case SIGILL:
        case SIGFPE:
        case SIGSEGV:
        case SIGBUS:
            return true;
        default:
            return false;
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ typedef struct mapinfo {
    unsigned exidx_start;
    unsigned exidx_end;
    struct symbol_table *symbols;
    bool isExecutable;
    char name[];
} mapinfo;

@@ -56,6 +57,9 @@ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def);
/* Log information onto the tombstone */
extern void _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...);

/* Determine whether si_addr is valid for this signal */
bool signal_has_address(int sig);

#define LOG(fmt...) _LOG(-1, 0, fmt)

/* Set to 1 for normal debug traces */