type Xmmreg1 C.struct__xmmreg
type Fpstate1 C.struct__fpstate
type Fpreg1 C.struct__fpreg
-type SigaltstackT C.struct_sigaltstack
+type StackT C.stack_t
type Mcontext C.mcontext_t
type Ucontext C.ucontext_t
type Sigcontext C.struct_sigcontext
_EVFILT_WRITE = 0x1
)
-type sigaltstackt struct {
- ss_sp uintptr
- ss_size uintptr
- ss_flags int32
-}
-
type sigset struct {
__bits [4]uint32
}
_EVFILT_WRITE = 0x1
)
-type sigaltstackt struct {
- ss_sp uintptr
- ss_size uintptr
- ss_flags int32
- pad_cgo_0 [4]byte
-}
-
type sigset struct {
__bits [4]uint32
}
_EVFILT_WRITE = 0x1
)
-type sigaltstackt struct {
- ss_sp uintptr
- ss_size uintptr
- ss_flags int32
-}
-
type sigset struct {
__bits [4]uint32
}
sem_pad2 [2]uint64
}
-type sigaltstackt struct {
- ss_sp *byte
- ss_size uint64
- ss_flags int32
- pad_cgo_0 [4]byte
-}
-
type sigset struct {
__sigbits [4]uint32
}
type stackt struct {
ss_sp *byte
- ss_size uint64
+ ss_size uintptr
ss_flags int32
pad_cgo_0 [4]byte
}
type Timeval C.struct_timeval
type Sigaction C.struct_kernel_sigaction
type Siginfo C.siginfo_t
-type SigaltstackT C.struct_sigaltstack
+type StackT C.stack_t
type Sigcontext C.struct_sigcontext
type Ucontext C.struct_ucontext
type Itimerval C.struct_itimerval
type FPregset C.elf_fpregset_t
type Vreg C.elf_vrreg_t
-type SigaltstackT C.struct_sigaltstack
+type StackT C.stack_t
// PPC64 uses sigcontext in place of mcontext in ucontext.
// see http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/powerpc/include/uapi/asm/ucontext.h
)
type Timespec C.struct_timespec
-type SigaltstackT C.struct_sigaltstack
+type StackT C.stack_t
type Sigcontext C.struct_sigcontext
type Ucontext C.struct_ucontext
type Timeval C.struct_timeval
type Rtprio C.struct_rtprio
type Lwpparams C.struct_lwp_params
-type SigaltstackT C.struct_sigaltstack
type Sigset C.struct___sigset
type StackT C.stack_t
tid2 unsafe.Pointer // *int32
}
-type sigaltstackt struct {
- ss_sp uintptr
- ss_size uintptr
- ss_flags int32
- pad_cgo_0 [4]byte
-}
-
type sigset struct {
__bits [4]uint32
}
type Rtprio C.struct_rtprio
type ThrParam C.struct_thr_param
-type SigaltstackT C.struct_sigaltstack
type Sigset C.struct___sigset
type StackT C.stack_t
spare [3]uintptr
}
-type sigaltstackt struct {
- ss_sp *int8
- ss_size uint32
- ss_flags int32
-}
-
type sigset struct {
__bits [4]uint32
}
spare [3]uintptr
}
-type sigaltstackt struct {
- ss_sp *int8
- ss_size uint64
- ss_flags int32
- pad_cgo_0 [4]byte
-}
-
type sigset struct {
__bits [4]uint32
}
spare [3]uintptr
}
-type sigaltstackt struct {
- ss_sp *uint8
- ss_size uint32
- ss_flags int32
-}
-
type sigset struct {
__bits [4]uint32
}
si_addr uint32
}
-type sigaltstackt struct {
+type stackt struct {
ss_sp *byte
ss_flags int32
ss_size uintptr
type ucontext struct {
uc_flags uint32
uc_link *ucontext
- uc_stack sigaltstackt
+ uc_stack stackt
uc_mcontext sigcontext
uc_sigmask uint32
}
exponent uint16
}
-type sigaltstackt struct {
+type stackt struct {
ss_sp *byte
ss_flags int32
pad_cgo_0 [4]byte
type ucontext struct {
uc_flags uint64
uc_link *ucontext
- uc_stack sigaltstackt
+ uc_stack stackt
uc_mcontext mcontext
uc_sigmask usigset
__fpregs_mem fpstate
ts.tv_nsec = x
}
-type sigaltstackt struct {
+type stackt struct {
ss_sp *byte
ss_flags int32
ss_size uintptr
type ucontext struct {
uc_flags uint32
uc_link *ucontext
- uc_stack sigaltstackt
+ uc_stack stackt
uc_mcontext sigcontext
uc_sigmask uint32
__unused [31]int32
__val [16]uint64
}
-type sigaltstackt struct {
+type stackt struct {
ss_sp *byte
ss_flags int32
pad_cgo_0 [4]byte
type ucontext struct {
uc_flags uint64
uc_link *ucontext
- uc_stack sigaltstackt
+ uc_stack stackt
uc_sigmask uint64
_pad [(1024 - 64) / 8]byte
_pad2 [8]byte // sigcontext must be aligned to 16-byte
_SA_RESTORER = 0
)
-type sigaltstackt struct {
+type stackt struct {
ss_sp *byte
ss_size uintptr
ss_flags int32
type ucontext struct {
uc_flags uint64
uc_link *ucontext
- uc_stack sigaltstackt
+ uc_stack stackt
uc_mcontext sigcontext
uc_sigmask uint64
}
u [4]uint32
}
-type sigaltstackt struct {
+type stackt struct {
ss_sp *byte
ss_flags int32
pad_cgo_0 [4]byte
type ucontext struct {
uc_flags uint64
uc_link *ucontext
- uc_stack sigaltstackt
+ uc_stack stackt
uc_sigmask uint64
__unused [15]uint64
uc_mcontext sigcontext
u [4]uint32
}
-type sigaltstackt struct {
+type stackt struct {
ss_sp *byte
ss_flags int32
pad_cgo_0 [4]byte
type ucontext struct {
uc_flags uint64
uc_link *ucontext
- uc_stack sigaltstackt
+ uc_stack stackt
uc_sigmask uint64
__unused [15]uint64
uc_mcontext sigcontext
_SA_RESTORER = 0
)
-type sigaltstackt struct {
+type stackt struct {
ss_sp *byte
ss_flags int32
ss_size uintptr
type ucontext struct {
uc_flags uint64
uc_link *ucontext
- uc_stack sigaltstackt
+ uc_stack stackt
uc_mcontext sigcontext
uc_sigmask uint64
}
EVFILT_WRITE = C.EVFILT_WRITE
)
-type SigaltstackT C.struct_sigaltstack
type Sigset C.sigset_t
type Siginfo C.struct__ksiginfo
type TforkT C.struct___tfork
-type SigaltstackT C.struct_sigaltstack
type Sigcontext C.struct_sigcontext
type Siginfo C.siginfo_t
type Sigset C.sigset_t
tf_stack uintptr
}
-type sigaltstackt struct {
- ss_sp uintptr
- ss_size uintptr
- ss_flags int32
-}
-
type sigcontext struct {
sc_gs uint32
sc_fs uint32
tf_stack uintptr
}
-type sigaltstackt struct {
- ss_sp uintptr
- ss_size uintptr
- ss_flags int32
- pad_cgo_0 [4]byte
-}
-
type sigcontext struct {
sc_rdi uint64
sc_rsi uint64
tf_stack uintptr
}
-type sigaltstackt struct {
- ss_sp uintptr
- ss_size uintptr
- ss_flags int32
-}
-
type sigcontext struct {
__sc_unused int32
sc_mask int32
type SemT C.sem_t
-type SigaltstackT C.struct_sigaltstack
type Sigset C.sigset_t
type StackT C.stack_t
func minit() {
_g_ := getg()
asmcgocall(unsafe.Pointer(funcPC(miniterrno)), unsafe.Pointer(&libc____errno))
- // Initialize signal handling
- var st sigaltstackt
- sigaltstack(nil, &st)
- if st.ss_flags&_SS_DISABLE != 0 {
- signalstack(&_g_.m.gsignal.stack)
- _g_.m.newSigstack = true
- } else {
- // Use existing signal stack.
- stsp := uintptr(unsafe.Pointer(st.ss_sp))
- _g_.m.gsignal.stack.lo = stsp
- _g_.m.gsignal.stack.hi = stsp + uintptr(st.ss_size)
- _g_.m.gsignal.stackguard0 = stsp + _StackGuard
- _g_.m.gsignal.stackguard1 = stsp + _StackGuard
- _g_.m.gsignal.stackAlloc = uintptr(st.ss_size)
- _g_.m.newSigstack = false
- }
+
+ minitSignalStack()
// restore signal mask from m.sigmask and unblock essential signals
nmask := _g_.m.sigmask
return *((*uintptr)(unsafe.Pointer(&sa._funcptr)))
}
+// setSignaltstackSP sets the ss_sp field of a stackt.
//go:nosplit
-func signalstack(s *stack) {
- var st sigaltstackt
- if s == nil {
- st.ss_flags = _SS_DISABLE
- } else {
- st.ss_sp = (*byte)(unsafe.Pointer(s.lo))
- st.ss_size = uint64(s.hi - s.lo)
- st.ss_flags = 0
- }
- sigaltstack(&st, nil)
+func setSignalstackSP(s *stackt, sp uintptr) {
+ s.ss_sp = (*byte)(unsafe.Pointer(sp))
}
//go:nosplit
//go:nosplit
//go:nowritebarrierrec
-func sigaltstack(ss *sigaltstackt, oss *sigaltstackt) /* int32 */ {
+func sigaltstack(ss *stackt, oss *stackt) /* int32 */ {
sysvicall2(&libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss)))
}
// The signal handler handles it directly.
// The sigaltstack assembly function does nothing.
if GOARCH != "arm" && GOARCH != "arm64" {
- var st stackt
- sigaltstack(nil, &st)
- if st.ss_flags&_SS_DISABLE != 0 {
- signalstack(&_g_.m.gsignal.stack)
- _g_.m.newSigstack = true
- } else {
- // Use existing signal stack.
- stsp := uintptr(unsafe.Pointer(st.ss_sp))
- _g_.m.gsignal.stack.lo = stsp
- _g_.m.gsignal.stack.hi = stsp + st.ss_size
- _g_.m.gsignal.stackguard0 = stsp + _StackGuard
- _g_.m.gsignal.stackguard1 = stsp + _StackGuard
- _g_.m.gsignal.stackAlloc = st.ss_size
- _g_.m.newSigstack = false
- }
+ minitSignalStack()
}
// restore signal mask from m.sigmask and unblock essential signals
return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u))
}
+// setSignaltstackSP sets the ss_sp field of a stackt.
//go:nosplit
-func signalstack(s *stack) {
- var st stackt
- if s == nil {
- st.ss_flags = _SS_DISABLE
- } else {
- st.ss_sp = (*byte)(unsafe.Pointer(s.lo))
- st.ss_size = s.hi - s.lo
- st.ss_flags = 0
- }
- sigaltstack(&st, nil)
+func setSignalstackSP(s *stackt, sp uintptr) {
+ s.ss_sp = (*byte)(unsafe.Pointer(sp))
}
//go:nosplit
func lwp_create(param *lwpparams) int32
//go:noescape
-func sigaltstack(new, old *sigaltstackt)
+func sigaltstack(new, old *stackt)
//go:noescape
func sigaction(sig int32, new, old *sigactiont)
// m.procid is a uint64, but lwp_start writes an int32. Fix it up.
_g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
- // Initialize signal handling.
- var st sigaltstackt
- sigaltstack(nil, &st)
- if st.ss_flags&_SS_DISABLE != 0 {
- signalstack(&_g_.m.gsignal.stack)
- _g_.m.newSigstack = true
- } else {
- // Use existing signal stack.
- stsp := uintptr(unsafe.Pointer(st.ss_sp))
- _g_.m.gsignal.stack.lo = stsp
- _g_.m.gsignal.stack.hi = stsp + st.ss_size
- _g_.m.gsignal.stackguard0 = stsp + _StackGuard
- _g_.m.gsignal.stackguard1 = stsp + _StackGuard
- _g_.m.gsignal.stackAlloc = st.ss_size
- _g_.m.newSigstack = false
- }
+ minitSignalStack()
// restore signal mask from m.sigmask and unblock essential signals
nmask := _g_.m.sigmask
return sa.sa_sigaction
}
+// setSignaltstackSP sets the ss_sp field of a stackt.
//go:nosplit
-func signalstack(s *stack) {
- var st sigaltstackt
- if s == nil {
- st.ss_flags = _SS_DISABLE
- } else {
- st.ss_sp = s.lo
- st.ss_size = s.hi - s.lo
- st.ss_flags = 0
- }
- sigaltstack(&st, nil)
+func setSignalstackSP(s *stackt, sp uintptr) {
+ s.ss_sp = sp
}
//go:nosplit
_g_.m.procid = uint64(*(*uint32)(unsafe.Pointer(&_g_.m.procid)))
}
- // Initialize signal handling.
- var st stackt
- sigaltstack(nil, &st)
- if st.ss_flags&_SS_DISABLE != 0 {
- signalstack(&_g_.m.gsignal.stack)
- _g_.m.newSigstack = true
- } else {
- // Use existing signal stack.
- stsp := uintptr(unsafe.Pointer(st.ss_sp))
- _g_.m.gsignal.stack.lo = stsp
- _g_.m.gsignal.stack.hi = stsp + st.ss_size
- _g_.m.gsignal.stackguard0 = stsp + _StackGuard
- _g_.m.gsignal.stackguard1 = stsp + _StackGuard
- _g_.m.gsignal.stackAlloc = st.ss_size
- _g_.m.newSigstack = false
- }
+ minitSignalStack()
// restore signal mask from m.sigmask and unblock essential signals
nmask := _g_.m.sigmask
return sa.sa_handler
}
+// setSignaltstackSP sets the ss_sp field of a stackt.
//go:nosplit
-func signalstack(s *stack) {
- var st stackt
- if s == nil {
- st.ss_flags = _SS_DISABLE
- } else {
- st.ss_sp = s.lo
- st.ss_size = s.hi - s.lo
- st.ss_flags = 0
- }
- sigaltstack(&st, nil)
+func setSignalstackSP(s *stackt, sp uintptr) {
+ s.ss_sp = sp
}
//go:nosplit
// Initialize signal handling.
_g_ := getg()
- var st sigaltstackt
- sigaltstack(nil, &st)
- if st.ss_flags&_SS_DISABLE != 0 {
- signalstack(&_g_.m.gsignal.stack)
- _g_.m.newSigstack = true
- } else {
- // Use existing signal stack.
- stsp := uintptr(unsafe.Pointer(st.ss_sp))
- _g_.m.gsignal.stack.lo = stsp
- _g_.m.gsignal.stack.hi = stsp + st.ss_size
- _g_.m.gsignal.stackguard0 = stsp + _StackGuard
- _g_.m.gsignal.stackguard1 = stsp + _StackGuard
- _g_.m.gsignal.stackAlloc = st.ss_size
- _g_.m.newSigstack = false
- }
+ minitSignalStack()
// for debuggers, in case cgo created the thread
_g_.m.procid = uint64(gettid())
func rt_sigaction(sig uintptr, new, old *sigactiont, size uintptr) int32
//go:noescape
-func sigaltstack(new, old *sigaltstackt)
+func sigaltstack(new, old *stackt)
//go:noescape
func setitimer(mode int32, new, old *itimerval)
return sa.sa_handler
}
+// setSignaltstackSP sets the ss_sp field of a stackt.
//go:nosplit
-func signalstack(s *stack) {
- var st sigaltstackt
- if s == nil {
- st.ss_flags = _SS_DISABLE
- } else {
- st.ss_sp = (*byte)(unsafe.Pointer(s.lo))
- st.ss_size = s.hi - s.lo
- st.ss_flags = 0
- }
- sigaltstack(&st, nil)
+func setSignalstackSP(s *stackt, sp uintptr) {
+ s.ss_sp = (*byte)(unsafe.Pointer(sp))
}
func sigaction(sig int32, new, old *sigactiont)
//go:noescape
-func sigaltstack(new, old *sigaltstackt)
+func sigaltstack(new, old *stackt)
//go:noescape
func sigprocmask(how int32, new, old *sigset)
return sa.sa_sigaction
}
+// setSignaltstackSP sets the ss_sp field of a stackt.
//go:nosplit
-func signalstack(s *stack) {
- var st sigaltstackt
- if s == nil {
- st.ss_flags = _SS_DISABLE
- } else {
- st.ss_sp = s.lo
- st.ss_size = s.hi - s.lo
- st.ss_flags = 0
- }
- sigaltstack(&st, nil)
+func setSignalstackSP(s *stackt, sp uintptr) {
+ s.ss_sp = sp
}
//go:nosplit
// m.procid is a uint64, but tfork writes an int32. Fix it up.
_g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
- // Initialize signal handling
- var st stackt
- sigaltstack(nil, &st)
- if st.ss_flags&_SS_DISABLE != 0 {
- signalstack(&_g_.m.gsignal.stack)
- _g_.m.newSigstack = true
- } else {
- // Use existing signal stack.
- stsp := uintptr(unsafe.Pointer(st.ss_sp))
- _g_.m.gsignal.stack.lo = stsp
- _g_.m.gsignal.stack.hi = stsp + st.ss_size
- _g_.m.gsignal.stackguard0 = stsp + _StackGuard
- _g_.m.gsignal.stackguard1 = stsp + _StackGuard
- _g_.m.gsignal.stackAlloc = st.ss_size
- _g_.m.newSigstack = false
- }
+ minitSignalStack()
// restore signal mask from m.sigmask and unblock essential signals
nmask := _g_.m.sigmask
return sa.sa_sigaction
}
+// setSignaltstackSP sets the ss_sp field of a stackt.
//go:nosplit
-func signalstack(s *stack) {
- var st stackt
- if s == nil {
- st.ss_flags = _SS_DISABLE
- } else {
- st.ss_sp = s.lo
- st.ss_size = s.hi - s.lo
- st.ss_flags = 0
- }
- sigaltstack(&st, nil)
+func setSignalstackSP(s *stackt, sp uintptr) {
+ s.ss_sp = sp
}
//go:nosplit
setg(nil)
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
- g.m.gsignal.stack.lo = stsp
- g.m.gsignal.stack.hi = stsp + st.ss_size
- g.m.gsignal.stackguard0 = stsp + _StackGuard
- g.m.gsignal.stackguard1 = stsp + _StackGuard
- g.m.gsignal.stackAlloc = st.ss_size
+ setGsignalStack(&st)
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
}
setg(nil)
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
- g.m.gsignal.stack.lo = stsp
- g.m.gsignal.stack.hi = stsp + st.ss_size
- g.m.gsignal.stackguard0 = stsp + _StackGuard
- g.m.gsignal.stackguard1 = stsp + _StackGuard
- g.m.gsignal.stackAlloc = st.ss_size
+ setGsignalStack(&st)
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
}
setg(nil)
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
- g.m.gsignal.stack.lo = stsp
- g.m.gsignal.stack.hi = stsp + st.ss_size
- g.m.gsignal.stackguard0 = stsp + _StackGuard
- g.m.gsignal.stackguard1 = stsp + _StackGuard
- g.m.gsignal.stackAlloc = st.ss_size
+ setGsignalStack(&st)
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
}
// If some non-Go code called sigaltstack, adjust.
sp := uintptr(unsafe.Pointer(&sig))
if sp < g.m.gsignal.stack.lo || sp >= g.m.gsignal.stack.hi {
- var st sigaltstackt
+ var st stackt
sigaltstack(nil, &st)
if st.ss_flags&_SS_DISABLE != 0 {
setg(nil)
setg(nil)
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
- g.m.gsignal.stack.lo = stsp
- g.m.gsignal.stack.hi = stsp + st.ss_size
- g.m.gsignal.stackguard0 = stsp + _StackGuard
- g.m.gsignal.stackguard1 = stsp + _StackGuard
- g.m.gsignal.stackAlloc = st.ss_size
+ setGsignalStack(&st)
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
}
sigprocmask(_SIG_UNBLOCK, &set, nil)
}
+// minitSignalStack is called when initializing a new m to set the
+// alternate signal stack. If the alternate signal stack is not set
+// for the thread (the normal case) then set the alternate signal
+// stack to the gsignal stack. If the alternate signal stack is set
+// for the thread (the case when a non-Go thread sets the alternate
+// signal stack and then calls a Go function) then set the gsignal
+// stack to the alternate signal stack. Record which choice was made
+// in newSigstack, so that it can be undone in unminit.
+func minitSignalStack() {
+ _g_ := getg()
+ var st stackt
+ sigaltstack(nil, &st)
+ if st.ss_flags&_SS_DISABLE != 0 {
+ signalstack(&_g_.m.gsignal.stack)
+ _g_.m.newSigstack = true
+ } else {
+ setGsignalStack(&st)
+ _g_.m.newSigstack = false
+ }
+}
+
+// setGsignalStack sets the gsignal stack of the current m to an
+// alternate signal stack returned from the sigaltstack system call.
+// This is used when handling a signal if non-Go code has set the
+// alternate signal stack.
+//go:nosplit
+//go:nowritebarrierrec
+func setGsignalStack(st *stackt) {
+ g := getg()
+ stsp := uintptr(unsafe.Pointer(st.ss_sp))
+ g.m.gsignal.stack.lo = stsp
+ g.m.gsignal.stack.hi = stsp + st.ss_size
+ g.m.gsignal.stackguard0 = stsp + _StackGuard
+ g.m.gsignal.stackguard1 = stsp + _StackGuard
+ g.m.gsignal.stackAlloc = st.ss_size
+}
+
+// signalstack sets the current thread's alternate signal stack to s.
+// If s is nil, the current thread's alternate signal stack is disabled.
+//go:nosplit
+func signalstack(s *stack) {
+ var st stackt
+ if s == nil {
+ st.ss_flags = _SS_DISABLE
+ } else {
+ setSignalstackSP(&st, s.lo)
+ st.ss_size = s.hi - s.lo
+ st.ss_flags = 0
+ }
+ sigaltstack(&st, nil)
+}
+
// setsigsegv is used on darwin/arm{,64} to fake a segmentation fault.
//go:nosplit
func setsigsegv(pc uintptr) {