diff options
Diffstat (limited to 'src/pkg/runtime/os_plan9_386.c')
-rw-r--r-- | src/pkg/runtime/os_plan9_386.c | 135 |
1 files changed, 76 insertions, 59 deletions
diff --git a/src/pkg/runtime/os_plan9_386.c b/src/pkg/runtime/os_plan9_386.c index 0844d726b..80d711f33 100644 --- a/src/pkg/runtime/os_plan9_386.c +++ b/src/pkg/runtime/os_plan9_386.c @@ -10,71 +10,80 @@ void runtime·dumpregs(Ureg *u) { - runtime·printf("ax %X\n", u->ax); - runtime·printf("bx %X\n", u->bx); - runtime·printf("cx %X\n", u->cx); - runtime·printf("dx %X\n", u->dx); - runtime·printf("di %X\n", u->di); - runtime·printf("si %X\n", u->si); - runtime·printf("bp %X\n", u->bp); - runtime·printf("sp %X\n", u->sp); - runtime·printf("pc %X\n", u->pc); - runtime·printf("flags %X\n", u->flags); - runtime·printf("cs %X\n", u->cs); - runtime·printf("fs %X\n", u->fs); - runtime·printf("gs %X\n", u->gs); + runtime·printf("ax %x\n", u->ax); + runtime·printf("bx %x\n", u->bx); + runtime·printf("cx %x\n", u->cx); + runtime·printf("dx %x\n", u->dx); + runtime·printf("di %x\n", u->di); + runtime·printf("si %x\n", u->si); + runtime·printf("bp %x\n", u->bp); + runtime·printf("sp %x\n", u->sp); + runtime·printf("pc %x\n", u->pc); + runtime·printf("flags %x\n", u->flags); + runtime·printf("cs %x\n", u->cs); + runtime·printf("fs %x\n", u->fs); + runtime·printf("gs %x\n", u->gs); } int32 -runtime·sighandler(void *v, int8 *s, G *gp) +runtime·sighandler(void *v, int8 *note, G *gp) { + uintptr *sp; + SigTab *t; bool crash; Ureg *ureg; - uintptr *sp; - SigTab *sig, *nsig; - intgo len, i; + intgo len, n; + int32 sig, flags; - if(!s) - return NCONT; - - len = runtime·findnull((byte*)s); - if(len <= 4 || runtime·mcmp((byte*)s, (byte*)"sys:", 4) != 0) - return NDFLT; - - nsig = nil; - sig = runtime·sigtab; - for(i=0; i < NSIG; i++) { - if(runtime·strstr((byte*)s, (byte*)sig->name)) { - nsig = sig; + ureg = (Ureg*)v; + + // The kernel will never pass us a nil note or ureg so we probably + // made a mistake somewhere in runtime·sigtramp. + if(ureg == nil || note == nil) { + runtime·printf("sighandler: ureg %p note %p\n", ureg, note); + goto Throw; + } + + // Check that the note is no more than ERRMAX bytes (including + // the trailing NUL). We should never receive a longer note. + len = runtime·findnull((byte*)note); + if(len > ERRMAX-1) { + runtime·printf("sighandler: note is longer than ERRMAX\n"); + goto Throw; + } + + // See if the note matches one of the patterns in runtime·sigtab. + // Notes that do not match any pattern can be handled at a higher + // level by the program but will otherwise be ignored. + flags = SigNotify; + for(sig = 0; sig < nelem(runtime·sigtab); sig++) { + t = &runtime·sigtab[sig]; + n = runtime·findnull((byte*)t->name); + if(len < n) + continue; + if(runtime·strncmp((byte*)note, (byte*)t->name, n) == 0) { + flags = t->flags; break; } - sig++; } - if(nsig == nil) - return NDFLT; - - ureg = v; - if(nsig->flags & SigPanic) { - if(gp == nil || m->notesig == 0) - goto Throw; + if(flags & SigGoExit) + runtime·exits(note+9); // Strip "go: exit " prefix. - // Save error string from sigtramp's stack, - // into gsignal->sigcode0, so we can reliably - // access it from the panic routines. - if(len > ERRMAX) - len = ERRMAX; - runtime·memmove((void*)m->notesig, (void*)s, len); + if(flags & SigPanic) { + // Copy the error string from sigtramp's stack into m->notesig so + // we can reliably access it from the panic routines. + runtime·memmove(m->notesig, note, len+1); - gp->sig = i; + gp->sig = sig; gp->sigpc = ureg->pc; - // Only push runtime·sigpanic if ureg->pc != 0. - // If ureg->pc == 0, probably panicked because of a - // call to a nil func. Not pushing that onto sp will - // make the trace look like a call to runtime·sigpanic instead. - // (Otherwise the trace will end at runtime·sigpanic and we - // won't get to see who faulted.) + // Only push runtime·sigpanic if PC != 0. + // + // If PC == 0, probably panicked because of a call to a nil func. + // Not pushing that onto SP will make the trace look like a call + // to runtime·sigpanic instead. (Otherwise the trace will end at + // runtime·sigpanic and we won't get to see who faulted). if(ureg->pc != 0) { sp = (uintptr*)ureg->sp; *--sp = ureg->pc; @@ -84,34 +93,42 @@ runtime·sighandler(void *v, int8 *s, G *gp) return NCONT; } - if(!(nsig->flags & SigThrow)) - return NDFLT; + if(flags & SigNotify) { + // TODO(ality): See if os/signal wants it. + //if(runtime·sigsend(...)) + // return NCONT; + } + if(flags & SigKill) + goto Exit; + if(!(flags & SigThrow)) + return NCONT; Throw: m->throwing = 1; m->caughtsig = gp; runtime·startpanic(); - runtime·printf("%s\n", s); - runtime·printf("PC=%X\n", ureg->pc); + runtime·printf("%s\n", note); + runtime·printf("PC=%x\n", ureg->pc); runtime·printf("\n"); if(runtime·gotraceback(&crash)) { + runtime·goroutineheader(gp); runtime·traceback(ureg->pc, ureg->sp, 0, gp); runtime·tracebackothers(gp); + runtime·printf("\n"); runtime·dumpregs(ureg); } if(crash) runtime·crash(); - runtime·goexitsall(""); - runtime·exits(s); - - return 0; +Exit: + runtime·goexitsall(note); + runtime·exits(note); + return NDFLT; // not reached } - void runtime·sigenable(uint32 sig) { |