]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: adjust gsignal stack to current signal stack
authorIan Lance Taylor <iant@golang.org>
Tue, 22 Dec 2015 06:27:01 +0000 (22:27 -0800)
committerIan Lance Taylor <iant@golang.org>
Thu, 24 Dec 2015 17:00:04 +0000 (17:00 +0000)
If non-Go code calls sigaltstack before a signal is received, use
sigaltstack to determine the current signal stack and set the gsignal
stack to use it.  This makes the Go runtime more robust in the face of
non-Go code.  We still can't handle a disabled signal stack or a signal
triggered with SA_ONSTACK clear, but we now give clear errors for those
cases.

Fixes #7227.
Update #9896.

Change-Id: Icb1607e01fd6461019b6d77d940e59b3aed4d258
Reviewed-on: https://go-review.googlesource.com/18102
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
23 files changed:
misc/cgo/test/cgo_unix_test.go [new file with mode: 0644]
misc/cgo/test/sigaltstack.go [new file with mode: 0644]
src/runtime/signal1_unix.go
src/runtime/signal2_unix.go
src/runtime/signal_darwin.go
src/runtime/signal_freebsd.go
src/runtime/signal_linux.go [deleted file]
src/runtime/signal_openbsd.go
src/runtime/signal_sigtramp.go [new file with mode: 0644]
src/runtime/sys_darwin_386.s
src/runtime/sys_darwin_arm.s
src/runtime/sys_darwin_arm64.s
src/runtime/sys_dragonfly_amd64.s
src/runtime/sys_freebsd_386.s
src/runtime/sys_freebsd_amd64.s
src/runtime/sys_freebsd_arm.s
src/runtime/sys_netbsd_386.s
src/runtime/sys_netbsd_amd64.s
src/runtime/sys_netbsd_arm.s
src/runtime/sys_openbsd_386.s
src/runtime/sys_openbsd_amd64.s
src/runtime/sys_openbsd_arm.s
src/runtime/sys_solaris_amd64.s

diff --git a/misc/cgo/test/cgo_unix_test.go b/misc/cgo/test/cgo_unix_test.go
new file mode 100644 (file)
index 0000000..5808e6e
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2015 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 !windows
+
+package cgotest
+
+import "testing"
+
+func TestSigaltstack(t *testing.T) { testSigaltstack(t) }
diff --git a/misc/cgo/test/sigaltstack.go b/misc/cgo/test/sigaltstack.go
new file mode 100644 (file)
index 0000000..54faa2a
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2015 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 !windows
+
+// Test that the Go runtime still works if C code changes the signal stack.
+
+package cgotest
+
+/*
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static stack_t oss;
+static char signalStack[SIGSTKSZ];
+
+static void changeSignalStack() {
+       stack_t ss;
+       memset(&ss, 0, sizeof ss);
+       ss.ss_sp = signalStack;
+       ss.ss_flags = 0;
+       ss.ss_size = SIGSTKSZ;
+       if (sigaltstack(&ss, &oss) < 0) {
+               perror("sigaltstack");
+               abort();
+       }
+}
+
+static void restoreSignalStack() {
+#if defined(__x86_64__) && defined(__APPLE__)
+       // The Darwin C library enforces a minimum that the kernel does not.
+       // This is OK since we allocated this much space in mpreinit,
+       // it was just removed from the buffer by stackalloc.
+       oss.ss_size = MINSIGSTKSZ;
+#endif
+       if (sigaltstack(&oss, NULL) < 0) {
+               perror("sigaltstack restore");
+               abort();
+       }
+}
+
+static int zero() {
+       return 0;
+}
+*/
+import "C"
+
+import (
+       "runtime"
+       "testing"
+)
+
+func testSigaltstack(t *testing.T) {
+       switch {
+       case runtime.GOOS == "solaris", runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64"):
+               t.Skipf("switching signal stack not implemented on %s/s", runtime.GOOS, runtime.GOARCH)
+       }
+
+       C.changeSignalStack()
+       defer C.restoreSignalStack()
+       defer func() {
+               if recover() == nil {
+                       t.Error("did not see expected panic")
+               }
+       }()
+       v := 1 / int(C.zero())
+       t.Errorf("unexpected success of division by zero == %d", v)
+}
index 2a325bb9fcca7fdeb02982e85d394b136c6d7673..3bb3ed831272f7b6350dc2bea941375f5b1c8c65 100644 (file)
@@ -249,3 +249,19 @@ func ensureSigM() {
                }
        }()
 }
+
+// This is called when we receive a signal when there is no signal stack.
+// This can only happen if non-Go code calls sigaltstack to disable the
+// signal stack.  This is called via cgocallback to establish a stack.
+func noSignalStack(sig uint32) {
+       println("signal", sig, "received on thread with no signal stack")
+       throw("non-Go code disabled sigaltstack")
+}
+
+// This is called if we receive a signal when there is a signal stack
+// but we are not on it.  This can only happen if non-Go code called
+// sigaction without setting the SS_ONSTACK flag.
+func sigNotOnStack(sig uint32) {
+       println("signal", sig, "received but handler not on signal stack")
+       throw("non-Go code set up signal handler without SA_ONSTACK flag")
+}
index 0633a5190057d5d052525d3637de43fc6f8d6cd2..490a69d56db69715ca1a2e824d40ada369e14ed6 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin linux
+// +build darwin dragonfly freebsd linux netbsd openbsd
 
 package runtime
 
index e8ec162fda51297c7b24ca007a518242c93f08e4..142f4e24ce5d7411dc5807e4307a154dcaa6d2f8 100644 (file)
@@ -61,6 +61,29 @@ func sigtrampgo(fn uintptr, infostyle, sig uint32, info *siginfo, ctx unsafe.Poi
                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))
+               }
+               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))
+               }
+               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.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
+       }
+
        setg(g.m.gsignal)
        sighandler(sig, info, ctx, g)
        setg(g)
index 1dbdb1bd9756a3cfa703d2a85679773dc9538fd5..bc167c7a9a4689f96acfc3a01ad6c81eeb3a11c8 100644 (file)
@@ -4,6 +4,8 @@
 
 package runtime
 
+import "unsafe"
+
 type sigTabT struct {
        flags int32
        name  string
@@ -44,3 +46,41 @@ var sigtable = [...]sigTabT{
        /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
        /* 32 */ {_SigNotify, "SIGTHR: reserved"},
 }
+
+//go:nosplit
+func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
+       if sigfwdgo(sig, info, ctx) {
+               return
+       }
+       g := getg()
+       if g == nil {
+               badsignal(uintptr(sig))
+               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))
+               }
+               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))
+               }
+               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.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
+       }
+
+       setg(g.m.gsignal)
+       sighandler(sig, info, ctx, g)
+       setg(g)
+}
diff --git a/src/runtime/signal_linux.go b/src/runtime/signal_linux.go
deleted file mode 100644 (file)
index 8199b6c..0000000
+++ /dev/null
@@ -1,23 +0,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.
-
-package runtime
-
-import "unsafe"
-
-// Continuation of the (assembly) sigtramp() logic.
-//go:nosplit
-func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
-       if sigfwdgo(sig, info, ctx) {
-               return
-       }
-       g := getg()
-       if g == nil {
-               badsignal(uintptr(sig))
-               return
-       }
-       setg(g.m.gsignal)
-       sighandler(sig, info, ctx, g)
-       setg(g)
-}
index 78afc59efacd97423faee7f9f4ac04da052a0783..f724db9fcdfbac4a6692f8f00e498b5848eb0263 100644 (file)
@@ -4,6 +4,8 @@
 
 package runtime
 
+import "unsafe"
+
 type sigTabT struct {
        flags int32
        name  string
@@ -44,3 +46,41 @@ var sigtable = [...]sigTabT{
        /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
        /* 32 */ {_SigNotify, "SIGTHR: reserved"},
 }
+
+//go:nosplit
+func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
+       if sigfwdgo(sig, info, ctx) {
+               return
+       }
+       g := getg()
+       if g == nil {
+               badsignal(uintptr(sig))
+               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))
+               }
+               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))
+               }
+               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.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
+       }
+
+       setg(g.m.gsignal)
+       sighandler(sig, info, ctx, g)
+       setg(g)
+}
diff --git a/src/runtime/signal_sigtramp.go b/src/runtime/signal_sigtramp.go
new file mode 100644 (file)
index 0000000..5197a3d
--- /dev/null
@@ -0,0 +1,48 @@
+// 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.
+//go:nosplit
+func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
+       if sigfwdgo(sig, info, ctx) {
+               return
+       }
+       g := getg()
+       if g == nil {
+               badsignal(uintptr(sig))
+               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 sigaltstackt
+               sigaltstack(nil, &st)
+               if st.ss_flags&_SS_DISABLE != 0 {
+                       setg(nil)
+                       cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+               }
+               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))
+               }
+               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.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
+       }
+
+       setg(g.m.gsignal)
+       sighandler(sig, info, ctx, g)
+       setg(g)
+}
index 87a9038041e786a067d2a116220445ff7532fb7f..c516ef2da81a8195be1d10d37a0f1d93c9465ab0 100644 (file)
@@ -242,53 +242,49 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0
        MOVL    $0xf1, 0xf1  // crash
        RET
 
-// Sigtramp's job is to call the actual signal handler.
-// It is called with the following arguments on the stack:
-//     0(FP)   "return address" - ignored
-//     4(FP)   actual handler
-//     8(FP)   signal number
-//     12(FP)  siginfo style
-//     16(FP)  siginfo
-//     20(FP)  context
-TEXT runtime·sigtramp(SB),NOSPLIT,$40
-       get_tls(CX)
-       
-       // check that g exists
-       MOVL    g(CX), DI
-       CMPL    DI, $0
-       JNE     6(PC)
-       MOVL    sig+8(FP), BX
-       MOVL    BX, 0(SP)
-       MOVL    $runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
+       MOVL    sig+4(FP), AX
+       MOVL    AX, 0(SP)
+       MOVL    info+8(FP), AX
+       MOVL    AX, 4(SP)
+       MOVL    ctx+12(FP), AX
+       MOVL    AX, 8(SP)
+       MOVL    fn+0(FP), AX
        CALL    AX
-       JMP     ret
-
-       // save g
-       MOVL    DI, 20(SP)
+       RET
 
-       // g = m->gsignal
-       MOVL    g_m(DI), BP
-       MOVL    m_gsignal(BP), BP
-       MOVL    BP, g(CX)
+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
 
-       // copy arguments to sighandler
-       MOVL    sig+8(FP), BX
+// Sigtramp's job is to call the actual signal handler.
+// It is called with the following arguments on the stack:
+//     0(SP)   "return address" - ignored
+//     4(SP)   actual handler
+//     8(SP)   signal number
+//     12(SP)  siginfo style
+//     16(SP)  siginfo
+//     20(SP)  context
+TEXT runtime·sigtramp(SB),NOSPLIT,$20
+       MOVL    fn+0(FP), BX
        MOVL    BX, 0(SP)
-       MOVL    info+12(FP), BX
+       MOVL    style+4(FP), BX
        MOVL    BX, 4(SP)
-       MOVL    context+16(FP), BX
+       MOVL    sig+8(FP), BX
        MOVL    BX, 8(SP)
-       MOVL    DI, 12(SP)
-
-       MOVL    handler+0(FP), BX
-       CALL    BX
-
-       // restore g
-       get_tls(CX)
-       MOVL    20(SP), DI
-       MOVL    DI, g(CX)
+       MOVL    info+12(FP), BX
+       MOVL    BX, 12(SP)
+       MOVL    context+16(FP), BX
+       MOVL    BX, 16(SP)
+       CALL    runtime·sigtrampgo(SB)
 
-ret:
        // call sigreturn
        MOVL    context+16(FP), CX
        MOVL    style+4(FP), BX
index fdbb27826a9ef44d5432bcef202fefd2f4d21672..82a8db991413402262c0717cc76badb935d3ee91 100644 (file)
@@ -194,6 +194,18 @@ TEXT runtime·nanotime(SB),NOSPLIT,$32
        MOVW    R1, ret_hi+4(FP)
        RET
 
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+       MOVW    sig+4(FP), R0
+       MOVW    info+8(FP), R1
+       MOVW    ctx+12(FP), R2
+       MOVW    fn+0(FP), R11
+       MOVW    R13, R4
+       SUB     $24, R13
+       BIC     $0x7, R13 // alignment for ELF ABI
+       BL      (R11)
+       MOVW    R4, R13
+       RET
+
 // Sigtramp's job is to call the actual signal handler.
 // It is called with the following arguments on the stack:
 //      LR     "return address" - ignored
index 145674d844d78d33cde661f7e07ab877a336904e..d0034d5a33f9aee2e2341980d0fd26a237a80efe 100644 (file)
@@ -180,6 +180,14 @@ TEXT runtime·nanotime(SB),NOSPLIT,$40
        MOVD    R0, ret+0(FP)
        RET
 
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+       MOVW    sig+8(FP), R0
+       MOVD    info+16(FP), R1
+       MOVD    ctx+24(FP), R2
+       MOVD    fn+0(FP), R11
+       BL      (R11)
+       RET
+
 // Sigtramp's job is to call the actual signal handler.
 // It is called with the following arguments on the stack:
 //     LR      "return address" - ignored
index 26c97848f2513fb485479aeecd87005749bb9163..d1b94e1bfdc18edcead2bc25e5a9676da0a4ab1a 100644 (file)
@@ -187,37 +187,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
        MOVL    $0xf1, 0xf1  // crash
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$64
-       get_tls(BX)
-
-       // check that g exists
-       MOVQ    g(BX), R10
-       CMPQ    R10, $0
-       JNE     5(PC)
-       MOVQ    DI, 0(SP)
-       MOVQ    $runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+       MOVL    sig+8(FP), DI
+       MOVQ    info+16(FP), SI
+       MOVQ    ctx+24(FP), DX
+       MOVQ    fn+0(FP), AX
        CALL    AX
        RET
 
-       // save g
-       MOVQ    R10, 40(SP)
-       
-       // g = m->signal
-       MOVQ    g_m(R10), AX
-       MOVQ    m_gsignal(AX), AX
-       MOVQ    AX, g(BX)
-       
+TEXT runtime·sigtramp(SB),NOSPLIT,$24
        MOVQ    DI, 0(SP)
        MOVQ    SI, 8(SP)
        MOVQ    DX, 16(SP)
-       MOVQ    R10, 24(SP)
-
-       CALL    runtime·sighandler(SB)
-
-       // restore g
-       get_tls(BX)
-       MOVQ    40(SP), R10
-       MOVQ    R10, g(BX)
+       CALL    runtime·sigtrampgo(SB)
        RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$0
index 3aaeede6be987a0eaa7bae5f38eb9d7e63667e0f..b37abcef957b32b5a087eeac0cf804bd55ddcbbe 100644 (file)
@@ -207,44 +207,26 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-4
        MOVL    $0xf1, 0xf1  // crash
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$44
-       get_tls(CX)
-
-       // check that g exists
-       MOVL    g(CX), DI
-       CMPL    DI, $0
-       JNE     6(PC)
-       MOVL    signo+0(FP), BX
-       MOVL    BX, 0(SP)
-       MOVL    $runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
+       MOVL    sig+4(FP), AX
+       MOVL    AX, 0(SP)
+       MOVL    info+8(FP), AX
+       MOVL    AX, 4(SP)
+       MOVL    ctx+12(FP), AX
+       MOVL    AX, 8(SP)
+       MOVL    fn+0(FP), AX
        CALL    AX
-       JMP     ret
-
-       // save g
-       MOVL    DI, 20(SP)
-       
-       // g = m->gsignal
-       MOVL    g_m(DI), BX
-       MOVL    m_gsignal(BX), BX
-       MOVL    BX, g(CX)
+       RET
 
-       // copy arguments for call to sighandler
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
        MOVL    signo+0(FP), BX
        MOVL    BX, 0(SP)
        MOVL    info+4(FP), BX
        MOVL    BX, 4(SP)
        MOVL    context+8(FP), BX
        MOVL    BX, 8(SP)
-       MOVL    DI, 12(SP)
-
-       CALL    runtime·sighandler(SB)
-
-       // restore g
-       get_tls(CX)
-       MOVL    20(SP), BX
-       MOVL    BX, g(CX)
+       CALL    runtime·sigtrampgo(SB)
 
-ret:
        // call sigreturn
        MOVL    context+8(FP), AX
        MOVL    $0, 0(SP)       // syscall gap
index b1c67c7dfc99a72ab2c70689b4213e2b0600078a..9700117d0f2edf18c04205fe04871b51c9a65fa2 100644 (file)
@@ -183,37 +183,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
        MOVL    $0xf1, 0xf1  // crash
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$64
-       get_tls(BX)
-
-       // check that g exists
-       MOVQ    g(BX), R10
-       CMPQ    R10, $0
-       JNE     5(PC)
-       MOVQ    DI, 0(SP)
-       MOVQ    $runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+       MOVL    sig+8(FP), DI
+       MOVQ    info+16(FP), SI
+       MOVQ    ctx+24(FP), DX
+       MOVQ    fn+0(FP), AX
        CALL    AX
        RET
 
-       // save g
-       MOVQ    R10, 40(SP)
-       
-       // g = m->signal
-       MOVQ    g_m(R10), AX
-       MOVQ    m_gsignal(AX), AX
-       MOVQ    AX, g(BX)
-       
+TEXT runtime·sigtramp(SB),NOSPLIT,$24
        MOVQ    DI, 0(SP)
        MOVQ    SI, 8(SP)
        MOVQ    DX, 16(SP)
-       MOVQ    R10, 24(SP)
-
-       CALL    runtime·sighandler(SB)
-
-       // restore g
-       get_tls(BX)
-       MOVQ    40(SP), R10
-       MOVQ    R10, g(BX)
+       CALL    runtime·sigtrampgo(SB)
        RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$0
index b755ec70a83f1c70bf3e118297ce091b25bdeda6..e7dfb281d586c9e55634290904c91940a882dd01 100644 (file)
@@ -216,7 +216,7 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
        MOVW.CS R8, (R8)
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$24
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
        // this might be called in external code context,
        // where g is not set.
        // first save R0, because runtime·load_g will clobber it
@@ -225,30 +225,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
        CMP     $0, R0
        BL.NE   runtime·load_g(SB)
 
-       CMP $0, g
-       BNE 4(PC)
-       // signal number is already prepared in 4(R13)
-       MOVW $runtime·badsignal(SB), R11
-       BL (R11)
-       RET
-
-       // save g
-       MOVW g, R4
-       MOVW g, 20(R13)
-
-       // g = m->signal
-       MOVW g_m(g), R8
-       MOVW m_gsignal(R8), g
-
-       // R0 is already saved
-       MOVW R1, 8(R13) // info
-       MOVW R2, 12(R13) // context
-       MOVW R4, 16(R13) // oldg
-
-       BL runtime·sighandler(SB)
-
-       // restore g
-       MOVW 20(R13), g
+       MOVW    R1, 8(R13)
+       MOVW    R2, 12(R13)
+       BL      runtime·sigtrampgo(SB)
        RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$16
@@ -300,6 +279,18 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
        MOVW.CS R8, (R8)
        RET
 
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+       MOVW    sig+4(FP), R0
+       MOVW    info+8(FP), R1
+       MOVW    ctx+12(FP), R2
+       MOVW    fn+0(FP), R11
+       MOVW    R13, R4
+       SUB     $24, R13
+       BIC     $0x7, R13 // alignment for ELF ABI
+       BL      (R11)
+       MOVW    R4, R13
+       RET
+
 TEXT runtime·usleep(SB),NOSPLIT,$16
        MOVW usec+0(FP), R0
        CALL runtime·usplitR0(SB)
index 13b842840e7da62eb1f470b440f4f69acf9accce..3b3c1095f02086e891c144540f7a33c83eded077 100644 (file)
@@ -215,42 +215,25 @@ TEXT runtime·sigaction(SB),NOSPLIT,$24
        MOVL    $0xf1, 0xf1             // crash
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$44
-       get_tls(CX)
-
-       // check that g exists
-       MOVL    g(CX), DI
-       CMPL    DI, $0
-       JNE     6(PC)
-       MOVL    signo+0(FP), BX
-       MOVL    BX, 0(SP)
-       MOVL    $runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
+       MOVL    sig+4(FP), AX
+       MOVL    AX, 0(SP)
+       MOVL    info+8(FP), AX
+       MOVL    AX, 4(SP)
+       MOVL    ctx+12(FP), AX
+       MOVL    AX, 8(SP)
+       MOVL    fn+0(FP), AX
        CALL    AX
        RET
 
-       // save g
-       MOVL    DI, 20(SP)
-
-       // g = m->gsignal
-       MOVL    g_m(DI), BX
-       MOVL    m_gsignal(BX), BX
-       MOVL    BX, g(CX)
-
-       // copy arguments for call to sighandler
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
        MOVL    signo+0(FP), BX
        MOVL    BX, 0(SP)
        MOVL    info+4(FP), BX
        MOVL    BX, 4(SP)
        MOVL    context+8(FP), BX
        MOVL    BX, 8(SP)
-       MOVL    DI, 12(SP)
-
-       CALL    runtime·sighandler(SB)
-
-       // restore g
-       get_tls(CX)
-       MOVL    20(SP), BX
-       MOVL    BX, g(CX)
+       CALL    runtime·sigtrampgo(SB)
        RET
 
 // int32 lwp_create(void *context, uintptr flags, void *lwpid);
index d0640dbfac7cf52b0e7736776e31de8c40535050..35a1b5dd00324a7d7a553f685f194a96487f7e28 100644 (file)
@@ -237,37 +237,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
        MOVL    $0xf1, 0xf1             // crash
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$64
-       get_tls(BX)
-
-       // check that g exists
-       MOVQ    g(BX), R10
-       CMPQ    R10, $0
-       JNE     5(PC)
-       MOVQ    DI, 0(SP)
-       MOVQ    $runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+       MOVL    sig+8(FP), DI
+       MOVQ    info+16(FP), SI
+       MOVQ    ctx+24(FP), DX
+       MOVQ    fn+0(FP), AX
        CALL    AX
        RET
 
-       // save g
-       MOVQ    R10, 40(SP)
-
-       // g = m->signal
-       MOVQ    g_m(R10), AX
-       MOVQ    m_gsignal(AX), AX
-       MOVQ    AX, g(BX)
-
-       MOVQ    DI, 0(SP)
-       MOVQ    SI, 8(SP)
-       MOVQ    DX, 16(SP)
-       MOVQ    R10, 24(SP)
-
-       CALL    runtime·sighandler(SB)
-
-       // restore g
-       get_tls(BX)
-       MOVQ    40(SP), R10
-       MOVQ    R10, g(BX)
+TEXT runtime·sigtramp(SB),NOSPLIT,$24
+       MOVQ    DI, 0(SP)   // signum
+       MOVQ    SI, 8(SP)   // info
+       MOVQ    DX, 16(SP)  // ctx
+       CALL    runtime·sigtrampgo(SB)
        RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$0
index d6628848f78ab68e0c48d9f3442a8f870d28e5eb..3d3b65ffa952de61bb4357c96f1bc8a466b704c2 100644 (file)
@@ -213,7 +213,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$4
        MOVW.CS R8, (R8)
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$24
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+       MOVW    sig+4(FP), R0
+       MOVW    info+8(FP), R1
+       MOVW    ctx+12(FP), R2
+       MOVW    fn+0(FP), R11
+       MOVW    R13, R4
+       SUB     $24, R13
+       BIC     $0x7, R13 // alignment for ELF ABI
+       BL      (R11)
+       MOVW    R4, R13
+       RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
        // this might be called in external code context,
        // where g is not set.
        // first save R0, because runtime·load_g will clobber it
@@ -222,30 +234,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
        CMP     $0, R0
        BL.NE   runtime·load_g(SB)
 
-       CMP $0, g
-       BNE 4(PC)
-       // signal number is already prepared in 4(R13)
-       MOVW $runtime·badsignal(SB), R11
-       BL (R11)
-       RET
-
-       // save g
-       MOVW g, R4
-       MOVW g, 20(R13)
-
-       // g = m->signal
-       MOVW g_m(g), R8
-       MOVW m_gsignal(R8), g
-
-       // R0 is already saved
-       MOVW R1, 8(R13) // info
-       MOVW R2, 12(R13) // context
-       MOVW R4, 16(R13) // gp
-
-       BL runtime·sighandler(SB)
-
-       // restore g
-       MOVW 20(R13), g
+       MOVW    R1, 8(R13)
+       MOVW    R2, 12(R13)
+       BL      runtime·sigtrampgo(SB)
        RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$12
index bdf18d88f9c411037dcb1f3c123902024ecab741..769b2f9455f5c8cbfbbc337ba9b3dc5426810bd3 100644 (file)
@@ -195,44 +195,26 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$-4
        MOVL    AX, ret+8(FP)
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$44
-       get_tls(CX)
-
-       // check that g exists
-       MOVL    g(CX), DI
-       CMPL    DI, $0
-       JNE     6(PC)
-       MOVL    signo+0(FP), BX
-       MOVL    BX, 0(SP)
-       MOVL    $runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
+       MOVL    sig+4(FP), AX
+       MOVL    AX, 0(SP)
+       MOVL    info+8(FP), AX
+       MOVL    AX, 4(SP)
+       MOVL    ctx+12(FP), AX
+       MOVL    AX, 8(SP)
+       MOVL    fn+0(FP), AX
        CALL    AX
-       JMP     ret
-
-       // save g
-       MOVL    DI, 20(SP)
-       
-       // g = m->gsignal
-       MOVL    g_m(DI), BX
-       MOVL    m_gsignal(BX), BX
-       MOVL    BX, g(CX)
+       RET
 
-       // copy arguments for call to sighandler
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
        MOVL    signo+0(FP), BX
        MOVL    BX, 0(SP)
        MOVL    info+4(FP), BX
        MOVL    BX, 4(SP)
        MOVL    context+8(FP), BX
        MOVL    BX, 8(SP)
-       MOVL    DI, 12(SP)
-
-       CALL    runtime·sighandler(SB)
-
-       // restore g
-       get_tls(CX)
-       MOVL    20(SP), BX
-       MOVL    BX, g(CX)
+       CALL    runtime·sigtrampgo(SB)
 
-ret:
        // call sigreturn
        MOVL    context+8(FP), AX
        MOVL    $0, 0(SP)               // syscall gap
index 381354ea09be03953624fc482a9dbbd3a822adc0..ed368babc086a1621e4409b373be4e972be40aa1 100644 (file)
@@ -228,37 +228,19 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
        MOVL    AX, ret+8(FP)
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$64
-       get_tls(BX)
-       
-       // check that g exists
-       MOVQ    g(BX), R10
-       CMPQ    R10, $0
-       JNE     5(PC)
-       MOVQ    DI, 0(SP)
-       MOVQ    $runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+       MOVL    sig+8(FP), DI
+       MOVQ    info+16(FP), SI
+       MOVQ    ctx+24(FP), DX
+       MOVQ    fn+0(FP), AX
        CALL    AX
        RET
 
-       // save g
-       MOVQ    R10, 40(SP)
-       
-       // g = m->signal
-       MOVQ    g_m(R10), AX
-       MOVQ    m_gsignal(AX), AX
-       MOVQ    AX, g(BX)
-       
+TEXT runtime·sigtramp(SB),NOSPLIT,$24
        MOVQ    DI, 0(SP)
        MOVQ    SI, 8(SP)
        MOVQ    DX, 16(SP)
-       MOVQ    R10, 24(SP)
-       
-       CALL    runtime·sighandler(SB)
-
-       // restore g
-       get_tls(BX)
-       MOVQ    40(SP), R10
-       MOVQ    R10, g(BX)
+       CALL    runtime·sigtrampgo(SB)
        RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$0
index 8c951e46d437605bf59ecc03a3c1eda2a0b4e584..29e89710af26f3c3a328c76b83473ea3ede573af 100644 (file)
@@ -208,7 +208,19 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
        MOVW    R0, ret+8(FP)
        RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$24
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+       MOVW    sig+4(FP), R0
+       MOVW    info+8(FP), R1
+       MOVW    ctx+12(FP), R2
+       MOVW    fn+0(FP), R11
+       MOVW    R13, R4
+       SUB     $24, R13
+       BIC     $0x7, R13 // alignment for ELF ABI
+       BL      (R11)
+       MOVW    R4, R13
+       RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
        // If called from an external code context, g will not be set.
        // Save R0, since runtime·load_g will clobber it.
        MOVW    R0, 4(R13)              // signum
@@ -216,30 +228,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
        CMP     $0, R0
        BL.NE   runtime·load_g(SB)
 
-       CMP     $0, g
-       BNE     4(PC)
-       // Signal number saved in 4(R13).
-       MOVW    runtime·badsignal(SB), R11
-       BL      (R11)
-       RET
-
-       // Save g.
-       MOVW    g, R3
-       MOVW    g, 20(R13)
-
-       // g = m->signal
-       MOVW    g_m(g), R8
-       MOVW    m_gsignal(R8), g
-
-       // R0 already saved.
-       MOVW    R1, 8(R13)              // info
-       MOVW    R2, 12(R13)             // context
-       MOVW    R3, 16(R13)             // gp (original g)
-
-       BL      runtime·sighandler(SB)
-
-       // Restore g.
-       MOVW    20(R13), g
+       MOVW    R1, 8(R13)
+       MOVW    R2, 12(R13)
+       BL      runtime·sigtrampgo(SB)
        RET
 
 // int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
index 179dfa305f81dd4d5707fe8ba20bb35309f514bc..3a82674684b0fdbe3e6c5db7718d5b8ea0c538f8 100644 (file)
@@ -224,6 +224,8 @@ allgood:
        MOVQ    m_gsignal(BP), BP
        MOVQ    BP, g(BX)
 
+       // TODO: If current SP is not in gsignal.stack, then adjust.
+
        // prepare call
        MOVQ    DI, 0(SP)
        MOVQ    SI, 8(SP)