static void dump_fault_addr(log_t* log, pid_t tid, int sig)
{
    siginfo_t si;

    memset(&si, 0, sizeof(si));
    if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
        _LOG(log, false, "cannot get siginfo: %s\n", strerror(errno));
    } else if (signal_has_address(sig)) {
        _LOG(log, false, "signal %d (%s), code %d (%s), fault addr %08x\n",
             sig, get_signame(sig),
             si.si_code, get_sigcode(sig, si.si_code),
             (uintptr_t) si.si_addr);
    } else {
        _LOG(log, false, "signal %d (%s), code %d (%s), fault addr --------\n",
             sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
    }
}
Beispiel #2
0
/*
 * If this isn't clearly a null pointer dereference, dump the
 * /proc/maps entries near the fault address.
 *
 * This only makes sense to do on the thread that crashed.
 */
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 for %d: %s\n",
            pid, 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");
    }
}