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

runtime: adjust gsignal stack to current signal stack

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: 's avatarMikio Hara <mikioh.mikioh@gmail.com>
parent e4dcf5c8
// 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) }
// 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)
}
...@@ -249,3 +249,19 @@ func ensureSigM() { ...@@ -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")
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin linux // +build darwin dragonfly freebsd linux netbsd openbsd
package runtime package runtime
......
...@@ -61,6 +61,29 @@ func sigtrampgo(fn uintptr, infostyle, sig uint32, info *siginfo, ctx unsafe.Poi ...@@ -61,6 +61,29 @@ func sigtrampgo(fn uintptr, infostyle, sig uint32, info *siginfo, ctx unsafe.Poi
sigreturn(ctx, infostyle) sigreturn(ctx, infostyle)
return 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) setg(g.m.gsignal)
sighandler(sig, info, ctx, g) sighandler(sig, info, ctx, g)
setg(g) setg(g)
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package runtime package runtime
import "unsafe"
type sigTabT struct { type sigTabT struct {
flags int32 flags int32
name string name string
...@@ -44,3 +46,41 @@ var sigtable = [...]sigTabT{ ...@@ -44,3 +46,41 @@ 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
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)
}
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package runtime package runtime
import "unsafe"
type sigTabT struct { type sigTabT struct {
flags int32 flags int32
name string name string
...@@ -44,3 +46,41 @@ var sigtable = [...]sigTabT{ ...@@ -44,3 +46,41 @@ 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
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)
}
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build dragonfly linux netbsd
package runtime package runtime
import "unsafe" import "unsafe"
...@@ -17,6 +19,29 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { ...@@ -17,6 +19,29 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
badsignal(uintptr(sig)) badsignal(uintptr(sig))
return 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) setg(g.m.gsignal)
sighandler(sig, info, ctx, g) sighandler(sig, info, ctx, g)
setg(g) setg(g)
......
...@@ -242,53 +242,49 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0 ...@@ -242,53 +242,49 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0
MOVL $0xf1, 0xf1 // crash MOVL $0xf1, 0xf1 // crash
RET RET
// Sigtramp's job is to call the actual signal handler. TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
// It is called with the following arguments on the stack: MOVL sig+4(FP), AX
// 0(FP) "return address" - ignored MOVL AX, 0(SP)
// 4(FP) actual handler MOVL info+8(FP), AX
// 8(FP) signal number MOVL AX, 4(SP)
// 12(FP) siginfo style MOVL ctx+12(FP), AX
// 16(FP) siginfo MOVL AX, 8(SP)
// 20(FP) context MOVL fn+0(FP), AX
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
CALL AX CALL AX
JMP ret RET
// save g
MOVL DI, 20(SP)
// g = m->gsignal TEXT runtime·sigreturn(SB),NOSPLIT,$12-8
MOVL g_m(DI), BP MOVL ctx+0(FP), CX
MOVL m_gsignal(BP), BP MOVL infostyle+4(FP), BX
MOVL BP, g(CX) 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 // Sigtramp's job is to call the actual signal handler.
MOVL sig+8(FP), BX // 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 BX, 0(SP)
MOVL info+12(FP), BX MOVL style+4(FP), BX
MOVL BX, 4(SP) MOVL BX, 4(SP)
MOVL context+16(FP), BX MOVL sig+8(FP), BX
MOVL BX, 8(SP) MOVL BX, 8(SP)
MOVL DI, 12(SP) MOVL info+12(FP), BX
MOVL BX, 12(SP)
MOVL handler+0(FP), BX MOVL context+16(FP), BX
CALL BX MOVL BX, 16(SP)
CALL runtime·sigtrampgo(SB)
// restore g
get_tls(CX)
MOVL 20(SP), DI
MOVL DI, g(CX)
ret:
// call sigreturn // call sigreturn
MOVL context+16(FP), CX MOVL context+16(FP), CX
MOVL style+4(FP), BX MOVL style+4(FP), BX
......
...@@ -194,6 +194,18 @@ TEXT runtime·nanotime(SB),NOSPLIT,$32 ...@@ -194,6 +194,18 @@ TEXT runtime·nanotime(SB),NOSPLIT,$32
MOVW R1, ret_hi+4(FP) MOVW R1, ret_hi+4(FP)
RET 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. // 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:
// LR "return address" - ignored // LR "return address" - ignored
......
...@@ -180,6 +180,14 @@ TEXT runtime·nanotime(SB),NOSPLIT,$40 ...@@ -180,6 +180,14 @@ TEXT runtime·nanotime(SB),NOSPLIT,$40
MOVD R0, ret+0(FP) MOVD R0, ret+0(FP)
RET 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. // 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:
// LR "return address" - ignored // LR "return address" - ignored
......
...@@ -187,37 +187,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8 ...@@ -187,37 +187,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
MOVL $0xf1, 0xf1 // crash MOVL $0xf1, 0xf1 // crash
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$64 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
get_tls(BX) MOVL sig+8(FP), DI
MOVQ info+16(FP), SI
// check that g exists MOVQ ctx+24(FP), DX
MOVQ g(BX), R10 MOVQ fn+0(FP), AX
CMPQ R10, $0
JNE 5(PC)
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
CALL AX CALL AX
RET RET
// save g TEXT runtime·sigtramp(SB),NOSPLIT,$24
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 DI, 0(SP)
MOVQ SI, 8(SP) MOVQ SI, 8(SP)
MOVQ DX, 16(SP) MOVQ DX, 16(SP)
MOVQ R10, 24(SP) CALL runtime·sigtrampgo(SB)
CALL runtime·sighandler(SB)
// restore g
get_tls(BX)
MOVQ 40(SP), R10
MOVQ R10, g(BX)
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$0 TEXT runtime·mmap(SB),NOSPLIT,$0
......
...@@ -207,44 +207,26 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-4 ...@@ -207,44 +207,26 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-4
MOVL $0xf1, 0xf1 // crash MOVL $0xf1, 0xf1 // crash
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$44 TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
get_tls(CX) MOVL sig+4(FP), AX
MOVL AX, 0(SP)
// check that g exists MOVL info+8(FP), AX
MOVL g(CX), DI MOVL AX, 4(SP)
CMPL DI, $0 MOVL ctx+12(FP), AX
JNE 6(PC) MOVL AX, 8(SP)
MOVL signo+0(FP), BX MOVL fn+0(FP), AX
MOVL BX, 0(SP)
MOVL $runtime·badsignal(SB), AX
CALL AX CALL AX
JMP ret 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 signo+0(FP), BX
MOVL BX, 0(SP) MOVL BX, 0(SP)
MOVL info+4(FP), BX MOVL info+4(FP), BX
MOVL BX, 4(SP) MOVL BX, 4(SP)
MOVL context+8(FP), BX MOVL context+8(FP), BX
MOVL BX, 8(SP) MOVL BX, 8(SP)
MOVL DI, 12(SP) CALL runtime·sigtrampgo(SB)
CALL runtime·sighandler(SB)
// restore g
get_tls(CX)
MOVL 20(SP), BX
MOVL BX, g(CX)
ret:
// call sigreturn // call sigreturn
MOVL context+8(FP), AX MOVL context+8(FP), AX
MOVL $0, 0(SP) // syscall gap MOVL $0, 0(SP) // syscall gap
......
...@@ -183,37 +183,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8 ...@@ -183,37 +183,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
MOVL $0xf1, 0xf1 // crash MOVL $0xf1, 0xf1 // crash
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$64 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
get_tls(BX) MOVL sig+8(FP), DI
MOVQ info+16(FP), SI
// check that g exists MOVQ ctx+24(FP), DX
MOVQ g(BX), R10 MOVQ fn+0(FP), AX
CMPQ R10, $0
JNE 5(PC)
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
CALL AX CALL AX
RET RET
// save g TEXT runtime·sigtramp(SB),NOSPLIT,$24
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 DI, 0(SP)
MOVQ SI, 8(SP) MOVQ SI, 8(SP)
MOVQ DX, 16(SP) MOVQ DX, 16(SP)
MOVQ R10, 24(SP) CALL runtime·sigtrampgo(SB)
CALL runtime·sighandler(SB)
// restore g
get_tls(BX)
MOVQ 40(SP), R10
MOVQ R10, g(BX)
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$0 TEXT runtime·mmap(SB),NOSPLIT,$0
......
...@@ -216,7 +216,7 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8 ...@@ -216,7 +216,7 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
MOVW.CS R8, (R8) MOVW.CS R8, (R8)
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$24 TEXT runtime·sigtramp(SB),NOSPLIT,$12
// this might be called in external code context, // this might be called in external code context,
// where g is not set. // where g is not set.
// first save R0, because runtime·load_g will clobber it // first save R0, because runtime·load_g will clobber it
...@@ -225,30 +225,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24 ...@@ -225,30 +225,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
CMP $0, R0 CMP $0, R0
BL.NE runtime·load_g(SB) BL.NE runtime·load_g(SB)
CMP $0, g MOVW R1, 8(R13)
BNE 4(PC) MOVW R2, 12(R13)
// signal number is already prepared in 4(R13) BL runtime·sigtrampgo(SB)
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
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$16 TEXT runtime·mmap(SB),NOSPLIT,$16
...@@ -300,6 +279,18 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8 ...@@ -300,6 +279,18 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
MOVW.CS R8, (R8) MOVW.CS R8, (R8)
RET 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 TEXT runtime·usleep(SB),NOSPLIT,$16
MOVW usec+0(FP), R0 MOVW usec+0(FP), R0
CALL runtime·usplitR0(SB) CALL runtime·usplitR0(SB)
......
...@@ -215,42 +215,25 @@ TEXT runtime·sigaction(SB),NOSPLIT,$24 ...@@ -215,42 +215,25 @@ TEXT runtime·sigaction(SB),NOSPLIT,$24
MOVL $0xf1, 0xf1 // crash MOVL $0xf1, 0xf1 // crash
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$44 TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
get_tls(CX) MOVL sig+4(FP), AX
MOVL AX, 0(SP)
// check that g exists MOVL info+8(FP), AX
MOVL g(CX), DI MOVL AX, 4(SP)
CMPL DI, $0 MOVL ctx+12(FP), AX
JNE 6(PC) MOVL AX, 8(SP)
MOVL signo+0(FP), BX MOVL fn+0(FP), AX
MOVL BX, 0(SP)
MOVL $runtime·badsignal(SB), AX
CALL AX CALL AX
RET RET
// save g TEXT runtime·sigtramp(SB),NOSPLIT,$12
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
MOVL signo+0(FP), BX MOVL signo+0(FP), BX
MOVL BX, 0(SP) MOVL BX, 0(SP)
MOVL info+4(FP), BX MOVL info+4(FP), BX
MOVL BX, 4(SP) MOVL BX, 4(SP)
MOVL context+8(FP), BX MOVL context+8(FP), BX
MOVL BX, 8(SP) MOVL BX, 8(SP)
MOVL DI, 12(SP) CALL runtime·sigtrampgo(SB)
CALL runtime·sighandler(SB)
// restore g
get_tls(CX)
MOVL 20(SP), BX
MOVL BX, g(CX)
RET RET
// int32 lwp_create(void *context, uintptr flags, void *lwpid); // int32 lwp_create(void *context, uintptr flags, void *lwpid);
......
...@@ -237,37 +237,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8 ...@@ -237,37 +237,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
MOVL $0xf1, 0xf1 // crash MOVL $0xf1, 0xf1 // crash
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$64 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
get_tls(BX) MOVL sig+8(FP), DI
MOVQ info+16(FP), SI
// check that g exists MOVQ ctx+24(FP), DX
MOVQ g(BX), R10 MOVQ fn+0(FP), AX
CMPQ R10, $0
JNE 5(PC)
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
CALL AX CALL AX
RET RET
// save g TEXT runtime·sigtramp(SB),NOSPLIT,$24
MOVQ R10, 40(SP) MOVQ DI, 0(SP) // signum
MOVQ SI, 8(SP) // info
// g = m->signal MOVQ DX, 16(SP) // ctx
MOVQ g_m(R10), AX CALL runtime·sigtrampgo(SB)
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)
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$0 TEXT runtime·mmap(SB),NOSPLIT,$0
......
...@@ -213,7 +213,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$4 ...@@ -213,7 +213,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$4
MOVW.CS R8, (R8) MOVW.CS R8, (R8)
RET 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, // this might be called in external code context,
// where g is not set. // where g is not set.
// first save R0, because runtime·load_g will clobber it // first save R0, because runtime·load_g will clobber it
...@@ -222,30 +234,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24 ...@@ -222,30 +234,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
CMP $0, R0 CMP $0, R0
BL.NE runtime·load_g(SB) BL.NE runtime·load_g(SB)
CMP $0, g MOVW R1, 8(R13)
BNE 4(PC) MOVW R2, 12(R13)
// signal number is already prepared in 4(R13) BL runtime·sigtrampgo(SB)
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
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$12 TEXT runtime·mmap(SB),NOSPLIT,$12
......
...@@ -195,44 +195,26 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$-4 ...@@ -195,44 +195,26 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$-4
MOVL AX, ret+8(FP) MOVL AX, ret+8(FP)
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$44 TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
get_tls(CX) MOVL sig+4(FP), AX
MOVL AX, 0(SP)
// check that g exists MOVL info+8(FP), AX
MOVL g(CX), DI MOVL AX, 4(SP)
CMPL DI, $0 MOVL ctx+12(FP), AX
JNE 6(PC) MOVL AX, 8(SP)
MOVL signo+0(FP), BX MOVL fn+0(FP), AX
MOVL BX, 0(SP)
MOVL $runtime·badsignal(SB), AX
CALL AX CALL AX
JMP ret 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 signo+0(FP), BX
MOVL BX, 0(SP) MOVL BX, 0(SP)
MOVL info+4(FP), BX MOVL info+4(FP), BX
MOVL BX, 4(SP) MOVL BX, 4(SP)
MOVL context+8(FP), BX MOVL context+8(FP), BX
MOVL BX, 8(SP) MOVL BX, 8(SP)
MOVL DI, 12(SP) CALL runtime·sigtrampgo(SB)
CALL runtime·sighandler(SB)
// restore g
get_tls(CX)
MOVL 20(SP), BX
MOVL BX, g(CX)
ret:
// call sigreturn // call sigreturn
MOVL context+8(FP), AX MOVL context+8(FP), AX
MOVL $0, 0(SP) // syscall gap MOVL $0, 0(SP) // syscall gap
......
...@@ -228,37 +228,19 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0 ...@@ -228,37 +228,19 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
MOVL AX, ret+8(FP) MOVL AX, ret+8(FP)
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$64 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
get_tls(BX) MOVL sig+8(FP), DI
MOVQ info+16(FP), SI
// check that g exists MOVQ ctx+24(FP), DX
MOVQ g(BX), R10 MOVQ fn+0(FP), AX
CMPQ R10, $0
JNE 5(PC)
MOVQ DI, 0(SP)
MOVQ $runtime·badsignal(SB), AX
CALL AX CALL AX
RET RET
// save g TEXT runtime·sigtramp(SB),NOSPLIT,$24
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 DI, 0(SP)
MOVQ SI, 8(SP) MOVQ SI, 8(SP)
MOVQ DX, 16(SP) MOVQ DX, 16(SP)
MOVQ R10, 24(SP) CALL runtime·sigtrampgo(SB)
CALL runtime·sighandler(SB)
// restore g
get_tls(BX)
MOVQ 40(SP), R10
MOVQ R10, g(BX)
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$0 TEXT runtime·mmap(SB),NOSPLIT,$0
......
...@@ -208,7 +208,19 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0 ...@@ -208,7 +208,19 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
MOVW R0, ret+8(FP) MOVW R0, ret+8(FP)
RET 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. // If called from an external code context, g will not be set.
// Save R0, since runtime·load_g will clobber it. // Save R0, since runtime·load_g will clobber it.
MOVW R0, 4(R13) // signum MOVW R0, 4(R13) // signum
...@@ -216,30 +228,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24 ...@@ -216,30 +228,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
CMP $0, R0 CMP $0, R0
BL.NE runtime·load_g(SB) BL.NE runtime·load_g(SB)
CMP $0, g MOVW R1, 8(R13)
BNE 4(PC) MOVW R2, 12(R13)
// Signal number saved in 4(R13). BL runtime·sigtrampgo(SB)
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
RET RET
// int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void)); // int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
......
...@@ -224,6 +224,8 @@ allgood: ...@@ -224,6 +224,8 @@ allgood:
MOVQ m_gsignal(BP), BP MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX) MOVQ BP, g(BX)
// TODO: If current SP is not in gsignal.stack, then adjust.
// prepare call // prepare call
MOVQ DI, 0(SP) MOVQ DI, 0(SP)
MOVQ SI, 8(SP) MOVQ SI, 8(SP)
......
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