1
0
mirror of https://github.com/golang/go synced 2024-10-05 00:21:21 -06:00
go/src/pkg/runtime/signal_netbsd_386.c
Joel Sing 1b6557a0cf runtime: fix netbsd/386 stack pointer handling
When manipulating the stack pointer use the UESP register instead
of the ESP register, since the UESP register is the one that gets
restored from the machine context. Fixes broken tests on netbsd/386.

R=golang-dev, minux.ma, r, bsiegert
CC=golang-dev
https://golang.org/cl/6465054
2012-08-17 21:53:02 +10:00

150 lines
4.1 KiB
C

// Copyright 2009 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.
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "signals_GOOS.h"
#include "os_GOOS.h"
extern void runtime·lwp_tramp(void);
extern void runtime·sigtramp(void);
typedef struct sigaction {
union {
void (*_sa_handler)(int32);
void (*_sa_sigaction)(int32, Siginfo*, void *);
} _sa_u; /* signal handler */
uint32 sa_mask[4]; /* signal mask to apply */
int32 sa_flags; /* see signal options below */
} Sigaction;
void
runtime·dumpregs(McontextT *mc)
{
runtime·printf("eax %x\n", mc->__gregs[REG_EAX]);
runtime·printf("ebx %x\n", mc->__gregs[REG_EBX]);
runtime·printf("ecx %x\n", mc->__gregs[REG_ECX]);
runtime·printf("edx %x\n", mc->__gregs[REG_EDX]);
runtime·printf("edi %x\n", mc->__gregs[REG_EDI]);
runtime·printf("esi %x\n", mc->__gregs[REG_ESI]);
runtime·printf("ebp %x\n", mc->__gregs[REG_EBP]);
runtime·printf("esp %x\n", mc->__gregs[REG_UESP]);
runtime·printf("eip %x\n", mc->__gregs[REG_EIP]);
runtime·printf("eflags %x\n", mc->__gregs[REG_EFL]);
runtime·printf("cs %x\n", mc->__gregs[REG_CS]);
runtime·printf("fs %x\n", mc->__gregs[REG_FS]);
runtime·printf("gs %x\n", mc->__gregs[REG_GS]);
}
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
UcontextT *uc = context;
McontextT *mc = &uc->uc_mcontext;
uintptr *sp;
SigTab *t;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)mc->__gregs[REG_EIP],
(uint8*)mc->__gregs[REG_UESP], nil, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil)
goto Throw;
// Make it look like a call to the signal func.
// We need to pass arguments out of band since
// augmenting the stack frame would break
// the unwinding code.
gp->sig = sig;
gp->sigcode0 = info->_code;
gp->sigcode1 = *(uintptr*)&info->_reason[0]; /* _addr */
gp->sigpc = mc->__gregs[REG_EIP];
// Only push runtime·sigpanic if __gregs[REG_EIP] != 0.
// If __gregs[REG_EIP] == 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(mc->__gregs[REG_EIP] != 0) {
sp = (uintptr*)mc->__gregs[REG_UESP];
*--sp = mc->__gregs[REG_EIP];
mc->__gregs[REG_UESP] = (uintptr)sp;
}
mc->__gregs[REG_EIP] = (uintptr)runtime·sigpanic;
return;
}
if(info->_code == SI_USER || (t->flags & SigNotify))
if(runtime·sigsend(sig))
return;
if(t->flags & SigKill)
runtime·exit(2);
if(!(t->flags & SigThrow))
return;
Throw:
runtime·startpanic();
if(sig < 0 || sig >= NSIG)
runtime·printf("Signal %d\n", sig);
else
runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", mc->__gregs[REG_EIP]);
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)mc->__gregs[REG_EIP],
(void*)mc->__gregs[REG_UESP], 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(mc);
}
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = p;
st.ss_size = n;
st.ss_flags = 0;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask[0] = ~0U;
sa.sa_mask[1] = ~0U;
sa.sa_mask[2] = ~0U;
sa.sa_mask[3] = ~0U;
if (fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa._sa_u._sa_sigaction = (void*)fn;
runtime·sigaction(i, &sa, nil);
}
void
runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *m, G *g, void (*fn)(void))
{
mc->__gregs[REG_EIP] = (uint32)runtime·lwp_tramp;
mc->__gregs[REG_UESP] = (uint32)stack;
mc->__gregs[REG_EBX] = (uint32)m;
mc->__gregs[REG_EDX] = (uint32)g;
mc->__gregs[REG_ESI] = (uint32)fn;
}