summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/darwin
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/darwin')
-rw-r--r--src/pkg/runtime/darwin/386/defs.h46
-rw-r--r--src/pkg/runtime/darwin/386/signal.c38
-rw-r--r--src/pkg/runtime/darwin/amd64/defs.h44
-rw-r--r--src/pkg/runtime/darwin/amd64/signal.c39
-rw-r--r--src/pkg/runtime/darwin/defs.c48
-rw-r--r--src/pkg/runtime/darwin/os.h1
-rw-r--r--src/pkg/runtime/darwin/signals.h10
-rw-r--r--src/pkg/runtime/darwin/thread.c25
8 files changed, 236 insertions, 15 deletions
diff --git a/src/pkg/runtime/darwin/386/defs.h b/src/pkg/runtime/darwin/386/defs.h
index b66a5d8b4..69ccc35f7 100644
--- a/src/pkg/runtime/darwin/386/defs.h
+++ b/src/pkg/runtime/darwin/386/defs.h
@@ -1,4 +1,4 @@
-// godefs -f -m32 defs.c
+// godefs defs.c
// MACHINE GENERATED - DO NOT EDIT.
@@ -44,6 +44,50 @@ enum {
SA_ONSTACK = 0x1,
SA_USERTRAMP = 0x100,
SA_64REGSET = 0x200,
+ SIGHUP = 0x1,
+ SIGINT = 0x2,
+ SIGQUIT = 0x3,
+ SIGILL = 0x4,
+ SIGTRAP = 0x5,
+ SIGABRT = 0x6,
+ SIGEMT = 0x7,
+ SIGFPE = 0x8,
+ SIGKILL = 0x9,
+ SIGBUS = 0xa,
+ SIGSEGV = 0xb,
+ SIGSYS = 0xc,
+ SIGPIPE = 0xd,
+ SIGALRM = 0xe,
+ SIGTERM = 0xf,
+ SIGURG = 0x10,
+ SIGSTOP = 0x11,
+ SIGTSTP = 0x12,
+ SIGCONT = 0x13,
+ SIGCHLD = 0x14,
+ SIGTTIN = 0x15,
+ SIGTTOU = 0x16,
+ SIGIO = 0x17,
+ SIGXCPU = 0x18,
+ SIGXFSZ = 0x19,
+ SIGVTALRM = 0x1a,
+ SIGPROF = 0x1b,
+ SIGWINCH = 0x1c,
+ SIGINFO = 0x1d,
+ SIGUSR1 = 0x1e,
+ SIGUSR2 = 0x1f,
+ FPE_INTDIV = 0x7,
+ FPE_INTOVF = 0x8,
+ FPE_FLTDIV = 0x1,
+ FPE_FLTOVF = 0x2,
+ FPE_FLTUND = 0x3,
+ FPE_FLTRES = 0x4,
+ FPE_FLTINV = 0x5,
+ FPE_FLTSUB = 0x6,
+ BUS_ADRALN = 0x1,
+ BUS_ADRERR = 0x2,
+ BUS_OBJERR = 0x3,
+ SEGV_MAPERR = 0x1,
+ SEGV_ACCERR = 0x2,
};
// Types
diff --git a/src/pkg/runtime/darwin/386/signal.c b/src/pkg/runtime/darwin/386/signal.c
index 6fe5f308f..65c217b4e 100644
--- a/src/pkg/runtime/darwin/386/signal.c
+++ b/src/pkg/runtime/darwin/386/signal.c
@@ -39,6 +39,39 @@ sighandler(int32 sig, Siginfo *info, void *context)
Ucontext *uc;
Mcontext *mc;
Regs *r;
+ uintptr *sp;
+ void (*fn)(void);
+ G *gp;
+ byte *pc;
+
+ uc = context;
+ mc = uc->uc_mcontext;
+ r = &mc->ss;
+
+ if((gp = m->curg) != nil && (sigtab[sig].flags & SigPanic)) {
+ // Work around Leopard bug that doesn't set FPE_INTDIV.
+ // Look at instruction to see if it is a divide.
+ // Not necessary in Snow Leopard (si_code will be != 0).
+ if(sig == SIGFPE && info->si_code == 0) {
+ pc = (byte*)r->eip;
+ if(pc[0] == 0xF7)
+ info->si_code = FPE_INTDIV;
+ }
+
+ // 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->esp;
+ *--sp = r->eip;
+ r->eip = (uintptr)sigpanic;
+ r->esp = (uintptr)sp;
+ return;
+ }
if(sigtab[sig].flags & SigQueue) {
if(sigsend(sig) || (sigtab[sig].flags & SigIgnore))
@@ -56,11 +89,6 @@ sighandler(int32 sig, Siginfo *info, void *context)
printf("%s\n", sigtab[sig].name);
}
- uc = context;
- mc = uc->uc_mcontext;
- r = &mc->ss;
-
- printf("Faulting address: %p\n", info->si_addr);
printf("pc: %x\n", r->eip);
printf("\n");
diff --git a/src/pkg/runtime/darwin/amd64/defs.h b/src/pkg/runtime/darwin/amd64/defs.h
index 1076e4c10..0b5fde85c 100644
--- a/src/pkg/runtime/darwin/amd64/defs.h
+++ b/src/pkg/runtime/darwin/amd64/defs.h
@@ -44,6 +44,50 @@ enum {
SA_ONSTACK = 0x1,
SA_USERTRAMP = 0x100,
SA_64REGSET = 0x200,
+ SIGHUP = 0x1,
+ SIGINT = 0x2,
+ SIGQUIT = 0x3,
+ SIGILL = 0x4,
+ SIGTRAP = 0x5,
+ SIGABRT = 0x6,
+ SIGEMT = 0x7,
+ SIGFPE = 0x8,
+ SIGKILL = 0x9,
+ SIGBUS = 0xa,
+ SIGSEGV = 0xb,
+ SIGSYS = 0xc,
+ SIGPIPE = 0xd,
+ SIGALRM = 0xe,
+ SIGTERM = 0xf,
+ SIGURG = 0x10,
+ SIGSTOP = 0x11,
+ SIGTSTP = 0x12,
+ SIGCONT = 0x13,
+ SIGCHLD = 0x14,
+ SIGTTIN = 0x15,
+ SIGTTOU = 0x16,
+ SIGIO = 0x17,
+ SIGXCPU = 0x18,
+ SIGXFSZ = 0x19,
+ SIGVTALRM = 0x1a,
+ SIGPROF = 0x1b,
+ SIGWINCH = 0x1c,
+ SIGINFO = 0x1d,
+ SIGUSR1 = 0x1e,
+ SIGUSR2 = 0x1f,
+ FPE_INTDIV = 0x7,
+ FPE_INTOVF = 0x8,
+ FPE_FLTDIV = 0x1,
+ FPE_FLTOVF = 0x2,
+ FPE_FLTUND = 0x3,
+ FPE_FLTRES = 0x4,
+ FPE_FLTINV = 0x5,
+ FPE_FLTSUB = 0x6,
+ BUS_ADRALN = 0x1,
+ BUS_ADRERR = 0x2,
+ BUS_OBJERR = 0x3,
+ SEGV_MAPERR = 0x1,
+ SEGV_ACCERR = 0x2,
};
// Types
diff --git a/src/pkg/runtime/darwin/amd64/signal.c b/src/pkg/runtime/darwin/amd64/signal.c
index beb55decf..9c4f0dc14 100644
--- a/src/pkg/runtime/darwin/amd64/signal.c
+++ b/src/pkg/runtime/darwin/amd64/signal.c
@@ -47,6 +47,40 @@ sighandler(int32 sig, Siginfo *info, void *context)
Ucontext *uc;
Mcontext *mc;
Regs *r;
+ G *gp;
+ uintptr *sp;
+ byte *pc;
+
+ uc = context;
+ mc = uc->uc_mcontext;
+ r = &mc->ss;
+
+ if((gp = m->curg) != nil && (sigtab[sig].flags & SigPanic)) {
+ // Work around Leopard bug that doesn't set FPE_INTDIV.
+ // Look at instruction to see if it is a divide.
+ // Not necessary in Snow Leopard (si_code will be != 0).
+ if(sig == SIGFPE && info->si_code == 0) {
+ pc = (byte*)r->rip;
+ if((pc[0]&0xF0) == 0x40) // 64-bit REX prefix
+ pc++;
+ if(pc[0] == 0xF7)
+ info->si_code = FPE_INTDIV;
+ }
+
+ // 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->rsp;
+ *--sp = r->rip;
+ r->rip = (uintptr)sigpanic;
+ r->rsp = (uintptr)sp;
+ return;
+ }
if(sigtab[sig].flags & SigQueue) {
if(sigsend(sig) || (sigtab[sig].flags & SigIgnore))
@@ -64,11 +98,6 @@ sighandler(int32 sig, Siginfo *info, void *context)
printf("%s\n", sigtab[sig].name);
}
- uc = context;
- mc = uc->uc_mcontext;
- r = &mc->ss;
-
- printf("Faulting address: %p\n", info->si_addr);
printf("pc: %X\n", r->rip);
printf("\n");
diff --git a/src/pkg/runtime/darwin/defs.c b/src/pkg/runtime/darwin/defs.c
index 1ed662957..95edf7bb1 100644
--- a/src/pkg/runtime/darwin/defs.c
+++ b/src/pkg/runtime/darwin/defs.c
@@ -67,6 +67,54 @@ enum {
$SA_ONSTACK = SA_ONSTACK,
$SA_USERTRAMP = SA_USERTRAMP,
$SA_64REGSET = SA_64REGSET,
+
+ $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 mach_msg_body_t $MachBody;
diff --git a/src/pkg/runtime/darwin/os.h b/src/pkg/runtime/darwin/os.h
index 2e493aed0..24496485c 100644
--- a/src/pkg/runtime/darwin/os.h
+++ b/src/pkg/runtime/darwin/os.h
@@ -22,3 +22,4 @@ void sigaction(uintptr, struct Sigaction*, struct Sigaction*);
struct StackT;
void sigaltstack(struct StackT*, struct StackT*);
void sigtramp(void);
+void sigpanic(void);
diff --git a/src/pkg/runtime/darwin/signals.h b/src/pkg/runtime/darwin/signals.h
index c93e7fbe9..ac9e5d606 100644
--- a/src/pkg/runtime/darwin/signals.h
+++ b/src/pkg/runtime/darwin/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", /* used by panic and array out of bounds, etc. */
/* 6 */ C, "SIGABRT: abort",
/* 7 */ C, "SIGEMT: emulate instruction executed",
- /* 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",
@@ -45,5 +46,6 @@ static SigTab sigtab[] = {
#undef I
#undef R
#undef Q
+#undef P
#define NSIG 32
diff --git a/src/pkg/runtime/darwin/thread.c b/src/pkg/runtime/darwin/thread.c
index 38e3c23fb..d9acfa8d3 100644
--- a/src/pkg/runtime/darwin/thread.c
+++ b/src/pkg/runtime/darwin/thread.c
@@ -6,6 +6,8 @@
#include "defs.h"
#include "os.h"
+extern SigTab sigtab[];
+
static void
unimplemented(int8 *name)
{
@@ -443,3 +445,26 @@ mach_semrelease(uint32 sem)
}
}
+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);
+}