summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/freebsd
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-04-08 18:15:30 -0700
committerRuss Cox <rsc@golang.org>2010-04-08 18:15:30 -0700
commit2d19c2d8f2a9d759ecfa73d07ed1bab66f8ac24f (patch)
tree9042a434db46b9ee490ca915723872f355fd60f2 /src/pkg/runtime/freebsd
parent1fa9a0c209f50aa6b8eac0755ce6ccd00ff2cf02 (diff)
downloadgolang-2d19c2d8f2a9d759ecfa73d07ed1bab66f8ac24f.tar.gz
runtime: turn divide by zero, nil dereference into panics
tested on linux/amd64, linux/386, linux/arm, darwin/amd64, darwin/386. freebsd untested; will finish in a separate CL. for now all the panics are errorStrings. richer structures can be added as necessary once the mechanism is shaked out. R=r CC=golang-dev http://codereview.appspot.com/906041
Diffstat (limited to 'src/pkg/runtime/freebsd')
-rw-r--r--src/pkg/runtime/freebsd/386/signal.c31
-rw-r--r--src/pkg/runtime/freebsd/amd64/signal.c31
-rw-r--r--src/pkg/runtime/freebsd/defs.c48
-rw-r--r--src/pkg/runtime/freebsd/signals.h10
-rw-r--r--src/pkg/runtime/freebsd/thread.c26
5 files changed, 126 insertions, 20 deletions
diff --git a/src/pkg/runtime/freebsd/386/signal.c b/src/pkg/runtime/freebsd/386/signal.c
index 3529d1a58..2483e7d90 100644
--- a/src/pkg/runtime/freebsd/386/signal.c
+++ b/src/pkg/runtime/freebsd/386/signal.c
@@ -48,7 +48,26 @@ void
sighandler(int32 sig, Siginfo* info, void* context)
{
Ucontext *uc;
- Mcontext *mc;
+ Mcontext *r;
+
+ uc = context;
+ r = &uc->uc_mcontext;
+
+ if((gp = m->curg) != nil && (sigtab[sig].flags & SigPanic)) {
+ // Make it look like a call to the signal func.
+ // Have to pass arguments out of band since
+ // augmenting the stack frame would break
+ // the unwinding code.
+ gp->sig = sig;
+ gp->sigcode0 = info->si_code;
+ gp->sigcode1 = (uintptr)info->si_addr;
+
+ sp = (uintptr*)r->mc_esp;
+ *--sp = r->mc_eip;
+ r->mc_eip = (uintptr)sigpanic;
+ r->mc_esp = (uintptr)sp;
+ return;
+ }
if(sigtab[sig].flags & SigQueue) {
if(sigsend(sig) || (sigtab[sig].flags & SigIgnore))
@@ -60,22 +79,18 @@ sighandler(int32 sig, Siginfo* info, void* context)
exit(2);
panicking = 1;
- uc = context;
- mc = &uc->uc_mcontext;
-
if(sig < 0 || sig >= NSIG)
printf("Signal %d\n", sig);
else
printf("%s\n", sigtab[sig].name);
- printf("Faulting address: %p\n", info->si_addr);
- printf("PC=%X\n", mc->mc_eip);
+ printf("PC=%X\n", r->mc_eip);
printf("\n");
if(gotraceback()){
- traceback((void*)mc->mc_eip, (void*)mc->mc_esp, 0, m->curg);
+ traceback((void*)r->mc_eip, (void*)r->mc_esp, 0, m->curg);
tracebackothers(m->curg);
- dumpregs(mc);
+ dumpregs(r);
}
breakpoint();
diff --git a/src/pkg/runtime/freebsd/amd64/signal.c b/src/pkg/runtime/freebsd/amd64/signal.c
index dc0e1eb58..ea15922c6 100644
--- a/src/pkg/runtime/freebsd/amd64/signal.c
+++ b/src/pkg/runtime/freebsd/amd64/signal.c
@@ -56,7 +56,26 @@ void
sighandler(int32 sig, Siginfo* info, void* context)
{
Ucontext *uc;
- Mcontext *mc;
+ Mcontext *r;
+
+ uc = context;
+ r = &uc->uc_mcontext;
+
+ if((gp = m->curg) != nil && (sigtab[sig].flags & SigPanic)) {
+ // Make it look like a call to the signal func.
+ // Have to pass arguments out of band since
+ // augmenting the stack frame would break
+ // the unwinding code.
+ gp->sig = sig;
+ gp->sigcode0 = info->si_code;
+ gp->sigcode1 = (uintptr)info->si_addr;
+
+ sp = (uintptr*)r->mc_rsp;
+ *--sp = r->mc_rip;
+ r->mc_rip = (uintptr)sigpanic;
+ r->mc_rsp = (uintptr)sp;
+ return;
+ }
if(sigtab[sig].flags & SigQueue) {
if(sigsend(sig) || (sigtab[sig].flags & SigIgnore))
@@ -68,21 +87,17 @@ sighandler(int32 sig, Siginfo* info, void* context)
exit(2);
panicking = 1;
- uc = context;
- mc = &uc->uc_mcontext;
-
if(sig < 0 || sig >= NSIG)
printf("Signal %d\n", sig);
else
printf("%s\n", sigtab[sig].name);
- printf("Faulting address: %p\n", info->si_addr);
- printf("PC=%X\n", mc->mc_rip);
+ printf("PC=%X\n", r->mc_rip);
printf("\n");
if(gotraceback()){
- traceback((void*)mc->mc_rip, (void*)mc->mc_rsp, 0, (void*)mc->mc_r15);
- tracebackothers((void*)mc->mc_r15);
+ traceback((void*)r->mc_rip, (void*)r->mc_rsp, 0, (void*)r->mc_r15);
+ tracebackothers((void*)r->mc_r15);
dumpregs(mc);
}
diff --git a/src/pkg/runtime/freebsd/defs.c b/src/pkg/runtime/freebsd/defs.c
index e4d0f0068..0c75e75c4 100644
--- a/src/pkg/runtime/freebsd/defs.c
+++ b/src/pkg/runtime/freebsd/defs.c
@@ -37,6 +37,54 @@ enum {
$UMTX_OP_WAKE = UMTX_OP_WAKE,
$EINTR = EINTR,
+
+ $SIGHUP = SIGHUP,
+ $SIGINT = SIGINT,
+ $SIGQUIT = SIGQUIT,
+ $SIGILL = SIGILL,
+ $SIGTRAP = SIGTRAP,
+ $SIGABRT = SIGABRT,
+ $SIGEMT = SIGEMT,
+ $SIGFPE = SIGFPE,
+ $SIGKILL = SIGKILL,
+ $SIGBUS = SIGBUS,
+ $SIGSEGV = SIGSEGV,
+ $SIGSYS = SIGSYS,
+ $SIGPIPE = SIGPIPE,
+ $SIGALRM = SIGALRM,
+ $SIGTERM = SIGTERM,
+ $SIGURG = SIGURG,
+ $SIGSTOP = SIGSTOP,
+ $SIGTSTP = SIGTSTP,
+ $SIGCONT = SIGCONT,
+ $SIGCHLD = SIGCHLD,
+ $SIGTTIN = SIGTTIN,
+ $SIGTTOU = SIGTTOU,
+ $SIGIO = SIGIO,
+ $SIGXCPU = SIGXCPU,
+ $SIGXFSZ = SIGXFSZ,
+ $SIGVTALRM = SIGVTALRM,
+ $SIGPROF = SIGPROF,
+ $SIGWINCH = SIGWINCH,
+ $SIGINFO = SIGINFO,
+ $SIGUSR1 = SIGUSR1,
+ $SIGUSR2 = SIGUSR2,
+
+ $FPE_INTDIV = FPE_INTDIV,
+ $FPE_INTOVF = FPE_INTOVF,
+ $FPE_FLTDIV = FPE_FLTDIV,
+ $FPE_FLTOVF = FPE_FLTOVF,
+ $FPE_FLTUND = FPE_FLTUND,
+ $FPE_FLTRES = FPE_FLTRES,
+ $FPE_FLTINV = FPE_FLTINV,
+ $FPE_FLTSUB = FPE_FLTSUB,
+
+ $BUS_ADRALN = BUS_ADRALN,
+ $BUS_ADRERR = BUS_ADRERR,
+ $BUS_OBJERR = BUS_OBJERR,
+
+ $SEGV_MAPERR = SEGV_MAPERR,
+ $SEGV_ACCERR = SEGV_ACCERR,
};
typedef struct rtprio $Rtprio;
diff --git a/src/pkg/runtime/freebsd/signals.h b/src/pkg/runtime/freebsd/signals.h
index 93ff7eb98..0c41daf84 100644
--- a/src/pkg/runtime/freebsd/signals.h
+++ b/src/pkg/runtime/freebsd/signals.h
@@ -6,8 +6,9 @@
#define I SigIgnore
#define R SigRestart
#define Q SigQueue
+#define P SigPanic
-static SigTab sigtab[] = {
+SigTab sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ Q+R, "SIGHUP: terminal line hangup",
/* 2 */ Q+R, "SIGINT: interrupt",
@@ -16,10 +17,10 @@ static SigTab sigtab[] = {
/* 5 */ C, "SIGTRAP: trace trap",
/* 6 */ C, "SIGABRT: abort",
/* 7 */ C, "SIGEMT: EMT instruction",
- /* 8 */ C, "SIGFPE: floating-point exception",
+ /* 8 */ C+P, "SIGFPE: floating-point exception",
/* 9 */ 0, "SIGKILL: kill",
- /* 10 */ C, "SIGBUS: bus error",
- /* 11 */ C, "SIGSEGV: segmentation violation",
+ /* 10 */ C+P, "SIGBUS: bus error",
+ /* 11 */ C+P, "SIGSEGV: segmentation violation",
/* 12 */ C, "SIGSYS: bad system call",
/* 13 */ I, "SIGPIPE: write to broken pipe",
/* 14 */ Q+I+R, "SIGALRM: alarm clock",
@@ -46,5 +47,6 @@ static SigTab sigtab[] = {
#undef I
#undef R
#undef Q
+#undef P
#define NSIG 33
diff --git a/src/pkg/runtime/freebsd/thread.c b/src/pkg/runtime/freebsd/thread.c
index 19c14c5ab..9ee21c592 100644
--- a/src/pkg/runtime/freebsd/thread.c
+++ b/src/pkg/runtime/freebsd/thread.c
@@ -6,6 +6,8 @@
#include "signals.h"
#include "os.h"
+extern SigTab sigtab[];
+
// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
// thus the code is largely similar. See linux/thread.c for comments.
@@ -169,3 +171,27 @@ minit(void)
m->gsignal = malg(32*1024);
signalstack(m->gsignal->stackguard, 32*1024);
}
+
+void
+sigpanic(void)
+{
+ switch(g->sig) {
+ case SIGBUS:
+ if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000)
+ panicstring("invalid memory address or nil pointer dereference");
+ break;
+ case SIGSEGV:
+ if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR) && g->sigcode1 < 0x1000)
+ panicstring("invalid memory address or nil pointer dereference");
+ break;
+ case SIGFPE:
+ switch(g->sigcode0) {
+ case FPE_INTDIV:
+ panicstring("integer divide by zero");
+ case FPE_INTOVF:
+ panicstring("integer overflow");
+ }
+ panicstring("floating point error");
+ }
+ panicstring(sigtab[g->sig].name);
+}