]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: turn divide by zero, nil dereference into panics
authorRuss Cox <rsc@golang.org>
Fri, 9 Apr 2010 01:15:30 +0000 (18:15 -0700)
committerRuss Cox <rsc@golang.org>
Fri, 9 Apr 2010 01:15:30 +0000 (18:15 -0700)
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
https://golang.org/cl/906041

28 files changed:
src/pkg/runtime/darwin/386/defs.h
src/pkg/runtime/darwin/386/signal.c
src/pkg/runtime/darwin/amd64/defs.h
src/pkg/runtime/darwin/amd64/signal.c
src/pkg/runtime/darwin/defs.c
src/pkg/runtime/darwin/os.h
src/pkg/runtime/darwin/signals.h
src/pkg/runtime/darwin/thread.c
src/pkg/runtime/freebsd/386/signal.c
src/pkg/runtime/freebsd/amd64/signal.c
src/pkg/runtime/freebsd/defs.c
src/pkg/runtime/freebsd/signals.h
src/pkg/runtime/freebsd/thread.c
src/pkg/runtime/linux/386/defs.h
src/pkg/runtime/linux/386/signal.c
src/pkg/runtime/linux/amd64/defs.h
src/pkg/runtime/linux/amd64/signal.c
src/pkg/runtime/linux/arm/defs.h
src/pkg/runtime/linux/arm/signal.c
src/pkg/runtime/linux/defs.c
src/pkg/runtime/linux/defs1.c
src/pkg/runtime/linux/defs2.c
src/pkg/runtime/linux/defs_arm.c
src/pkg/runtime/linux/os.h
src/pkg/runtime/linux/signals.h
src/pkg/runtime/linux/thread.c
src/pkg/runtime/runtime.h
test/recover3.go [new file with mode: 0644]

index b66a5d8b4ec57378c43c4fb80ef1ac8cdaefb3c6..69ccc35f7d7842bfc00d54c883856d2678ec08df 100644 (file)
@@ -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
index 6fe5f308fe66ea384205f81b94bb5b913093715d..65c217b4e0ea171b7eb4919d909f784b8db5d400 100644 (file)
@@ -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");
 
index 1076e4c10a4eda86a379486d4c00e39262f8cfc0..0b5fde85ca4deaa086c7cecea9446f418dc7921d 100644 (file)
@@ -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
index beb55decf63d2b85f81af8714140b29575219a9d..9c4f0dc147e5f89e479760b3b0a61413b78f0e07 100644 (file)
@@ -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");
 
index 1ed662957fa259026f704129f74c7b0add068d37..95edf7bb104146021b8bd44c02703a4204768303 100644 (file)
@@ -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;
index 2e493aed05efb9dc21b0e62de1bdae03b263001c..24496485c43da3e9ad09e0d686cecb705149446d 100644 (file)
@@ -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);
index c93e7fbe9b09f9b86ac69566bb7add6342bcf938..ac9e5d6066ee36b5cb5e376e3301b8b6a04343d8 100644 (file)
@@ -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
index 38e3c23fb2969063c7456f688dc221aa4262660f..d9acfa8d30697d17393051702207b814dca50cdd 100644 (file)
@@ -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);
+}
index 3529d1a58bd3ac61c1f3a47df28d1073eb8792ba..2483e7d9070ecb183cfab4ef58b12f0c286eb8e3 100644 (file)
@@ -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();
index dc0e1eb586f0704a3f7543e6a77117177c107a7a..ea15922c62961f4fc330682cee7ffffb6543ac5a 100644 (file)
@@ -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);
        }
 
index e4d0f0068cbdb456df52a4f6748bde16fee1b074..0c75e75c4ce459c08768d33c30fd23ccf799dad5 100644 (file)
@@ -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;
index 93ff7eb98122f416006cff354827c75ea09caa7d..0c41daf844d08a69b0d93bd85af24206e900f6d4 100644 (file)
@@ -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
index 19c14c5abe1628b03b3d78f33f8a2a2de40692df..9ee21c59244d5e2f722d5e7e32d601bd5aefcf75 100644 (file)
@@ -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);
+}
index 94bc2b5b6f82b1207113bc13c2af34edf8849203..ef8ef05d0379982b8b20ef60e505449598d59a7a 100644 (file)
@@ -1,4 +1,4 @@
-// godefs -f -m32 -f -D_LOOSE_KERNEL_NAMES -f -D__ARCH_SI_UID_T=__kernel_uid32_t defs2.c
+// godefs -f -m32 -f -I/home/rsc/pub/linux-2.6/arch/x86/include -f -I/home/rsc/pub/linux-2.6/include -f -D_LOOSE_KERNEL_NAMES -f -D__ARCH_SI_UID_T=__kernel_uid32_t defs2.c
 
 // MACHINE GENERATED - DO NOT EDIT.
 
@@ -14,6 +14,49 @@ enum {
        SA_ONSTACK = 0x8000000,
        SA_RESTORER = 0x4000000,
        SA_SIGINFO = 0x4,
+       SIGHUP = 0x1,
+       SIGINT = 0x2,
+       SIGQUIT = 0x3,
+       SIGILL = 0x4,
+       SIGTRAP = 0x5,
+       SIGABRT = 0x6,
+       SIGBUS = 0x7,
+       SIGFPE = 0x8,
+       SIGKILL = 0x9,
+       SIGUSR1 = 0xa,
+       SIGSEGV = 0xb,
+       SIGUSR2 = 0xc,
+       SIGPIPE = 0xd,
+       SIGALRM = 0xe,
+       SIGSTKFLT = 0x10,
+       SIGCHLD = 0x11,
+       SIGCONT = 0x12,
+       SIGSTOP = 0x13,
+       SIGTSTP = 0x14,
+       SIGTTIN = 0x15,
+       SIGTTOU = 0x16,
+       SIGURG = 0x17,
+       SIGXCPU = 0x18,
+       SIGXFSZ = 0x19,
+       SIGVTALRM = 0x1a,
+       SIGPROF = 0x1b,
+       SIGWINCH = 0x1c,
+       SIGIO = 0x1d,
+       SIGPWR = 0x1e,
+       SIGSYS = 0x1f,
+       FPE_INTDIV = 0x1,
+       FPE_INTOVF = 0x2,
+       FPE_FLTDIV = 0x3,
+       FPE_FLTOVF = 0x4,
+       FPE_FLTUND = 0x5,
+       FPE_FLTRES = 0x6,
+       FPE_FLTINV = 0x7,
+       FPE_FLTSUB = 0x8,
+       BUS_ADRALN = 0x1,
+       BUS_ADRERR = 0x2,
+       BUS_OBJERR = 0x3,
+       SEGV_MAPERR = 0x1,
+       SEGV_ACCERR = 0x2,
 };
 
 // Types
index 87e6779b5e771b802e6f7f6badc2efd940d4d40c..fed052f63ede6fa76b6efefe14eb2bc1a8879a00 100644 (file)
@@ -45,7 +45,28 @@ void
 sighandler(int32 sig, Siginfo* info, void* context)
 {
        Ucontext *uc;
-       Sigcontext *sc;
+       Sigcontext *r;
+       uintptr *sp;
+       G *gp;
+
+       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)[3];
+
+               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))
@@ -57,22 +78,18 @@ sighandler(int32 sig, Siginfo* info, void* context)
                exit(2);
        panicking = 1;
 
-       uc = context;
-       sc = &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", *(void**)info->_sifields);
-       printf("PC=%X\n", sc->eip);
+       printf("PC=%X\n", r->eip);
        printf("\n");
 
        if(gotraceback()){
-               traceback((void*)sc->eip, (void*)sc->esp, 0, m->curg);
+               traceback((void*)r->eip, (void*)r->esp, 0, m->curg);
                tracebackothers(m->curg);
-               dumpregs(sc);
+               dumpregs(r);
        }
 
        breakpoint();
index 43b0475239f92358850199cdc1e3fef3d94613f4..c08e6b25d197293d5adaf858184ae29ea158bfc6 100644 (file)
@@ -14,6 +14,49 @@ enum {
        SA_ONSTACK = 0x8000000,
        SA_RESTORER = 0x4000000,
        SA_SIGINFO = 0x4,
+       SIGHUP = 0x1,
+       SIGINT = 0x2,
+       SIGQUIT = 0x3,
+       SIGILL = 0x4,
+       SIGTRAP = 0x5,
+       SIGABRT = 0x6,
+       SIGBUS = 0x7,
+       SIGFPE = 0x8,
+       SIGKILL = 0x9,
+       SIGUSR1 = 0xa,
+       SIGSEGV = 0xb,
+       SIGUSR2 = 0xc,
+       SIGPIPE = 0xd,
+       SIGALRM = 0xe,
+       SIGSTKFLT = 0x10,
+       SIGCHLD = 0x11,
+       SIGCONT = 0x12,
+       SIGSTOP = 0x13,
+       SIGTSTP = 0x14,
+       SIGTTIN = 0x15,
+       SIGTTOU = 0x16,
+       SIGURG = 0x17,
+       SIGXCPU = 0x18,
+       SIGXFSZ = 0x19,
+       SIGVTALRM = 0x1a,
+       SIGPROF = 0x1b,
+       SIGWINCH = 0x1c,
+       SIGIO = 0x1d,
+       SIGPWR = 0x1e,
+       SIGSYS = 0x1f,
+       FPE_INTDIV = 0x1,
+       FPE_INTOVF = 0x2,
+       FPE_FLTDIV = 0x3,
+       FPE_FLTOVF = 0x4,
+       FPE_FLTUND = 0x5,
+       FPE_FLTRES = 0x6,
+       FPE_FLTINV = 0x7,
+       FPE_FLTSUB = 0x8,
+       BUS_ADRALN = 0x1,
+       BUS_ADRERR = 0x2,
+       BUS_OBJERR = 0x3,
+       SEGV_MAPERR = 0x1,
+       SEGV_ACCERR = 0x2,
 };
 
 // Types
@@ -116,6 +159,12 @@ struct Fpstate1 {
        uint32 padding[24];
 };
 
+typedef struct Fpreg1 Fpreg1;
+struct Fpreg1 {
+       uint16 significand[4];
+       uint16 exponent;
+};
+
 typedef struct Sigaltstack Sigaltstack;
 struct Sigaltstack {
        void *ss_sp;
index 87a5a638b3053b5bb397683b0fb48072ee71f5fd..57cdea1322a91a1df1fe6ec3589a909225ff4a16 100644 (file)
@@ -54,7 +54,29 @@ sighandler(int32 sig, Siginfo* info, void* context)
 {
        Ucontext *uc;
        Mcontext *mc;
-       Sigcontext *sc;
+       Sigcontext *r;
+       uintptr *sp;
+       G *gp;
+
+       uc = context;
+       mc = &uc->uc_mcontext;
+       r = (Sigcontext*)mc;    // same layout, more conveient names
+
+       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)[2];
+
+               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))
@@ -66,23 +88,18 @@ sighandler(int32 sig, Siginfo* info, void* context)
                exit(2);
        panicking = 1;
 
-       uc = context;
-       mc = &uc->uc_mcontext;
-       sc = (Sigcontext*)mc;   // same layout, more conveient names
-
        if(sig < 0 || sig >= NSIG)
                printf("Signal %d\n", sig);
        else
                printf("%s\n", sigtab[sig].name);
 
-       printf("Faulting address: %p\n", *(void**)info->_sifields);
-       printf("PC=%X\n", sc->rip);
+       printf("PC=%X\n", r->rip);
        printf("\n");
 
        if(gotraceback()){
-               traceback((void*)sc->rip, (void*)sc->rsp, 0, (void*)sc->r15);
-               tracebackothers((void*)sc->r15);
-               dumpregs(sc);
+               traceback((void*)r->rip, (void*)r->rsp, 0, (void*)r->r15);
+               tracebackothers((void*)r->r15);
+               dumpregs(r);
        }
 
        breakpoint();
index 2159831588f5711bdff1f217aab907759985d870..b139851715689f8e0607a43b2a92a8fc6a7c06ba 100644 (file)
@@ -14,6 +14,49 @@ enum {
        SA_ONSTACK = 0x8000000,
        SA_RESTORER = 0x4000000,
        SA_SIGINFO = 0x4,
+       SIGHUP = 0x1,
+       SIGINT = 0x2,
+       SIGQUIT = 0x3,
+       SIGILL = 0x4,
+       SIGTRAP = 0x5,
+       SIGABRT = 0x6,
+       SIGBUS = 0x7,
+       SIGFPE = 0x8,
+       SIGKILL = 0x9,
+       SIGUSR1 = 0xa,
+       SIGSEGV = 0xb,
+       SIGUSR2 = 0xc,
+       SIGPIPE = 0xd,
+       SIGALRM = 0xe,
+       SIGSTKFLT = 0x10,
+       SIGCHLD = 0x11,
+       SIGCONT = 0x12,
+       SIGSTOP = 0x13,
+       SIGTSTP = 0x14,
+       SIGTTIN = 0x15,
+       SIGTTOU = 0x16,
+       SIGURG = 0x17,
+       SIGXCPU = 0x18,
+       SIGXFSZ = 0x19,
+       SIGVTALRM = 0x1a,
+       SIGPROF = 0x1b,
+       SIGWINCH = 0x1c,
+       SIGIO = 0x1d,
+       SIGPWR = 0x1e,
+       SIGSYS = 0x1f,
+       FPE_INTDIV = 0x30001,
+       FPE_INTOVF = 0x30002,
+       FPE_FLTDIV = 0x30003,
+       FPE_FLTOVF = 0x30004,
+       FPE_FLTUND = 0x30005,
+       FPE_FLTRES = 0x30006,
+       FPE_FLTINV = 0x30007,
+       FPE_FLTSUB = 0x30008,
+       BUS_ADRALN = 0x30001,
+       BUS_ADRERR = 0x30002,
+       BUS_OBJERR = 0x30003,
+       SEGV_MAPERR = 0x30001,
+       SEGV_ACCERR = 0x30002,
 };
 
 // Types
index d1d8bc08c7b817e0d573721cae4d31f33c20e4e1..6cc4ac9bea48e5961e9d79d8185a0759a04191e4 100644 (file)
@@ -53,7 +53,27 @@ void
 sighandler(int32 sig, Siginfo *info, void *context)
 {
        Ucontext *uc;
-       Sigcontext *sc;
+       Sigcontext *r;
+       G *gp;
+
+       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 = r->fault_address;
+
+               // If this is a leaf function, we do smash LR,
+               // but we're not going back there anyway.
+               r->arm_lr = r->arm_pc;
+               r->arm_pc = (uintptr)sigpanic;
+               return;
+       }
 
        if(sigtab[sig].flags & SigQueue) {
                if(sigsend(sig) || (sigtab[sig].flags & SigIgnore))
@@ -70,18 +90,14 @@ sighandler(int32 sig, Siginfo *info, void *context)
        else
                printf("%s\n", sigtab[sig].name);
 
-       uc = context;
-       sc = &uc->uc_mcontext;
-
-       printf("Faulting address: %p\n", sc->fault_address);
-       printf("PC=%x\n", sc->arm_pc);
+       printf("PC=%x\n", r->arm_pc);
        printf("\n");
 
        if(gotraceback()){
-               traceback((void*)sc->arm_pc, (void*)sc->arm_sp, (void*)sc->arm_lr, m->curg);
+               traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, m->curg);
                tracebackothers(m->curg);
                printf("\n");
-               dumpregs(sc);
+               dumpregs(r);
        }
 
 //     breakpoint();
index 35fa029532fc8c85f9ae5b66d126a681ced18c94..f3bdb61fa298872343bfd301ae65282e182b0f4b 100644 (file)
@@ -32,6 +32,53 @@ enum {
        $SA_ONSTACK = SA_ONSTACK,
        $SA_RESTORER = SA_RESTORER,
        $SA_SIGINFO = SA_SIGINFO,
+       
+       $SIGHUP = SIGHUP,
+       $SIGINT = SIGINT,
+       $SIGQUIT = SIGQUIT,
+       $SIGILL = SIGILL,
+       $SIGTRAP = SIGTRAP,
+       $SIGABRT = SIGABRT,
+       $SIGBUS = SIGBUS,
+       $SIGFPE = SIGFPE,
+       $SIGKILL = SIGKILL,
+       $SIGUSR1 = SIGUSR1,
+       $SIGSEGV = SIGSEGV,
+       $SIGUSR2 = SIGUSR2,
+       $SIGPIPE = SIGPIPE,
+       $SIGALRM = SIGALRM,
+       $SIGSTKFLT = SIGSTKFLT,
+       $SIGCHLD = SIGCHLD,
+       $SIGCONT = SIGCONT,
+       $SIGSTOP = SIGSTOP,
+       $SIGTSTP = SIGTSTP,
+       $SIGTTIN = SIGTTIN,
+       $SIGTTOU = SIGTTOU,
+       $SIGURG = SIGURG,
+       $SIGXCPU = SIGXCPU,
+       $SIGXFSZ = SIGXFSZ,
+       $SIGVTALRM = SIGVTALRM,
+       $SIGPROF = SIGPROF,
+       $SIGWINCH = SIGWINCH,
+       $SIGIO = SIGIO,
+       $SIGPWR = SIGPWR,
+       $SIGSYS = SIGSYS,
+       
+       $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 timespec $Timespec;
index 0fe3506ad60ff923cac047403a0c580b64c0b775..e737f8e9ef144ba2940daa74930f248a62dcae30 100644 (file)
@@ -14,7 +14,6 @@ typedef __sigset_t $Usigset;
 typedef struct _libc_fpxreg $Fpxreg;
 typedef struct _libc_xmmreg $Xmmreg;
 typedef struct _libc_fpstate $Fpstate;
-typedef struct _libc_fpreg $Fpreg;
 typedef struct _fpxreg $Fpxreg1;
 typedef struct _xmmreg $Xmmreg1;
 typedef struct _fpstate $Fpstate1;
index a91086aa5026bb0472643683996598c0bd2bead0..4cfe4a7ed0114c52aa9bae7d667e8bf729649e6a 100644 (file)
@@ -4,7 +4,12 @@
 
 /*
  * Input to godefs
-       godefs -f -m32 -f -I/home/rsc/pub/linux-2.6/arch/x86/include -f -I/home/rsc/pub/linux-2.6/include defs2.c >386/defs.h
+       godefs -f -m32 \
+               -f -I/home/rsc/pub/linux-2.6/arch/x86/include \
+               -f -I/home/rsc/pub/linux-2.6/include \
+               -f -D_LOOSE_KERNEL_NAMES \
+               -f -D__ARCH_SI_UID_T=__kernel_uid32_t \
+               defs2.c >386/defs.h
 
  * The asm header tricks we have to use for Linux on amd64
  * (see defs.c and defs1.c) don't work here, so this is yet another
@@ -47,6 +52,53 @@ enum {
        $SA_ONSTACK = SA_ONSTACK,
        $SA_RESTORER = SA_RESTORER,
        $SA_SIGINFO = SA_SIGINFO,
+
+       $SIGHUP = SIGHUP,
+       $SIGINT = SIGINT,
+       $SIGQUIT = SIGQUIT,
+       $SIGILL = SIGILL,
+       $SIGTRAP = SIGTRAP,
+       $SIGABRT = SIGABRT,
+       $SIGBUS = SIGBUS,
+       $SIGFPE = SIGFPE,
+       $SIGKILL = SIGKILL,
+       $SIGUSR1 = SIGUSR1,
+       $SIGSEGV = SIGSEGV,
+       $SIGUSR2 = SIGUSR2,
+       $SIGPIPE = SIGPIPE,
+       $SIGALRM = SIGALRM,
+       $SIGSTKFLT = SIGSTKFLT,
+       $SIGCHLD = SIGCHLD,
+       $SIGCONT = SIGCONT,
+       $SIGSTOP = SIGSTOP,
+       $SIGTSTP = SIGTSTP,
+       $SIGTTIN = SIGTTIN,
+       $SIGTTOU = SIGTTOU,
+       $SIGURG = SIGURG,
+       $SIGXCPU = SIGXCPU,
+       $SIGXFSZ = SIGXFSZ,
+       $SIGVTALRM = SIGVTALRM,
+       $SIGPROF = SIGPROF,
+       $SIGWINCH = SIGWINCH,
+       $SIGIO = SIGIO,
+       $SIGPWR = SIGPWR,
+       $SIGSYS = SIGSYS,
+       
+       $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 _fpreg $Fpreg;
index 01d6bfcdc14f219e2ce22f33d03290e873511e33..2b197272c687c2a6dd90105f1739ac16041db98f 100644 (file)
@@ -35,7 +35,54 @@ enum {
        $SA_RESTART = SA_RESTART,
        $SA_ONSTACK = SA_ONSTACK,
        $SA_RESTORER = SA_RESTORER,
-       $SA_SIGINFO = SA_SIGINFO
+       $SA_SIGINFO = SA_SIGINFO,
+
+       $SIGHUP = SIGHUP,
+       $SIGINT = SIGINT,
+       $SIGQUIT = SIGQUIT,
+       $SIGILL = SIGILL,
+       $SIGTRAP = SIGTRAP,
+       $SIGABRT = SIGABRT,
+       $SIGBUS = SIGBUS,
+       $SIGFPE = SIGFPE,
+       $SIGKILL = SIGKILL,
+       $SIGUSR1 = SIGUSR1,
+       $SIGSEGV = SIGSEGV,
+       $SIGUSR2 = SIGUSR2,
+       $SIGPIPE = SIGPIPE,
+       $SIGALRM = SIGALRM,
+       $SIGSTKFLT = SIGSTKFLT,
+       $SIGCHLD = SIGCHLD,
+       $SIGCONT = SIGCONT,
+       $SIGSTOP = SIGSTOP,
+       $SIGTSTP = SIGTSTP,
+       $SIGTTIN = SIGTTIN,
+       $SIGTTOU = SIGTTOU,
+       $SIGURG = SIGURG,
+       $SIGXCPU = SIGXCPU,
+       $SIGXFSZ = SIGXFSZ,
+       $SIGVTALRM = SIGVTALRM,
+       $SIGPROF = SIGPROF,
+       $SIGWINCH = SIGWINCH,
+       $SIGIO = SIGIO,
+       $SIGPWR = SIGPWR,
+       $SIGSYS = SIGSYS,
+       
+       $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 sigset_t $Sigset;
index 387fd43215dd2c0597fd7504c35afb63c1d0dde0..8ca26b7486d15e2272530422cd92b9b120c1c058 100644 (file)
@@ -10,3 +10,4 @@ struct Sigaction;
 void   rt_sigaction(uintptr, struct Sigaction*, void*, uintptr);
 
 void   sigaltstack(Sigaltstack*, Sigaltstack*);
+void   sigpanic(void);
index dbc87db25c205454831eb943203e80105c6b3c16..788f682407e100c811c9505c66d857c5ccdca45a 100644 (file)
@@ -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",
@@ -15,11 +16,11 @@ static SigTab sigtab[] = {
        /* 4 */ C, "SIGILL: illegal instruction",
        /* 5 */ C, "SIGTRAP: trace trap",
        /* 6 */ C, "SIGABRT: abort",
-       /* 7 */ C, "SIGBUS: bus error",
-       /* 8 */ C, "SIGFPE: floating-point exception",
+       /* 7 */ C+P, "SIGBUS: bus error",
+       /* 8 */ C+P, "SIGFPE: floating-point exception",
        /* 9 */ 0, "SIGKILL: kill",
        /* 10 */        Q+I+R, "SIGUSR1: user-defined signal 1",
-       /* 11 */        C, "SIGSEGV: segmentation violation",
+       /* 11 */        C+P, "SIGSEGV: segmentation violation",
        /* 12 */        Q+I+R, "SIGUSR2: user-defined signal 2",
        /* 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
index d6811eb378d0878a6c6f2c9e97913d597264b425..a849125f942a1ad7ba514fe4fa36296cffc347ee 100644 (file)
@@ -4,9 +4,10 @@
 
 #include "runtime.h"
 #include "defs.h"
-#include "signals.h"
 #include "os.h"
 
+extern SigTab sigtab[];
+
 // Linux futex.
 //
 //     futexsleep(uint32 *addr, uint32 val)
@@ -270,3 +271,27 @@ minit(void)
        m->gsignal = malg(32*1024);     // OS X wants >=8K, Linux >=2K
        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);
+}
index 26ce4b635cf79b7bf8fd2e09e6e41d308376d7c5..f3297e7e05d2bcfb4389e838338fc18a63e7ea95 100644 (file)
@@ -198,6 +198,9 @@ struct      G
        M*      lockedm;
        void    (*cgofn)(void*);        // for cgo/ffi
        void    *cgoarg;
+       int32   sig;
+       uintptr sigcode0;
+       uintptr sigcode1;
 };
 struct M
 {
@@ -268,6 +271,7 @@ enum
        SigIgnore = 1<<1,
        SigRestart = 1<<2,
        SigQueue = 1<<3,
+       SigPanic = 1<<4,
 };
 
 // NOTE(rsc): keep in sync with extern.go:/type.Func.
diff --git a/test/recover3.go b/test/recover3.go
new file mode 100644 (file)
index 0000000..f719b0c
--- /dev/null
@@ -0,0 +1,78 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "runtime"
+       "strings"
+       "syscall"
+)
+
+var didbug bool
+
+func bug() {
+       if didbug {
+               return
+       }
+       println("BUG")
+       didbug = true
+}
+
+func check(name string, f func(), err string) {
+       defer func() {
+               v := recover()
+               if v == nil {
+                       bug()
+                       println(name, "did not panic")
+                       return
+               }
+               runt, ok := v.(runtime.Error)
+               if !ok {
+                       bug()
+                       println(name, "panicked but not with runtime.Error")
+                       return
+               }
+               s := runt.String()
+               if strings.Index(s, err) < 0 {
+                       bug()
+                       println(name, "panicked with", s, "not", err)
+                       return
+               }
+       }()
+       
+       f()
+}
+
+func main() {
+       var x int
+       var x64 int64
+       var p *[10]int
+       var q *[10000]int
+       var i int
+
+       // not catching divide by zero on the arm.  is that even possible?
+       if syscall.ARCH != "arm" {
+               check("int-div-zero", func() { println(1/x) }, "integer divide by zero")
+               check("int64-div-zero", func() { println(1/x64) }, "integer divide by zero")
+       }
+
+       check("nil-deref", func() { println(p[0]) }, "nil pointer dereference")
+       check("nil-deref-1", func() { println(p[1]) }, "nil pointer dereference")
+       check("nil-deref-big", func() { println(q[5000]) }, "nil pointer dereference")
+
+       i = 99999
+       var sl []int
+       check("array-bounds", func() { println(p[i]) }, "index out of range")
+       check("slice-bounds", func() { println(sl[i]) }, "index out of range")
+       
+       var inter interface{}
+       inter = 1
+       check("type-concrete", func() { println(inter.(string)) }, "int, not string")
+       check("type-interface", func() { println(inter.(m)) }, "missing method m")
+}
+
+type m interface{ m() }