Commit e9d62a6d authored by Russ Cox's avatar Russ Cox

runtime: refactor os-specific code

thread_GOOS.c becomes os_GOOS.c.

signal_GOOS_GOARCH.c becomes os_GOOS_GOARCH.c,
but with non-GOARCH-specific code moved into os_GOOS.c.

The actual arch-specific signal handler moves into signal_GOARCH.c
to avoid per-GOOS duplication.

New files signal_GOOS_GOARCH.h provide macros for
accessing fields of the very system-specific signal info structs.

Lots moving, but nothing changing.
This is a preliminarly cleanup so I can work on the signal
handling code to fix some open issues without having to
make each change 13 times.

Tested on Linux and OS X, 386 and amd64.
Will fix Plan 9, Windows, and ARM after the fact if necessary.
(Plan 9 and Windows should be fine; ARM will probably have some typos.)

Net effect: -1081 lines of code.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/7565048
parent cdc64245
......@@ -794,6 +794,9 @@ install(char *dir)
bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
copy(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
if(isfile(p))
copy(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
copy(bpathf(&b, "%s/os_GOOS.h", workdir),
bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
copy(bpathf(&b, "%s/signals_GOOS.h", workdir),
......
......@@ -5,6 +5,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
extern SigTab runtime·sigtab[];
......@@ -546,3 +547,41 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
void
runtime·setsig(int32 i, GoSighandler *fn, 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 = ~(uintptr)0;
sa.sa_tramp = (void*)runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
*(uintptr*)sa.__sigaction_u = (uintptr)fn;
runtime·sigaction(i, &sa, nil);
}
GoSighandler*
runtime·getsig(int32 i)
{
Sigaction sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
return *(void**)sa.__sigaction_u;
}
void
runtime·signalstack(byte *p, int32 n)
{
StackT st;
st.ss_sp = (void*)p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
......@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define SIG_DFL ((void*)0)
#define SIG_IGN ((void*)1)
#define SIGHUP 1
#define SS_DISABLE 4
int32 runtime·bsdthread_create(void*, M*, G*, void(*)(void));
......@@ -27,8 +24,6 @@ void runtime·sigprocmask(int32, Sigset*, Sigset*);
struct Sigaction;
void runtime·sigaction(uintptr, struct Sigaction*, struct Sigaction*);
void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
struct StackT;
void runtime·sigaltstack(struct StackT*, struct StackT*);
......@@ -36,7 +31,6 @@ void runtime·sigtramp(void);
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
void runtime·raisesigpipe(void);
#define NSIG 32
#define SI_USER 0 /* empirically true, but not what headers say */
......
......@@ -4,6 +4,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
extern SigTab runtime·sigtab[];
......@@ -257,3 +258,58 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
extern void runtime·sigtramp(void);
typedef struct sigaction {
union {
void (*__sa_handler)(int32);
void (*__sa_sigaction)(int32, Siginfo*, void *);
} __sigaction_u; /* signal handler */
int32 sa_flags; /* see signal options below */
Sigset sa_mask; /* signal mask to apply */
} Sigaction;
void
runtime·setsig(int32 i, GoSighandler *fn, 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.__bits[0] = ~(uint32)0;
sa.sa_mask.__bits[1] = ~(uint32)0;
sa.sa_mask.__bits[2] = ~(uint32)0;
sa.sa_mask.__bits[3] = ~(uint32)0;
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.__sigaction_u.__sa_sigaction = (void*)fn;
runtime·sigaction(i, &sa, nil);
}
GoSighandler*
runtime·getsig(int32 i)
{
Sigaction sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if((void*)sa.__sigaction_u.__sa_sigaction == runtime·sigtramp)
return runtime·sighandler;
return (void*)sa.__sigaction_u.__sa_sigaction;
}
void
runtime·signalstack(byte *p, int32 n)
{
StackT st;
st.ss_sp = (void*)p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
#define SIG_DFL ((void*)0)
#define SIG_IGN ((void*)1)
#define SIGHUP 1
#define SS_DISABLE 4
int32 runtime·thr_new(ThrParam*, int32);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
void runtime·sigpanic(void);
void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
struct sigaction;
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·sigprocmask(Sigset *, Sigset *);
void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
void runtime·raisesigpipe(void);
#define NSIG 33
#define SI_USER 0x10001
......
// Copyright 2012 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 "os_GOOS.h"
void
runtime·checkgoarm(void)
{
// TODO(minux)
}
#pragma textflag 7
int64
runtime·cputicks(void)
{
// Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
// runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
// TODO: need more entropy to better seed fastrand1.
return runtime·nanotime();
}
......@@ -5,6 +5,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
extern SigTab runtime·sigtab[];
......@@ -309,3 +310,60 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
#ifdef GOARCH_386
#define sa_handler k_sa_handler
#endif
/*
* This assembler routine takes the args from registers, puts them on the stack,
* and calls sighandler().
*/
extern void runtime·sigtramp(void);
extern void runtime·sigreturn(void); // calls runtime·sigreturn
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
Sigaction sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask = ~0ULL;
// TODO(adonovan): Linux manpage says "sa_restorer element is
// obsolete and should not be used". Avoid it here, and test.
sa.sa_restorer = (void*)runtime·sigreturn;
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.sa_handler = fn;
if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
runtime·throw("rt_sigaction failure");
}
GoSighandler*
runtime·getsig(int32 i)
{
Sigaction sa;
runtime·memclr((byte*)&sa, sizeof sa);
if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
runtime·throw("rt_sigaction read failure");
if((void*)sa.sa_handler == runtime·sigtramp)
return runtime·sighandler;
return (void*)sa.sa_handler;
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
......@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define SIG_DFL ((void*)0)
#define SIG_IGN ((void*)1)
#define SIGHUP 1
#define SS_DISABLE 2
// Linux-specific system calls
......@@ -13,14 +10,11 @@ int32 runtime·clone(int32, void*, M*, G*, void(*)(void));
struct Sigaction;
int32 runtime·rt_sigaction(uintptr, struct Sigaction*, void*, uintptr);
void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
void runtime·raisesigpipe(void);
#define NSIG 65
#define SI_USER 0
......
// 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 "os_GOOS.h"
#define AT_NULL 0
#define AT_RANDOM 25
#define AT_SYSINFO 32
extern uint32 runtime·_vdso;
#pragma textflag 7
void
runtime·linux_setup_vdso(int32 argc, byte **argv)
{
byte **envp;
uint32 *auxv;
// skip envp to get to ELF auxiliary vector.
for(envp = &argv[argc+1]; *envp != nil; envp++)
;
envp++;
for(auxv=(uint32*)envp; auxv[0] != AT_NULL; auxv += 2) {
if(auxv[0] == AT_SYSINFO) {
runtime·_vdso = auxv[1];
continue;
}
if(auxv[0] == AT_RANDOM) {
runtime·startup_random_data = (byte*)auxv[1];
runtime·startup_random_data_len = 16;
continue;
}
}
}
......@@ -4,167 +4,8 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "signals_GOOS.h"
#include "os_GOOS.h"
void
runtime·dumpregs(Sigcontext *r)
{
runtime·printf("trap %x\n", r->trap_no);
runtime·printf("error %x\n", r->error_code);
runtime·printf("oldmask %x\n", r->oldmask);
runtime·printf("r0 %x\n", r->arm_r0);
runtime·printf("r1 %x\n", r->arm_r1);
runtime·printf("r2 %x\n", r->arm_r2);
runtime·printf("r3 %x\n", r->arm_r3);
runtime·printf("r4 %x\n", r->arm_r4);
runtime·printf("r5 %x\n", r->arm_r5);
runtime·printf("r6 %x\n", r->arm_r6);
runtime·printf("r7 %x\n", r->arm_r7);
runtime·printf("r8 %x\n", r->arm_r8);
runtime·printf("r9 %x\n", r->arm_r9);
runtime·printf("r10 %x\n", r->arm_r10);
runtime·printf("fp %x\n", r->arm_fp);
runtime·printf("ip %x\n", r->arm_ip);
runtime·printf("sp %x\n", r->arm_sp);
runtime·printf("lr %x\n", r->arm_lr);
runtime·printf("pc %x\n", r->arm_pc);
runtime·printf("cpsr %x\n", r->arm_cpsr);
runtime·printf("fault %x\n", r->fault_address);
}
/*
* This assembler routine takes the args from registers, puts them on the stack,
* and calls sighandler().
*/
extern void runtime·sigtramp(void);
extern void runtime·sigreturn(void); // calls runtime·sigreturn
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
Ucontext *uc;
Sigcontext *r;
SigTab *t;
uc = context;
r = &uc->uc_mcontext;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)r->arm_pc, (uint8*)r->arm_sp, (uint8*)r->arm_lr, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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;
gp->sigpc = r->arm_pc;
// We arrange lr, and pc to pretend the panicking
// function calls sigpanic directly.
// Always save LR to stack so that panics in leaf
// functions are correctly handled. This smashes
// the stack frame but we're not going back there
// anyway.
r->arm_sp -= 4;
*(uint32 *)r->arm_sp = r->arm_lr;
// Don't bother saving PC if it's zero, which is
// probably a call to a nil func: the old link register
// is more useful in the stack trace.
if(r->arm_pc != 0)
r->arm_lr = r->arm_pc;
// In case we are panicking from external C code
r->arm_r10 = (uintptr)gp;
r->arm_r9 = (uintptr)m;
r->arm_pc = (uintptr)runtime·sigpanic;
return;
}
if(info->si_code == SI_USER || (t->flags & SigNotify))
if(runtime·sigsend(sig))
return;
if(t->flags & SigKill)
runtime·exit(2);
if(!(t->flags & SigThrow))
return;
Throw:
if(runtime·panicking) // traceback already printed
runtime·exit(2);
runtime·panicking = 1;
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", r->arm_pc);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(r);
}
// breakpoint();
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
runtime·throw("rt_sigaction read failure");
if(sa.sa_handler == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask = ~0ULL;
sa.sa_restorer = (void*)runtime·sigreturn;
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.sa_handler = fn;
if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
runtime·throw("rt_sigaction failure");
}
#define AT_NULL 0
#define AT_PLATFORM 15 // introduced in at least 2.6.11
#define AT_HWCAP 16 // introduced in at least 2.6.11
......
......@@ -4,6 +4,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
enum
......@@ -302,3 +303,58 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
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·setsig(int32 i, GoSighandler *fn, 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);
}
GoSighandler*
runtime·getsig(int32 i)
{
Sigaction sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if((void*)sa._sa_u._sa_sigaction == runtime·sigtramp)
return runtime·sighandler;
return (void*)sa._sa_u._sa_sigaction;
}
void
runtime·signalstack(byte *p, int32 n)
{
StackT st;
st.ss_sp = (void*)p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
......@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define SIG_DFL ((void*)0)
#define SIG_IGN ((void*)1)
#define SIGHUP 1
#define SS_DISABLE 4
#define SIG_BLOCK 1
......@@ -13,9 +10,6 @@
struct sigaction;
void runtime·raisesigpipe(void);
void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
......
// 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 "os_GOOS.h"
void
runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
{
mc->__gregs[REG_EIP] = (uint32)runtime·lwp_tramp;
mc->__gregs[REG_UESP] = (uint32)stack;
mc->__gregs[REG_EBX] = (uint32)mp;
mc->__gregs[REG_EDX] = (uint32)gp;
mc->__gregs[REG_ESI] = (uint32)fn;
}
// 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 "os_GOOS.h"
void
runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
{
// Machine dependent mcontext initialisation for LWP.
mc->__gregs[REG_RIP] = (uint64)runtime·lwp_tramp;
mc->__gregs[REG_RSP] = (uint64)stack;
mc->__gregs[REG_R8] = (uint64)mp;
mc->__gregs[REG_R9] = (uint64)gp;
mc->__gregs[REG_R12] = (uint64)fn;
}
// Copyright 2013 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 "os_GOOS.h"
void
runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
{
mc->r15 = (uint32)runtime·lwp_tramp;
mc->r13 = (uint32)stack;
mc->r0 = (uint32)mp;
mc->r1 = (uint32)gp;
mc->r2 = (uint32)fn;
}
void
runtime·checkgoarm(void)
{
// TODO(minux)
}
#pragma textflag 7
int64
runtime·cputicks() {
// Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
// runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
// TODO: need more entropy to better seed fastrand1.
return runtime·nanotime();
}
......@@ -4,6 +4,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
enum
......@@ -279,3 +280,55 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
extern void runtime·sigtramp(void);
typedef struct sigaction {
union {
void (*__sa_handler)(int32);
void (*__sa_sigaction)(int32, Siginfo*, void *);
} __sigaction_u; /* signal handler */
uint32 sa_mask; /* signal mask to apply */
int32 sa_flags; /* see signal options below */
} Sigaction;
void
runtime·setsig(int32 i, GoSighandler *fn, 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 = ~0U;
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.__sigaction_u.__sa_sigaction = (void*)fn;
runtime·sigaction(i, &sa, nil);
}
GoSighandler*
runtime·getsig(int32 i)
{
Sigaction sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if((void*)sa.__sigaction_u.__sa_sigaction == runtime·sigtramp)
return runtime·sighandler;
return (void*)sa.__sigaction_u.__sa_sigaction;
}
void
runtime·signalstack(byte *p, int32 n)
{
StackT st;
st.ss_sp = (void*)p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
......@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define SIG_DFL ((void*)0)
#define SIG_IGN ((void*)1)
#define SIGHUP 1
#define SS_DISABLE 4
#define SIG_BLOCK 1
......@@ -13,14 +10,11 @@
struct sigaction;
void runtime·raisesigpipe(void);
void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
Sigset runtime·sigprocmask(int32, Sigset);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
......
......@@ -16,7 +16,6 @@ int32 runtime·plan9_semrelease(uint32 *addr, int32 count);
int32 runtime·notify(void (*fn)(void*, int8*));
int32 runtime·noted(int32);
void runtime·sigtramp(void*, int8*);
int32 runtime·sighandler(void*, int8*, G*);
void runtime·sigpanic(void);
void runtime·goexitsall(int8*);
void runtime·setfpmasks(void);
......
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2013 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.
// +build darwin freebsd linux netbsd openbsd
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_GOOS_GOARCH.h"
#include "signals_GOOS.h"
void
runtime·dumpregs(Regs32 *r)
runtime·dumpregs(Siginfo *info, void *ctxt)
{
runtime·printf("eax %x\n", r->eax);
runtime·printf("ebx %x\n", r->ebx);
runtime·printf("ecx %x\n", r->ecx);
runtime·printf("edx %x\n", r->edx);
runtime·printf("edi %x\n", r->edi);
runtime·printf("esi %x\n", r->esi);
runtime·printf("ebp %x\n", r->ebp);
runtime·printf("esp %x\n", r->esp);
runtime·printf("eip %x\n", r->eip);
runtime·printf("eflags %x\n", r->eflags);
runtime·printf("cs %x\n", r->cs);
runtime·printf("fs %x\n", r->fs);
runtime·printf("gs %x\n", r->gs);
USED(info);
USED(ctxt);
runtime·printf("eax %x\n", SIG_EAX(info, ctxt));
runtime·printf("ebx %x\n", SIG_EBX(info, ctxt));
runtime·printf("ecx %x\n", SIG_ECX(info, ctxt));
runtime·printf("edx %x\n", SIG_EDX(info, ctxt));
runtime·printf("edi %x\n", SIG_EDI(info, ctxt));
runtime·printf("esi %x\n", SIG_ESI(info, ctxt));
runtime·printf("ebp %x\n", SIG_EBP(info, ctxt));
runtime·printf("esp %x\n", SIG_ESP(info, ctxt));
runtime·printf("eip %x\n", SIG_EIP(info, ctxt));
runtime·printf("eflags %x\n", SIG_EFLAGS(info, ctxt));
runtime·printf("cs %x\n", SIG_CS(info, ctxt));
runtime·printf("fs %x\n", SIG_FS(info, ctxt));
runtime·printf("gs %x\n", SIG_GS(info, ctxt));
}
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{
Ucontext *uc;
Mcontext32 *mc;
Regs32 *r;
uintptr *sp;
byte *pc;
SigTab *t;
uc = context;
mc = uc->uc_mcontext;
r = &mc->ss;
if(sig == SIGPROF) {
if(gp != m->g0 && gp != m->gsignal)
runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
runtime·sigprof((byte*)SIG_EIP(info, ctxt), (byte*)SIG_ESP(info, ctxt), nil, gp);
return;
}
......@@ -49,38 +47,42 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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 = SIG_CODE0(info, ctxt);
gp->sigcode1 = SIG_CODE1(info, ctxt);
gp->sigpc = SIG_EIP(info, ctxt);
#ifdef GOOS_darwin
// 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(sig == SIGFPE && gp->sigcode0 == 0) {
byte *pc;
pc = (byte*)gp->sigpc;
if(pc[0] == 0x66) // 16-bit instruction prefix
pc++;
if(pc[0] == 0xF6 || pc[0] == 0xF7)
info->si_code = FPE_INTDIV;
gp->sigcode0 = FPE_INTDIV;
}
#endif
// 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;
gp->sigpc = r->eip;
// Only push runtime·sigpanic if r->eip != 0.
// If r->eip == 0, probably panicked because of a
// Only push runtime·sigpanic if eip != 0.
// If 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(r->eip != 0) {
sp = (uintptr*)r->esp;
*--sp = r->eip;
r->esp = (uintptr)sp;
if(SIG_EIP(info, ctxt) != 0) {
sp = (uintptr*)SIG_ESP(info, ctxt);
*--sp = SIG_EIP(info, ctxt);
SIG_ESP(info, ctxt) = (uintptr)sp;
}
r->eip = (uintptr)runtime·sigpanic;
SIG_EIP(info, ctxt) = (uintptr)runtime·sigpanic;
return;
}
......@@ -95,13 +97,12 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
Throw:
runtime·startpanic();
if(sig < 0 || sig >= NSIG){
if(sig < 0 || sig >= NSIG)
runtime·printf("Signal %d\n", sig);
}else{
else
runtime·printf("%s\n", runtime·sigtab[sig].name);
}
runtime·printf("PC=%x\n", r->eip);
runtime·printf("PC=%x\n", SIG_EIP(info, ctxt));
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
......@@ -109,47 +110,10 @@ Throw:
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
runtime·traceback((void*)SIG_EIP(info, ctxt), (void*)SIG_ESP(info, ctxt), 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
runtime·dumpregs(info, ctxt);
}
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
StackT st;
st.ss_sp = p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(*(void**)sa.__sigaction_u == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask = ~0U;
sa.sa_tramp = (void*)runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
*(uintptr*)sa.__sigaction_u = (uintptr)fn;
runtime·sigaction(i, &sa, nil);
}
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2013 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.
// +build darwin freebsd linux netbsd openbsd
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_GOOS_GOARCH.h"
#include "signals_GOOS.h"
void
runtime·dumpregs(Regs64 *r)
runtime·dumpregs(Siginfo *info, void *ctxt)
{
runtime·printf("rax %X\n", r->rax);
runtime·printf("rbx %X\n", r->rbx);
runtime·printf("rcx %X\n", r->rcx);
runtime·printf("rdx %X\n", r->rdx);
runtime·printf("rdi %X\n", r->rdi);
runtime·printf("rsi %X\n", r->rsi);
runtime·printf("rbp %X\n", r->rbp);
runtime·printf("rsp %X\n", r->rsp);
runtime·printf("r8 %X\n", r->r8 );
runtime·printf("r9 %X\n", r->r9 );
runtime·printf("r10 %X\n", r->r10);
runtime·printf("r11 %X\n", r->r11);
runtime·printf("r12 %X\n", r->r12);
runtime·printf("r13 %X\n", r->r13);
runtime·printf("r14 %X\n", r->r14);
runtime·printf("r15 %X\n", r->r15);
runtime·printf("rip %X\n", r->rip);
runtime·printf("rflags %X\n", r->rflags);
runtime·printf("cs %X\n", r->cs);
runtime·printf("fs %X\n", r->fs);
runtime·printf("gs %X\n", r->gs);
USED(info);
USED(ctxt);
runtime·printf("rax %X\n", SIG_RAX(info, ctxt));
runtime·printf("rbx %X\n", SIG_RBX(info, ctxt));
runtime·printf("rcx %X\n", SIG_RCX(info, ctxt));
runtime·printf("rdx %X\n", SIG_RDX(info, ctxt));
runtime·printf("rdi %X\n", SIG_RDI(info, ctxt));
runtime·printf("rsi %X\n", SIG_RSI(info, ctxt));
runtime·printf("rbp %X\n", SIG_RBP(info, ctxt));
runtime·printf("rsp %X\n", SIG_RSP(info, ctxt));
runtime·printf("r8 %X\n", SIG_R8(info, ctxt) );
runtime·printf("r9 %X\n", SIG_R9(info, ctxt) );
runtime·printf("r10 %X\n", SIG_R10(info, ctxt));
runtime·printf("r11 %X\n", SIG_R11(info, ctxt));
runtime·printf("r12 %X\n", SIG_R12(info, ctxt));
runtime·printf("r13 %X\n", SIG_R13(info, ctxt));
runtime·printf("r14 %X\n", SIG_R14(info, ctxt));
runtime·printf("r15 %X\n", SIG_R15(info, ctxt));
runtime·printf("rip %X\n", SIG_RIP(info, ctxt));
runtime·printf("rflags %X\n", SIG_RFLAGS(info, ctxt));
runtime·printf("cs %X\n", SIG_CS(info, ctxt));
runtime·printf("fs %X\n", SIG_FS(info, ctxt));
runtime·printf("gs %X\n", SIG_GS(info, ctxt));
}
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{
Ucontext *uc;
Mcontext64 *mc;
Regs64 *r;
uintptr *sp;
byte *pc;
SigTab *t;
uc = context;
mc = uc->uc_mcontext;
r = &mc->ss;
if(sig == SIGPROF) {
if(gp != m->g0 && gp != m->gsignal)
runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp);
return;
}
......@@ -57,40 +55,44 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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 = SIG_CODE0(info, ctxt);
gp->sigcode1 = SIG_CODE1(info, ctxt);
gp->sigpc = SIG_RIP(info, ctxt);
#ifdef GOOS_darwin
// 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(sig == SIGFPE && gp->sigcode0 == 0) {
byte *pc;
pc = (byte*)gp->sigpc;
if((pc[0]&0xF0) == 0x40) // 64-bit REX prefix
pc++;
else if(pc[0] == 0x66) // 16-bit instruction prefix
pc++;
if(pc[0] == 0xF6 || pc[0] == 0xF7)
info->si_code = FPE_INTDIV;
gp->sigcode0 = FPE_INTDIV;
}
#endif
// 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;
gp->sigpc = r->rip;
// Only push runtime·sigpanic if r->rip != 0.
// If r->rip == 0, probably panicked because of a
// Only push runtime·sigpanic if rip != 0.
// If rip == 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(r->rip != 0) {
sp = (uintptr*)r->rsp;
*--sp = r->rip;
r->rsp = (uintptr)sp;
if(SIG_RIP(info, ctxt) != 0) {
sp = (uintptr*)SIG_RSP(info, ctxt);
*--sp = SIG_RIP(info, ctxt);
SIG_RSP(info, ctxt) = (uintptr)sp;
}
r->rip = (uintptr)runtime·sigpanic;
SIG_RIP(info, ctxt) = (uintptr)runtime·sigpanic;
return;
}
......@@ -105,13 +107,12 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
Throw:
runtime·startpanic();
if(sig < 0 || sig >= NSIG){
if(sig < 0 || sig >= NSIG)
runtime·printf("Signal %d\n", sig);
}else{
else
runtime·printf("%s\n", runtime·sigtab[sig].name);
}
runtime·printf("PC=%X\n", r->rip);
runtime·printf("PC=%X\n", SIG_RIP(info, ctxt));
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
......@@ -119,47 +120,10 @@ Throw:
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
runtime·traceback((void*)SIG_RIP(info, ctxt), (void*)SIG_RSP(info, ctxt), 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
runtime·dumpregs(info, ctxt);
}
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
StackT st;
st.ss_sp = p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(*(void**)sa.__sigaction_u == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask = ~0ULL;
sa.sa_tramp = runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
*(uintptr*)sa.__sigaction_u = (uintptr)fn;
runtime·sigaction(i, &sa, nil);
}
......@@ -2,49 +2,51 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin freebsd linux netbsd openbsd
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "signals_GOOS.h"
#include "os_GOOS.h"
extern void runtime·sigtramp(void);
typedef struct sigaction {
union {
void (*__sa_handler)(int32);
void (*__sa_sigaction)(int32, Siginfo*, void *);
} __sigaction_u; /* signal handler */
uint32 sa_mask; /* signal mask to apply */
int32 sa_flags; /* see signal options below */
} Sigaction;
#include "signal_GOOS_GOARCH.h"
#include "signals_GOOS.h"
void
runtime·dumpregs(Sigcontext *r)
runtime·dumpregs(Siginfo *info, void *ctxt)
{
runtime·printf("eax %x\n", r->sc_eax);
runtime·printf("ebx %x\n", r->sc_ebx);
runtime·printf("ecx %x\n", r->sc_ecx);
runtime·printf("edx %x\n", r->sc_edx);
runtime·printf("edi %x\n", r->sc_edi);
runtime·printf("esi %x\n", r->sc_esi);
runtime·printf("ebp %x\n", r->sc_ebp);
runtime·printf("esp %x\n", r->sc_esp);
runtime·printf("eip %x\n", r->sc_eip);
runtime·printf("eflags %x\n", r->sc_eflags);
runtime·printf("cs %x\n", r->sc_cs);
runtime·printf("fs %x\n", r->sc_fs);
runtime·printf("gs %x\n", r->sc_gs);
USED(info);
USED(ctxt);
runtime·printf("trap %x\n", SIG_TRAP(info, ctxt));
runtime·printf("error %x\n", SIG_ERROR(info, ctxt));
runtime·printf("oldmask %x\n", SIG_OLDMASK(info, ctxt));
runtime·printf("r0 %x\n", SIG_R0(info, ctxt));
runtime·printf("r1 %x\n", SIG_R1(info, ctxt));
runtime·printf("r2 %x\n", SIG_R2(info, ctxt));
runtime·printf("r3 %x\n", SIG_R3(info, ctxt));
runtime·printf("r4 %x\n", SIG_R4(info, ctxt));
runtime·printf("r5 %x\n", SIG_R5(info, ctxt));
runtime·printf("r6 %x\n", SIG_R6(info, ctxt));
runtime·printf("r7 %x\n", SIG_R7(info, ctxt));
runtime·printf("r8 %x\n", SIG_R8(info, ctxt));
runtime·printf("r9 %x\n", SIG_R9(info, ctxt));
runtime·printf("r10 %x\n", SIG_R10(info, ctxt));
runtime·printf("fp %x\n", SIG_FP(info, ctxt));
runtime·printf("ip %x\n", SIG_IP(info, ctxt));
runtime·printf("sp %x\n", SIG_SP(info, ctxt));
runtime·printf("lr %x\n", SIG_LR(info, ctxt));
runtime·printf("pc %x\n", SIG_PC(info, ctxt));
runtime·printf("cpsr %x\n", SIG_CPSR(info, ctxt));
runtime·printf("fault %x\n", SIG_FAULT(info, ctxt));
}
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{
Sigcontext *r = context;
uintptr *sp;
SigTab *t;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)r->sc_eip, (uint8*)r->sc_esp, nil, gp);
if(gp != m->g0 && gp != m->gsignal)
runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LR(info, ctxt), gp);
return;
}
......@@ -52,27 +54,33 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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*)((byte*)info + 12); /* si_addr */
gp->sigpc = r->sc_eip;
// Only push runtime·sigpanic if r->sc_eip != 0.
// If r->sc_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(r->sc_eip != 0) {
sp = (uintptr*)r->sc_esp;
*--sp = r->sc_eip;
r->sc_esp = (uintptr)sp;
}
r->sc_eip = (uintptr)runtime·sigpanic;
gp->sigcode0 = SIG_CODE0(info, ctxt);
gp->sigcode1 = SIG_FAULT_ADDRESS(info, ctxt);
gp->sigpc = SIG_PC(info, ctxt);
// We arrange lr, and pc to pretend the panicking
// function calls sigpanic directly.
// Always save LR to stack so that panics in leaf
// functions are correctly handled. This smashes
// the stack frame but we're not going back there
// anyway.
SIG_SP(info, ctxt) -= 4;
*(uint32*)SIG_SP(info, ctxt) = SIG_LR(info, ctxt);
// Don't bother saving PC if it's zero, which is
// probably a call to a nil func: the old link register
// is more useful in the stack trace.
if(gp->sigpc != 0)
SIG_LR(info, ctxt) = gp->sigpc;
// In case we are panicking from external C code
SIG_R10(info, ctxt) = (uintptr)gp;
SIG_R9(info, ctxt) = (uintptr)m;
SIG_PC(info, ctxt) = (uintptr)runtime·sigpanic;
return;
}
......@@ -85,14 +93,16 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
return;
Throw:
runtime·startpanic();
if(runtime·panicking) // traceback already printed
runtime·exit(2);
runtime·panicking = 1;
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", r->sc_eip);
runtime·printf("PC=%x\n", SIG_PC(info, ctxt));
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
......@@ -100,48 +110,11 @@ Throw:
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->sc_eip, (void*)r->sc_esp, 0, gp);
runtime·traceback((void*)SIG_PC(info, ctxt), (void*)SIG_SP(info, ctxt), (void*)SIG_LR(info, ctxt), gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(r);
}
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask = ~0ULL;
if (fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.__sigaction_u.__sa_sigaction = (void*)fn;
runtime·sigaction(i, &sa, nil);
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext->ss)
#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).eax)
#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).ebx)
#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).ecx)
#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).edx)
#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).edi)
#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).esi)
#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).ebp)
#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).esp)
#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).eip)
#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).eflags)
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).cs)
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).fs)
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gs)
#define SIG_CODE0(info, ctxt) ((info)->si_code)
#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
// Copyright 2013 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.
#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext->ss)
#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax)
#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx)
#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).rcx)
#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).rdx)
#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).rdi)
#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).rsi)
#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).rbp)
#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).rsp)
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).r11)
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).r12)
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).r13)
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).r14)
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).r15)
#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).rip)
#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).rflags)
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).cs)
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).fs)
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gs)
#define SIG_CODE0(info, ctxt) ((info)->si_code)
#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
// 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·sigtramp(void);
typedef struct sigaction {
union {
void (*__sa_handler)(int32);
void (*__sa_sigaction)(int32, Siginfo*, void *);
} __sigaction_u; /* signal handler */
int32 sa_flags; /* see signal options below */
Sigset sa_mask; /* signal mask to apply */
} Sigaction;
void
runtime·dumpregs(Mcontext *r)
{
runtime·printf("eax %x\n", r->mc_eax);
runtime·printf("ebx %x\n", r->mc_ebx);
runtime·printf("ecx %x\n", r->mc_ecx);
runtime·printf("edx %x\n", r->mc_edx);
runtime·printf("edi %x\n", r->mc_edi);
runtime·printf("esi %x\n", r->mc_esi);
runtime·printf("ebp %x\n", r->mc_ebp);
runtime·printf("esp %x\n", r->mc_esp);
runtime·printf("eip %x\n", r->mc_eip);
runtime·printf("eflags %x\n", r->mc_eflags);
runtime·printf("cs %x\n", r->mc_cs);
runtime·printf("fs %x\n", r->mc_fs);
runtime·printf("gs %x\n", r->mc_gs);
}
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
Ucontext *uc;
Mcontext *r;
uintptr *sp;
SigTab *t;
uc = context;
r = &uc->uc_mcontext;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)r->mc_eip, (uint8*)r->mc_esp, nil, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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;
gp->sigpc = r->mc_eip;
// Only push runtime·sigpanic if r->mc_eip != 0.
// If r->mc_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(r->mc_eip != 0) {
sp = (uintptr*)r->mc_esp;
*--sp = r->mc_eip;
r->mc_esp = (uintptr)sp;
}
r->mc_eip = (uintptr)runtime·sigpanic;
return;
}
if(info->si_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", r->mc_eip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->mc_eip, (void*)r->mc_esp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
}
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = (int8*)p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask.__bits[0] = ~(uint32)0;
sa.sa_mask.__bits[1] = ~(uint32)0;
sa.sa_mask.__bits[2] = ~(uint32)0;
sa.sa_mask.__bits[3] = ~(uint32)0;
if (fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.__sigaction_u.__sa_sigaction = (void*)fn;
runtime·sigaction(i, &sa, nil);
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*((Ucontext*)(ctxt))->uc_mcontext)
#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).mc_eax)
#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).mc_ebx)
#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).mc_ecx)
#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).mc_edx)
#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).mc_edi)
#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).mc_esi)
#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).mc_ebp)
#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).mc_esp)
#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).mc_eip)
#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).mc_eflags)
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).mc_cs)
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).mc_fs)
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).mc_gs)
#define SIG_CODE0(info, ctxt) ((info)->si_code)
#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
// 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·sigtramp(void);
typedef struct sigaction {
union {
void (*__sa_handler)(int32);
void (*__sa_sigaction)(int32, Siginfo*, void *);
} __sigaction_u; /* signal handler */
int32 sa_flags; /* see signal options below */
Sigset sa_mask; /* signal mask to apply */
} Sigaction;
void
runtime·dumpregs(Mcontext *r)
{
runtime·printf("rax %X\n", r->mc_rax);
runtime·printf("rbx %X\n", r->mc_rbx);
runtime·printf("rcx %X\n", r->mc_rcx);
runtime·printf("rdx %X\n", r->mc_rdx);
runtime·printf("rdi %X\n", r->mc_rdi);
runtime·printf("rsi %X\n", r->mc_rsi);
runtime·printf("rbp %X\n", r->mc_rbp);
runtime·printf("rsp %X\n", r->mc_rsp);
runtime·printf("r8 %X\n", r->mc_r8 );
runtime·printf("r9 %X\n", r->mc_r9 );
runtime·printf("r10 %X\n", r->mc_r10);
runtime·printf("r11 %X\n", r->mc_r11);
runtime·printf("r12 %X\n", r->mc_r12);
runtime·printf("r13 %X\n", r->mc_r13);
runtime·printf("r14 %X\n", r->mc_r14);
runtime·printf("r15 %X\n", r->mc_r15);
runtime·printf("rip %X\n", r->mc_rip);
runtime·printf("rflags %X\n", r->mc_flags);
runtime·printf("cs %X\n", r->mc_cs);
runtime·printf("fs %X\n", r->mc_fs);
runtime·printf("gs %X\n", r->mc_gs);
}
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
Ucontext *uc;
Mcontext *r;
uintptr *sp;
SigTab *t;
uc = context;
r = &uc->uc_mcontext;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)r->mc_rip, (uint8*)r->mc_rsp, nil, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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;
gp->sigpc = r->mc_rip;
// Only push runtime·sigpanic if r->mc_rip != 0.
// If r->mc_rip == 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(r->mc_rip != 0) {
sp = (uintptr*)r->mc_rsp;
*--sp = r->mc_rip;
r->mc_rsp = (uintptr)sp;
}
r->mc_rip = (uintptr)runtime·sigpanic;
return;
}
if(info->si_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", r->mc_rip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->mc_rip, (void*)r->mc_rsp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
}
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = (int8*)p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask.__bits[0] = ~(uint32)0;
sa.sa_mask.__bits[1] = ~(uint32)0;
sa.sa_mask.__bits[2] = ~(uint32)0;
sa.sa_mask.__bits[3] = ~(uint32)0;
if (fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.__sigaction_u.__sa_sigaction = (void*)fn;
runtime·sigaction(i, &sa, nil);
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*((Ucontext*)(ctxt))->uc_mcontext)
#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).mc_rax)
#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).mc_rbx)
#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).mc_rcx)
#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).mc_rdx)
#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).mc_rdi)
#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).mc_rsi)
#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).mc_rbp)
#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).mc_rsp)
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).mc_r8)
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).mc_r9)
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).mc_r10)
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).mc_r11)
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).mc_r12)
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).mc_r13)
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).mc_r14)
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).mc_r15)
#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).mc_rip)
#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).mc_rflags)
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).mc_cs)
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).mc_fs)
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).mc_gs)
#define SIG_CODE0(info, ctxt) ((info)->si_code)
#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
// Copyright 2012 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"
#define r0 __gregs[0]
#define r1 __gregs[1]
#define r2 __gregs[2]
#define r3 __gregs[3]
#define r4 __gregs[4]
#define r5 __gregs[5]
#define r6 __gregs[6]
#define r7 __gregs[7]
#define r8 __gregs[8]
#define r9 __gregs[9]
#define r10 __gregs[10]
#define r11 __gregs[11]
#define r12 __gregs[12]
#define r13 __gregs[13]
#define r14 __gregs[14]
#define r15 __gregs[15]
#define cpsr __gregs[16]
void
runtime·dumpregs(Mcontext *r)
{
runtime·printf("r0 %x\n", r->r0);
runtime·printf("r1 %x\n", r->r1);
runtime·printf("r2 %x\n", r->r2);
runtime·printf("r3 %x\n", r->r3);
runtime·printf("r4 %x\n", r->r4);
runtime·printf("r5 %x\n", r->r5);
runtime·printf("r6 %x\n", r->r6);
runtime·printf("r7 %x\n", r->r7);
runtime·printf("r8 %x\n", r->r8);
runtime·printf("r9 %x\n", r->r9);
runtime·printf("r10 %x\n", r->r10);
runtime·printf("fp %x\n", r->r11);
runtime·printf("ip %x\n", r->r12);
runtime·printf("sp %x\n", r->r13);
runtime·printf("lr %x\n", r->r14);
runtime·printf("pc %x\n", r->r15);
runtime·printf("cpsr %x\n", r->cpsr);
}
extern void runtime·sigtramp(void);
typedef struct sigaction {
union {
void (*__sa_handler)(int32);
void (*__sa_sigaction)(int32, Siginfo*, void *);
} __sigaction_u; /* signal handler */
int32 sa_flags; /* see signal options below */
Sigset sa_mask; /* signal mask to apply */
} Sigaction;
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
Ucontext *uc;
Mcontext *r;
SigTab *t;
uc = context;
r = &uc->uc_mcontext;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)r->r15, (uint8*)r->r13, (uint8*)r->r14, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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;
gp->sigpc = r->r15;
// Only push runtime·sigpanic if r->mc_rip != 0.
// If r->mc_rip == 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(r->r15 != 0)
r->r14 = r->r15;
// In case we are panicking from external C code
r->r10 = (uintptr)gp;
r->r9 = (uintptr)m;
r->r15 = (uintptr)runtime·sigpanic;
return;
}
if(info->si_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", r->r15);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->r15, (void*)r->r13, (void*)r->r14, gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(r);
}
// breakpoint();
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = (uint8*)p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask.__bits[0] = ~(uint32)0;
sa.sa_mask.__bits[1] = ~(uint32)0;
sa.sa_mask.__bits[2] = ~(uint32)0;
sa.sa_mask.__bits[3] = ~(uint32)0;
if (fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.__sigaction_u.__sa_sigaction = (void*)fn;
runtime·sigaction(i, &sa, nil);
}
void
runtime·checkgoarm(void)
{
// TODO(minux)
}
#pragma textflag 7
int64
runtime·cputicks(void)
{
// Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
// runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
// TODO: need more entropy to better seed fastrand1.
return runtime·nanotime();
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).__gregs[0])
#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).__gregs[1])
#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).__gregs[2])
#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).__gregs[3])
#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).__gregs[4])
#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).__gregs[5])
#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).__gregs[6])
#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).__gregs[7])
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).__gregs[8])
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).__gregs[9])
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).__gregs[10])
#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).__gregs[11])
#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).__gregs[12])
#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).__gregs[13])
#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).__gregs[14])
#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).__gregs[15])
#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).__gregs[16])
#define SIG_FAULT(info, ctxt) ((uintptr)(info)->si_addr)
#define SIG_TRAP(info, ctxt) (0)
#define SIG_ERROR(info, ctxt) (0)
#define SIG_OLDMASK(info, ctxt) (0)
// 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"
void
runtime·dumpregs(Sigcontext *r)
{
runtime·printf("eax %x\n", r->eax);
runtime·printf("ebx %x\n", r->ebx);
runtime·printf("ecx %x\n", r->ecx);
runtime·printf("edx %x\n", r->edx);
runtime·printf("edi %x\n", r->edi);
runtime·printf("esi %x\n", r->esi);
runtime·printf("ebp %x\n", r->ebp);
runtime·printf("esp %x\n", r->esp);
runtime·printf("eip %x\n", r->eip);
runtime·printf("eflags %x\n", r->eflags);
runtime·printf("cs %x\n", r->cs);
runtime·printf("fs %x\n", r->fs);
runtime·printf("gs %x\n", r->gs);
}
/*
* This assembler routine takes the args from registers, puts them on the stack,
* and calls sighandler().
*/
extern void runtime·sigtramp(void);
extern void runtime·sigreturn(void); // calls runtime·sigreturn
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
Ucontext *uc;
Sigcontext *r;
uintptr *sp;
SigTab *t;
uc = context;
r = &uc->uc_mcontext;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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];
gp->sigpc = r->eip;
// Only push runtime·sigpanic if r->eip != 0.
// If r->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(r->eip != 0) {
sp = (uintptr*)r->esp;
*--sp = r->eip;
r->esp = (uintptr)sp;
}
r->eip = (uintptr)runtime·sigpanic;
return;
}
if(info->si_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", r->eip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
}
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
runtime·throw("rt_sigaction read failure");
if(sa.k_sa_handler == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask = ~0ULL;
sa.sa_restorer = (void*)runtime·sigreturn;
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.k_sa_handler = fn;
if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
runtime·throw("rt_sigaction failure");
}
#define AT_NULL 0
#define AT_RANDOM 25
#define AT_SYSINFO 32
extern uint32 runtime·_vdso;
#pragma textflag 7
void
runtime·linux_setup_vdso(int32 argc, byte **argv)
{
byte **envp;
uint32 *auxv;
// skip envp to get to ELF auxiliary vector.
for(envp = &argv[argc+1]; *envp != nil; envp++)
;
envp++;
for(auxv=(uint32*)envp; auxv[0] != AT_NULL; auxv += 2) {
if(auxv[0] == AT_SYSINFO) {
runtime·_vdso = auxv[1];
continue;
}
if(auxv[0] == AT_RANDOM) {
runtime·startup_random_data = (byte*)auxv[1];
runtime·startup_random_data_len = 16;
continue;
}
}
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).eax)
#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).ebx)
#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).ecx)
#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).edx)
#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).edi)
#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).esi)
#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).ebp)
#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).esp)
#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).eip)
#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).eflags)
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).cs)
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).fs)
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gs)
#define SIG_CODE0(info, ctxt) ((info)->si_code)
#define SIG_CODE1(info, ctxt) (((uintptr*)(info))[2])
// 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"
void
runtime·dumpregs(Sigcontext *r)
{
runtime·printf("rax %X\n", r->rax);
runtime·printf("rbx %X\n", r->rbx);
runtime·printf("rcx %X\n", r->rcx);
runtime·printf("rdx %X\n", r->rdx);
runtime·printf("rdi %X\n", r->rdi);
runtime·printf("rsi %X\n", r->rsi);
runtime·printf("rbp %X\n", r->rbp);
runtime·printf("rsp %X\n", r->rsp);
runtime·printf("r8 %X\n", r->r8 );
runtime·printf("r9 %X\n", r->r9 );
runtime·printf("r10 %X\n", r->r10);
runtime·printf("r11 %X\n", r->r11);
runtime·printf("r12 %X\n", r->r12);
runtime·printf("r13 %X\n", r->r13);
runtime·printf("r14 %X\n", r->r14);
runtime·printf("r15 %X\n", r->r15);
runtime·printf("rip %X\n", r->rip);
runtime·printf("rflags %X\n", r->eflags);
runtime·printf("cs %X\n", (uint64)r->cs);
runtime·printf("fs %X\n", (uint64)r->fs);
runtime·printf("gs %X\n", (uint64)r->gs);
}
/*
* This assembler routine takes the args from registers, puts them on the stack,
* and calls sighandler().
*/
extern void runtime·sigtramp(void);
extern void runtime·sigreturn(void); // calls runtime·sigreturn
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
Ucontext *uc;
Mcontext *mc;
Sigcontext *r;
uintptr *sp;
SigTab *t;
uc = context;
mc = &uc->uc_mcontext;
r = (Sigcontext*)mc; // same layout, more conveient names
if(sig == SIGPROF) {
runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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];
gp->sigpc = r->rip;
// Only push runtime·sigpanic if r->rip != 0.
// If r->rip == 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(r->rip != 0) {
sp = (uintptr*)r->rsp;
*--sp = r->rip;
r->rsp = (uintptr)sp;
}
r->rip = (uintptr)runtime·sigpanic;
return;
}
if(info->si_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", r->rip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
}
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
runtime·throw("rt_sigaction read failure");
if(sa.sa_handler == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask = ~0ULL;
// TODO(adonovan): Linux manpage says "sa_restorer element is
// obsolete and should not be used". Avoid it here, and test.
sa.sa_restorer = (void*)runtime·sigreturn;
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.sa_handler = fn;
if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
runtime·throw("rt_sigaction failure");
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax)
#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx)
#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).rcx)
#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).rdx)
#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).rdi)
#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).rsi)
#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).rbp)
#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).rsp)
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).r11)
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).r12)
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).r13)
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).r14)
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).r15)
#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).rip)
#define SIG_RFLAGS(info, ctxt) ((uint64)SIG_REGS(ctxt).eflags)
#define SIG_CS(info, ctxt) ((uint64)SIG_REGS(ctxt).cs)
#define SIG_FS(info, ctxt) ((uint64)SIG_REGS(ctxt).fs)
#define SIG_GS(info, ctxt) ((uint64)SIG_REGS(ctxt).gs)
#define SIG_CODE0(info, ctxt) ((info)->si_code)
#define SIG_CODE1(info, ctxt) (((uintptr*)(info))[2])
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).arm_r0)
#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).arm_r1)
#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).arm_r2)
#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).arm_r3)
#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).arm_r4)
#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).arm_r5)
#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).arm_r6)
#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).arm_r7)
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).arm_r8)
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).arm_r9)
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).arm_r10)
#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).arm_fp)
#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).arm_ip)
#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).arm_sp)
#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).arm_lr)
#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).arm_pc)
#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).arm_cpsr)
#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).fault_address)
#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap_no)
#define SIG_ERROR(info, ctxt) (SIG_REGS(ctxt).error_code)
#define SIG_OLDMASK(info, ctxt) (SIG_REGS(ctxt).oldmask)
// 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 || gp == m->g0)
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]);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
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;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(sa._sa_u._sa_sigaction == SIG_IGN)
return;
}
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 *mp, G *gp, void (*fn)(void))
{
mc->__gregs[REG_EIP] = (uint32)runtime·lwp_tramp;
mc->__gregs[REG_UESP] = (uint32)stack;
mc->__gregs[REG_EBX] = (uint32)mp;
mc->__gregs[REG_EDX] = (uint32)gp;
mc->__gregs[REG_ESI] = (uint32)fn;
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EAX])
#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EBX])
#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_ECX])
#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EDX])
#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EDI])
#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_ESI])
#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EBP])
#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_ESP])
#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EIP])
#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EFLAGS])
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_CS])
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_FS])
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_GS])
#define SIG_CODE0(info, ctxt) ((info)->_code)
#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->_reason[0])
// 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("rax %X\n", mc->__gregs[REG_RAX]);
runtime·printf("rbx %X\n", mc->__gregs[REG_RBX]);
runtime·printf("rcx %X\n", mc->__gregs[REG_RCX]);
runtime·printf("rdx %X\n", mc->__gregs[REG_RDX]);
runtime·printf("rdi %X\n", mc->__gregs[REG_RDI]);
runtime·printf("rsi %X\n", mc->__gregs[REG_RSI]);
runtime·printf("rbp %X\n", mc->__gregs[REG_RBP]);
runtime·printf("rsp %X\n", mc->__gregs[REG_RSP]);
runtime·printf("r8 %X\n", mc->__gregs[REG_R8]);
runtime·printf("r9 %X\n", mc->__gregs[REG_R9]);
runtime·printf("r10 %X\n", mc->__gregs[REG_R10]);
runtime·printf("r11 %X\n", mc->__gregs[REG_R11]);
runtime·printf("r12 %X\n", mc->__gregs[REG_R12]);
runtime·printf("r13 %X\n", mc->__gregs[REG_R13]);
runtime·printf("r14 %X\n", mc->__gregs[REG_R14]);
runtime·printf("r15 %X\n", mc->__gregs[REG_R15]);
runtime·printf("rip %X\n", mc->__gregs[REG_RIP]);
runtime·printf("rflags %X\n", mc->__gregs[REG_RFLAGS]);
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_RIP],
(uint8*)mc->__gregs[REG_RSP], nil, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
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_RIP];
// Only push runtime·sigpanic if __gregs[REG_RIP] != 0.
// If __gregs[REG_RIP] == 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_RIP] != 0) {
sp = (uintptr*)mc->__gregs[REG_RSP];
*--sp = mc->__gregs[REG_RIP];
mc->__gregs[REG_RSP] = (uintptr)sp;
}
mc->__gregs[REG_RIP] = (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_RIP]);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)mc->__gregs[REG_RIP],
(void*)mc->__gregs[REG_RSP], 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;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(sa._sa_u._sa_sigaction == SIG_IGN)
return;
}
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 *mp, G *gp, void (*fn)(void))
{
// Machine dependent mcontext initialisation for LWP.
mc->__gregs[REG_RIP] = (uint64)runtime·lwp_tramp;
mc->__gregs[REG_RSP] = (uint64)stack;
mc->__gregs[REG_R8] = (uint64)mp;
mc->__gregs[REG_R9] = (uint64)gp;
mc->__gregs[REG_R12] = (uint64)fn;
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RAX])
#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RBX])
#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RCX])
#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RDX])
#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RDI])
#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RSI])
#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RBP])
#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RSP])
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R8])
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R9])
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R10])
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R11])
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R12])
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R13])
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R14])
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R15])
#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RIP])
#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RFLAGS])
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_CS])
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_FS])
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_GS])
#define SIG_CODE0(info, ctxt) ((info)->_code)
#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->_reason[0])
// Copyright 2013 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"
#define r0 __gregs[0]
#define r1 __gregs[1]
#define r2 __gregs[2]
#define r3 __gregs[3]
#define r4 __gregs[4]
#define r5 __gregs[5]
#define r6 __gregs[6]
#define r7 __gregs[7]
#define r8 __gregs[8]
#define r9 __gregs[9]
#define r10 __gregs[10]
#define r11 __gregs[11]
#define r12 __gregs[12]
#define r13 __gregs[13]
#define r14 __gregs[14]
#define r15 __gregs[15]
#define cpsr __gregs[16]
void
runtime·dumpregs(McontextT *r)
{
runtime·printf("r0 %x\n", r->r0);
runtime·printf("r1 %x\n", r->r1);
runtime·printf("r2 %x\n", r->r2);
runtime·printf("r3 %x\n", r->r3);
runtime·printf("r4 %x\n", r->r4);
runtime·printf("r5 %x\n", r->r5);
runtime·printf("r6 %x\n", r->r6);
runtime·printf("r7 %x\n", r->r7);
runtime·printf("r8 %x\n", r->r8);
runtime·printf("r9 %x\n", r->r9);
runtime·printf("r10 %x\n", r->r10);
runtime·printf("fp %x\n", r->r11);
runtime·printf("ip %x\n", r->r12);
runtime·printf("sp %x\n", r->r13);
runtime·printf("lr %x\n", r->r14);
runtime·printf("pc %x\n", r->r15);
runtime·printf("cpsr %x\n", r->cpsr);
}
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·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
UcontextT *uc;
McontextT *r;
SigTab *t;
uc = context;
r = &uc->uc_mcontext;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)r->r15, (uint8*)r->r13, (uint8*)r->r14, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// Make it look like a call to the signal func.
// We have 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 = r->r15;
// We arrange lr, and pc to pretend the panicking
// function calls sigpanic directly.
// Always save LR to stack so that panics in leaf
// functions are correctly handled. This smashes
// the stack frame but we're not going back there
// anyway.
r->r13 -= 4;
*(uint32 *)r->r13 = r->r14;
// Don't bother saving PC if it's zero, which is
// probably a call to a nil func: the old link register
// is more useful in the stack trace.
if(r->r15 != 0)
r->r14 = r->r15;
// In case we are panicking from external C code
r->r10 = (uintptr)gp;
r->r9 = (uintptr)m;
r->r15 = (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", r->r15);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->r15, (void*)r->r13, (void*)r->r14, gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(r);
}
// breakpoint();
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = (uint8*)p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(sa._sa_u._sa_sigaction == SIG_IGN)
return;
}
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 *mp, G *gp, void (*fn)(void))
{
mc->r15 = (uint32)runtime·lwp_tramp;
mc->r13 = (uint32)stack;
mc->r0 = (uint32)mp;
mc->r1 = (uint32)gp;
mc->r2 = (uint32)fn;
}
void
runtime·checkgoarm(void)
{
// TODO(minux)
}
#pragma textflag 7
int64
runtime·cputicks() {
// Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
// runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
// TODO: need more entropy to better seed fastrand1.
return runtime·nanotime();
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).__gregs[0])
#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).__gregs[1])
#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).__gregs[2])
#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).__gregs[3])
#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).__gregs[4])
#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).__gregs[5])
#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).__gregs[6])
#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).__gregs[7])
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).__gregs[8])
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).__gregs[9])
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).__gregs[10])
#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).__gregs[11])
#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).__gregs[12])
#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).__gregs[13])
#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).__gregs[14])
#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).__gregs[15])
#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).__gregs[16])
#define SIG_FAULT(info, ctxt) (*(uintptr*)&(info)->_reason[0])
#define SIG_TRAP(info, ctxt) (0)
#define SIG_ERROR(info, ctxt) (0)
#define SIG_OLDMASK(info, ctxt) (0)
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*(Sigcontext*)(ctxt))
#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).sc_eax)
#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).sc_ebx)
#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).sc_ecx)
#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).sc_edx)
#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).sc_edi)
#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).sc_esi)
#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).sc_ebp)
#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).sc_esp)
#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).sc_eip)
#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).sc_eflags)
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).sc_cs)
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).sc_fs)
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).sc_gs)
#define SIG_CODE0(info, ctxt) ((info)->si_code)
#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
// 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·sigtramp(void);
typedef struct sigaction {
union {
void (*__sa_handler)(int32);
void (*__sa_sigaction)(int32, Siginfo*, void *);
} __sigaction_u; /* signal handler */
uint32 sa_mask; /* signal mask to apply */
int32 sa_flags; /* see signal options below */
} Sigaction;
void
runtime·dumpregs(Sigcontext *r)
{
runtime·printf("rax %X\n", r->sc_rax);
runtime·printf("rbx %X\n", r->sc_rbx);
runtime·printf("rcx %X\n", r->sc_rcx);
runtime·printf("rdx %X\n", r->sc_rdx);
runtime·printf("rdi %X\n", r->sc_rdi);
runtime·printf("rsi %X\n", r->sc_rsi);
runtime·printf("rbp %X\n", r->sc_rbp);
runtime·printf("rsp %X\n", r->sc_rsp);
runtime·printf("r8 %X\n", r->sc_r8);
runtime·printf("r9 %X\n", r->sc_r9);
runtime·printf("r10 %X\n", r->sc_r10);
runtime·printf("r11 %X\n", r->sc_r11);
runtime·printf("r12 %X\n", r->sc_r12);
runtime·printf("r13 %X\n", r->sc_r13);
runtime·printf("r14 %X\n", r->sc_r14);
runtime·printf("r15 %X\n", r->sc_r15);
runtime·printf("rip %X\n", r->sc_rip);
runtime·printf("rflags %X\n", r->sc_rflags);
runtime·printf("cs %X\n", r->sc_cs);
runtime·printf("fs %X\n", r->sc_fs);
runtime·printf("gs %X\n", r->sc_gs);
}
void
runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
{
Sigcontext *r = context;
uintptr *sp;
SigTab *t;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)r->sc_rip,
(uint8*)r->sc_rsp, nil, gp);
return;
}
t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0)
goto Throw;
// 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*)((byte*)info + 16); /* si_addr */
gp->sigpc = r->sc_rip;
// Only push runtime·sigpanic if r->sc_rip != 0.
// If r->sc_rip == 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(r->sc_rip != 0) {
sp = (uintptr*)r->sc_rsp;
*--sp = r->sc_rip;
r->sc_rsp = (uintptr)sp;
}
r->sc_rip = (uintptr)runtime·sigpanic;
return;
}
if(info->si_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", r->sc_rip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback((void*)r->sc_rip, (void*)r->sc_rsp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
}
runtime·exit(2);
}
void
runtime·signalstack(byte *p, int32 n)
{
Sigaltstack st;
st.ss_sp = p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
{
Sigaction sa;
// If SIGHUP handler is SIG_IGN, assume running
// under nohup and do not set explicit handler.
if(i == SIGHUP) {
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
return;
}
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask = ~0U;
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.__sigaction_u.__sa_sigaction = (void*)fn;
runtime·sigaction(i, &sa, nil);
}
// Copyright 2013 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.
#define SIG_REGS(ctxt) (*(Sigcontext*)(ctxt))
#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).sc_rax)
#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).sc_rbx)
#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).sc_rcx)
#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).sc_rdx)
#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).sc_rdi)
#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).sc_rsi)
#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).sc_rbp)
#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).sc_rsp)
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).sc_r8)
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).sc_r9)
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).sc_r10)
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).sc_r11)
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).sc_r12)
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).sc_r13)
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).sc_r14)
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).sc_r15)
#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).sc_rip)
#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).sc_rflags)
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).sc_cs)
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).sc_fs)
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).sc_gs)
#define SIG_CODE0(info, ctxt) ((info)->si_code)
#define SIG_CODE1(info, ctxt) (*(uintptr*)((byte*)(info) + 16))
......@@ -7,6 +7,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_unix.h"
extern SigTab runtime·sigtab[];
......
// Copyright 2013 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.
#define SIG_DFL ((void*)0)
#define SIG_IGN ((void*)1)
typedef void GoSighandler(int32, Siginfo*, void*, G*);
void runtime·setsig(int32, GoSighandler*, bool);
GoSighandler* runtime·getsig(int32);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
void runtime·raisesigpipe(void);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment