Commit c2735039 authored by Ian Lance Taylor's avatar Ian Lance Taylor

runtime: unify sigtrampgo

Combine the various versions of sigtrampgo into a single function in
signal_unix.go. This requires defining a fixsigcode method on sigctxt
for all operating systems; it only does something on Darwin. This also
requires changing the darwin/amd64 signal handler to call sigreturn
itself, rather than relying on sigtrampgo to call sigreturn for it. We
can then drop the Darwin sigreturn function, as it is no longer used.

Change-Id: I5a0b9d2d2c141957e151b41e694efeb20e4b4b9a
Reviewed-on: https://go-review.googlesource.com/29761
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 1906d93b
...@@ -318,6 +318,9 @@ func sigmaskToSigset(m sigmask) sigset { ...@@ -318,6 +318,9 @@ func sigmaskToSigset(m sigmask) sigset {
return set return set
} }
func (c *sigctxt) fixsigcode(sig uint32) {
}
//go:nosplit //go:nosplit
func semacreate(mp *m) { func semacreate(mp *m) {
if mp.waitsema != 0 { if mp.waitsema != 0 {
......
...@@ -290,3 +290,6 @@ func sigmaskToSigset(m sigmask) sigset { ...@@ -290,3 +290,6 @@ func sigmaskToSigset(m sigmask) sigset {
copy(set.__bits[:], m[:]) copy(set.__bits[:], m[:])
return set return set
} }
func (c *sigctxt) fixsigcode(sig uint32) {
}
...@@ -280,3 +280,6 @@ func sigmaskToSigset(m sigmask) sigset { ...@@ -280,3 +280,6 @@ func sigmaskToSigset(m sigmask) sigset {
copy(set.__bits[:], m[:]) copy(set.__bits[:], m[:])
return set return set
} }
func (c *sigctxt) fixsigcode(sig uint32) {
}
...@@ -410,3 +410,6 @@ func getsig(i int32) uintptr { ...@@ -410,3 +410,6 @@ func getsig(i int32) uintptr {
func setSignalstackSP(s *stackt, sp uintptr) { func setSignalstackSP(s *stackt, sp uintptr) {
s.ss_sp = (*byte)(unsafe.Pointer(sp)) s.ss_sp = (*byte)(unsafe.Pointer(sp))
} }
func (c *sigctxt) fixsigcode(sig uint32) {
}
...@@ -316,3 +316,6 @@ func sigmaskToSigset(m sigmask) sigset { ...@@ -316,3 +316,6 @@ func sigmaskToSigset(m sigmask) sigset {
copy(set.__bits[:], m[:]) copy(set.__bits[:], m[:])
return set return set
} }
func (c *sigctxt) fixsigcode(sig uint32) {
}
...@@ -294,3 +294,6 @@ func setSignalstackSP(s *stackt, sp uintptr) { ...@@ -294,3 +294,6 @@ func setSignalstackSP(s *stackt, sp uintptr) {
func sigmaskToSigset(m sigmask) sigset { func sigmaskToSigset(m sigmask) sigset {
return sigset(m[0]) return sigset(m[0])
} }
func (c *sigctxt) fixsigcode(sig uint32) {
}
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
package runtime package runtime
import "unsafe"
type sigTabT struct { type sigTabT struct {
flags int32 flags int32
name string name string
...@@ -45,46 +43,3 @@ var sigtable = [...]sigTabT{ ...@@ -45,46 +43,3 @@ var sigtable = [...]sigTabT{
/* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"}, /* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"}, /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
} }
//go:noescape
func sigreturn(ctx unsafe.Pointer, infostyle uint32)
//go:nosplit
//go:nowritebarrierrec
func sigtrampgo(fn uintptr, infostyle, sig uint32, info *siginfo, ctx unsafe.Pointer) {
if sigfwdgo(sig, info, ctx) {
sigreturn(ctx, infostyle)
return
}
g := getg()
if g == nil {
badsignal(uintptr(sig), &sigctxt{info, ctx})
sigreturn(ctx, infostyle)
return
}
// 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 stackt
sigaltstack(nil, &st)
if st.ss_flags&_SS_DISABLE != 0 {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
stsp := uintptr(unsafe.Pointer(st.ss_sp))
if sp < stsp || sp >= stsp+st.ss_size {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
setGsignalStack(&st)
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
}
setg(g.m.gsignal)
c := &sigctxt{info, ctx}
c.fixsigcode(sig)
sighandler(sig, info, ctx, g)
setg(g)
sigreturn(ctx, infostyle)
}
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
package runtime package runtime
import "unsafe"
type sigTabT struct { type sigTabT struct {
flags int32 flags int32
name string name string
...@@ -46,38 +44,3 @@ var sigtable = [...]sigTabT{ ...@@ -46,38 +44,3 @@ var sigtable = [...]sigTabT{
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"}, /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
/* 32 */ {_SigNotify, "SIGTHR: reserved"}, /* 32 */ {_SigNotify, "SIGTHR: reserved"},
} }
//go:nosplit
//go:nowritebarrierrec
func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
if sigfwdgo(sig, info, ctx) {
return
}
g := getg()
if g == nil {
badsignal(uintptr(sig), &sigctxt{info, ctx})
return
}
// 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 stackt
sigaltstack(nil, &st)
if st.ss_flags&_SS_DISABLE != 0 {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
stsp := uintptr(unsafe.Pointer(st.ss_sp))
if sp < stsp || sp >= stsp+st.ss_size {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
setGsignalStack(&st)
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
}
setg(g.m.gsignal)
sighandler(sig, info, ctx, g)
setg(g)
}
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
package runtime package runtime
import "unsafe"
type sigTabT struct { type sigTabT struct {
flags int32 flags int32
name string name string
...@@ -46,38 +44,3 @@ var sigtable = [...]sigTabT{ ...@@ -46,38 +44,3 @@ var sigtable = [...]sigTabT{
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"}, /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
/* 32 */ {_SigNotify, "SIGTHR: reserved"}, /* 32 */ {_SigNotify, "SIGTHR: reserved"},
} }
//go:nosplit
//go:nowritebarrierrec
func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
if sigfwdgo(sig, info, ctx) {
return
}
g := getg()
if g == nil {
badsignal(uintptr(sig), &sigctxt{info, ctx})
return
}
// 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 stackt
sigaltstack(nil, &st)
if st.ss_flags&_SS_DISABLE != 0 {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
stsp := uintptr(unsafe.Pointer(st.ss_sp))
if sp < stsp || sp >= stsp+st.ss_size {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
setGsignalStack(&st)
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
}
setg(g.m.gsignal)
sighandler(sig, info, ctx, g)
setg(g)
}
// 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.
// +build dragonfly linux netbsd
package runtime
import "unsafe"
// Continuation of the (assembly) sigtramp() logic.
// This may be called with the world stopped.
//go:nosplit
//go:nowritebarrierrec
func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
if sigfwdgo(sig, info, ctx) {
return
}
g := getg()
if g == nil {
if sig == _SIGPROF {
// Ignore profiling signals that arrive on
// non-Go threads. On some systems they will
// be handled directly by the signal handler,
// by calling sigprofNonGo, in which case we won't
// get here anyhow.
return
}
badsignal(uintptr(sig), &sigctxt{info, ctx})
return
}
// 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 stackt
sigaltstack(nil, &st)
if st.ss_flags&_SS_DISABLE != 0 {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
stsp := uintptr(unsafe.Pointer(st.ss_sp))
if sp < stsp || sp >= stsp+st.ss_size {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
setGsignalStack(&st)
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
}
setg(g.m.gsignal)
sighandler(sig, info, ctx, g)
setg(g)
}
...@@ -196,6 +196,54 @@ func sigpipe() { ...@@ -196,6 +196,54 @@ func sigpipe() {
dieFromSignal(_SIGPIPE) dieFromSignal(_SIGPIPE)
} }
// sigtrampgo is called from the signal handler function, sigtramp,
// written in assembly code.
// This is called by the signal handler, and the world may be stopped.
//go:nosplit
//go:nowritebarrierrec
func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
if sigfwdgo(sig, info, ctx) {
return
}
g := getg()
if g == nil {
if sig == _SIGPROF {
// Ignore profiling signals that arrive on
// non-Go threads. On some systems they will
// be handled directly by the signal handler,
// by calling sigprofNonGo, in which case we won't
// get here anyhow.
return
}
badsignal(uintptr(sig), &sigctxt{info, ctx})
return
}
// 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 stackt
sigaltstack(nil, &st)
if st.ss_flags&_SS_DISABLE != 0 {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
stsp := uintptr(unsafe.Pointer(st.ss_sp))
if sp < stsp || sp >= stsp+st.ss_size {
setg(nil)
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
}
setGsignalStack(&st)
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
}
setg(g.m.gsignal)
c := &sigctxt{info, ctx}
c.fixsigcode(sig)
sighandler(sig, info, ctx, g)
setg(g)
}
// sigpanic turns a synchronous signal into a run-time panic. // sigpanic turns a synchronous signal into a run-time panic.
// If the signal handler sees a synchronous panic, it arranges the // If the signal handler sees a synchronous panic, it arranges the
// stack to look like the function where the signal occurred called // stack to look like the function where the signal occurred called
......
...@@ -265,17 +265,6 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-16 ...@@ -265,17 +265,6 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
MOVL AX, SP MOVL AX, SP
RET RET
TEXT runtime·sigreturn(SB),NOSPLIT,$12-8
MOVL ctx+0(FP), CX
MOVL infostyle+4(FP), BX
MOVL $0, 0(SP) // "caller PC" - ignored
MOVL CX, 4(SP)
MOVL BX, 8(SP)
MOVL $184, AX // sigreturn(ucontext, infostyle)
INT $0x80
MOVL $0xf1, 0xf1 // crash
RET
// Sigtramp's job is to call the actual signal handler. // Sigtramp's job is to call the actual signal handler.
// It is called with the following arguments on the stack: // It is called with the following arguments on the stack:
// 0(SP) "return address" - ignored // 0(SP) "return address" - ignored
...@@ -285,16 +274,12 @@ TEXT runtime·sigreturn(SB),NOSPLIT,$12-8 ...@@ -285,16 +274,12 @@ TEXT runtime·sigreturn(SB),NOSPLIT,$12-8
// 16(SP) siginfo // 16(SP) siginfo
// 20(SP) context // 20(SP) context
TEXT runtime·sigtramp(SB),NOSPLIT,$20 TEXT runtime·sigtramp(SB),NOSPLIT,$20
MOVL fn+0(FP), BX
MOVL BX, 0(SP)
MOVL infostyle+4(FP), BX
MOVL BX, 4(SP)
MOVL sig+8(FP), BX MOVL sig+8(FP), BX
MOVL BX, 8(SP) MOVL BX, 0(SP)
MOVL info+12(FP), BX MOVL info+12(FP), BX
MOVL BX, 12(SP) MOVL BX, 4(SP)
MOVL ctx+16(FP), BX MOVL ctx+16(FP), BX
MOVL BX, 16(SP) MOVL BX, 8(SP)
CALL runtime·sigtrampgo(SB) CALL runtime·sigtrampgo(SB)
// call sigreturn // call sigreturn
......
...@@ -230,22 +230,18 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 ...@@ -230,22 +230,18 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
MOVQ BP, SP MOVQ BP, SP
RET RET
TEXT runtime·sigreturn(SB),NOSPLIT,$0-12
MOVQ ctx+0(FP), DI
MOVL infostyle+8(FP), SI
MOVL $(0x2000000+184), AX
SYSCALL
INT $3 // not reached
TEXT runtime·sigtramp(SB),NOSPLIT,$32 TEXT runtime·sigtramp(SB),NOSPLIT,$32
MOVQ DI, 0(SP) // fn MOVL SI, 24(SP) // save infostyle for sigreturn below
MOVL SI, 8(SP) // infostyle MOVL DX, 0(SP) // sig
MOVL DX, 12(SP) // sig MOVQ CX, 8(SP) // info
MOVQ CX, 16(SP) // info MOVQ R8, 16(SP) // ctx
MOVQ R8, 24(SP) // ctx
MOVQ $runtime·sigtrampgo(SB), AX MOVQ $runtime·sigtrampgo(SB), AX
CALL AX CALL AX
INT $3 // not reached (see issue 16453) MOVQ 16(SP), DI // ctx
MOVL 24(SP), SI // infostyle
MOVL $(0x2000000+184), AX
SYSCALL
INT $3 // not reached
TEXT runtime·mmap(SB),NOSPLIT,$0 TEXT runtime·mmap(SB),NOSPLIT,$0
MOVQ addr+0(FP), DI // arg 1 addr MOVQ addr+0(FP), DI // arg 1 addr
......
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