diff options
| author | forsyth <forsyth@vitanuova.com> | 2010-08-01 12:55:40 +0100 |
|---|---|---|
| committer | forsyth <forsyth@vitanuova.com> | 2010-08-01 12:55:40 +0100 |
| commit | 7781741266783e4df3b35d42a55e8e504838898b (patch) | |
| tree | dad0832f099405dc81e37e333443e88afc1c5923 /emu/Linux/os.c | |
| parent | ce8e0d607a2bec33fcaac7237d0b5535e5b152a1 (diff) | |
20100801
Diffstat (limited to 'emu/Linux/os.c')
| -rw-r--r-- | emu/Linux/os.c | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/emu/Linux/os.c b/emu/Linux/os.c index 86be1389..8db05f22 100644 --- a/emu/Linux/os.c +++ b/emu/Linux/os.c @@ -8,11 +8,15 @@ #include <sys/wait.h> #include <sys/time.h> +#include <stdint.h> + #include "dat.h" #include "fns.h" #include "error.h" #include <fpuctl.h> +#include <raise.h> + /* glibc 2.3.3-NTPL messes up getpid() by trying to cache the result, so we'll do it ourselves */ #include <sys/syscall.h> #define getpid() syscall(SYS_getpid) @@ -96,7 +100,7 @@ kproc(char *name, void (*func)(void*), void *arg, int flags) p = newproc(); if(0) - print("start %s:%.8lx\n", name, p); + print("start %s:%#p\n", name, p); if(p == nil) { print("kproc(%s): no memory", name); return; @@ -151,50 +155,49 @@ kproc(char *name, void (*func)(void*), void *arg, int flags) return 0; } -/* - * TO DO: - * To get pc on trap, use sigaction instead of signal and - * examine its siginfo structure - */ - -/* static void -diserr(char *s, int pc) +sysfault(char *what, void *addr) { - char buf[ERRMAX]; + char buf[64]; - snprint(buf, sizeof(buf), "%s: pc=0x%lux", s, pc); + snprint(buf, sizeof(buf), "sys: %s%#p", what, addr); disfault(nil, buf); } -*/ static void -trapILL(int signo) +trapILL(int signo, siginfo_t *si, void *a) { USED(signo); - disfault(nil, "Illegal instruction"); + USED(a); + sysfault("illegal instruction pc=", si->si_addr); } -static void -trapBUS(int signo) +static int +isnilref(siginfo_t *si) { - USED(signo); - disfault(nil, "Bus error"); + return si != 0 && (si->si_addr == (void*)~(uintptr_t)0 || (uintptr_t)si->si_addr < 512); } static void -trapSEGV(int signo) +trapmemref(int signo, siginfo_t *si, void *a) { - USED(signo); - disfault(nil, "Segmentation violation"); + USED(a); /* ucontext_t*, could fetch pc in machine-dependent way */ + if(isnilref(si)) + disfault(nil, exNilref); + else if(signo == SIGBUS) + sysfault("bad address addr=", si->si_addr); /* eg, misaligned */ + else + sysfault("segmentation violation addr=", si->si_addr); } static void -trapFPE(int signo) +trapFPE(int signo, siginfo_t *si, void *a) { char buf[64]; + USED(signo); - snprint(buf, sizeof(buf), "sys: fp: exception status=%.4lux", getfsr()); + USED(a); + snprint(buf, sizeof(buf), "sys: fp: exception status=%.4lux pc=%#p", getfsr(), si->si_addr); disfault(nil, buf); } @@ -348,14 +351,15 @@ libinit(char *imod) signal(SIGINT, cleanexit); if(sflag == 0) { - act.sa_handler = trapBUS; - sigaction(SIGBUS, &act, nil); - act.sa_handler = trapILL; + act.sa_flags = SA_SIGINFO; + act.sa_sigaction = trapILL; sigaction(SIGILL, &act, nil); - act.sa_handler = trapSEGV; - sigaction(SIGSEGV, &act, nil); - act.sa_handler = trapFPE; + act.sa_sigaction = trapFPE; sigaction(SIGFPE, &act, nil); + act.sa_sigaction = trapmemref; + sigaction(SIGBUS, &act, nil); + sigaction(SIGSEGV, &act, nil); + act.sa_flags &= ~SA_SIGINFO; } p = newproc(); |
