summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValery Ushakov <uwe@stderr.spb.ru>2017-09-10 21:45:09 +0300
committerValery Ushakov <uwe@stderr.spb.ru>2017-09-10 21:45:09 +0300
commitbbdfd52b59f74b1228961d07e13fc4d83969de58 (patch)
treecf8fe8615a8a79c35c65ac069b3663b91dbead6f
parent8eba7b79fe0fd83319cc590b9f4a6c480863fd1b (diff)
Use SA_SIGINFO to report pc in error messages. Copied from Linux.
-rw-r--r--emu/NetBSD/os.c62
1 files changed, 34 insertions, 28 deletions
diff --git a/emu/NetBSD/os.c b/emu/NetBSD/os.c
index 34526088..3aa95975 100644
--- a/emu/NetBSD/os.c
+++ b/emu/NetBSD/os.c
@@ -13,6 +13,8 @@
#include "fns.h"
#include "error.h"
+#include "raise.h"
+
/* For dynamic linking init/fini code that needs malloc */
void (*coherence)(void) = nofence;
@@ -31,50 +33,49 @@ int gidnobody = -1;
int uidnobody = -1;
static struct termios tinit;
-/*
- * 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);
}
@@ -187,14 +188,19 @@ 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 = 0;
}
p = newproc();