This is the mail archive of the gdb-prs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug gdb/15573] Decode fatal signals to show faulting address, access type, etc.


http://sourceware.org/bugzilla/show_bug.cgi?id=15573

--- Comment #3 from Andy Lutomirski <luto at mit dot edu> ---
It looks more or less like this.  I can provide some kind of license if it'll
be useful.

static void HandleFatalSignal(int sig, siginfo_t *info, void *context)
{
    /*
     * This is x86-specific and insanely poorly (wrongly?) documented.
     * I figured it by reading the kernel source.  --luto
     */
    struct ucontext *uc = (struct ucontext *)context;
    struct sigcontext *sc = (struct sigcontext *)&uc->uc_mcontext;

    psiginfo(info, "Caught fatal signal");

    std::cerr << "Dying due to fatal signal " << strsignal(sig)
              << " in pid " << getpid() << " / tid "
              << syscall(SYS_gettid) << std::endl;

    char causebuf[128];
    sprintf(causebuf, "code %d", info->si_code);

    const char *cause = causebuf;
    if (info->si_code == SI_USER)
        cause = "kill/raise";
    else if (info->si_code == SI_KERNEL)
        cause = "generic error from kernel";
    else if (info->si_code == SI_QUEUE)
        cause = "sigqueue";
    else if (info->si_code == SI_TKILL)
        cause = "tkill/tgkill";

    if (sig == SIGSEGV || sig == SIGBUS) {
        if (sig == SIGSEGV && info->si_code == SEGV_MAPERR)
            cause = "not mapped";
        else if (sig == SIGSEGV && info->si_code == SEGV_ACCERR)
            cause = "access error";
        else if (sig == SIGBUS && info->si_code == BUS_ADRALN)
            cause = "alignment error";
        else if (sig == SIGBUS && info->si_code == BUS_ADRERR)
            cause = "bad physical address";
        else if (sig == SIGBUS && info->si_code == BUS_OBJERR)
            cause = "object error";
        /* damnit, glibc
        else if (sig == SIGBUS && info->si_code == BUS_MCEERR_AR)
            cause = "mce; action required";
        else if (sig == SIGBUS && info->si_code == BUS_MCEERR_AO)
            cause = "mce; action optional";
        */

        void *cr2 = (void *)sc->cr2;

        // Decode the CPU error code (see Intel or AMD manual)
        const char *hw_reason = (sc->err & 1)
            ? "protection violation"
            : "page not present";
        const char *access_type;
        if (sc->err & 0x10)
            access_type = "executing from";
        else if (sc->err & 0x2)
            access_type = "writing to";
        else
            access_type = "reading from";

        std::cerr << "The error was \"" << cause << "\" at address "
                  << (void *)info->si_addr << ". The CPU reported "
                  << hw_reason << ' ' << access_type << ' '
                  << cr2 << '.' << std::endl;
    } else if (sig == SIGTRAP) {
        if (info->si_code == TRAP_BRKPT)
            cause = "breakpoint";
        else if (info->si_code == TRAP_TRACE)
            cause = "trace trap";
        /* damnit, glibc
        else if (info->si_code == TRAP_BRANCH)
            cause = "process taken branch trap";  // whatever that is...
        else if (info->si_code == TRAP_HWBKPT)
            cause = "hw breakpoint/watchpoint";
        */

        std::cerr << "The error was " << cause << std::endl;
    } else if (sig == SIGILL) {
        if (info->si_code == ILL_ILLOPC)
            cause = "illegal opcode";
        else if (info->si_code == ILL_ILLOPN)
            cause = "illegal operand";
        else if (info->si_code == ILL_ILLADR)
            cause = "illegal addressing mode";
        else if (info->si_code == ILL_ILLTRP)
            cause = "illegal trap";
        else if (info->si_code == ILL_PRVOPC)
            cause = "privileged opcode";
        else if (info->si_code == ILL_PRVREG)
            cause = "privileged register";  // not on x86...
        else if (info->si_code == ILL_COPROC)
            cause = "coprocessor error";  // yay '80s
        else if (info->si_code == ILL_BADSTK)
            cause = "internal stack error";

        std::cerr << "The error was " << cause << std::endl;
    } else {
        // TODO: We could also decode SIGFPE.

        std::cerr << "The error was " << cause << std::endl;
    }

#define SC(x) " " #x " = " << (void *)(uintptr_t)sc->x
    std::cerr << "Signal context:" << SC(rip) << '\n'
              << SC(rax) << SC(rbx) << SC(rcx) << SC(rdx) << '\n'
              << SC(rsi) << SC(rdi) << SC(rbp) << SC(rsp) << '\n'
              << SC(r8) << SC(r9) << SC(r10) << SC(r11) << '\n'
              << SC(r12) << SC(r13) << SC(r14) << SC(r15) << '\n'
              << SC(eflags) << SC(cs) << SC(gs) << SC(fs);
#undef SC
}

-- 
You are receiving this mail because:
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]