mirror of https://github.com/golang/go.git
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: Mikio Hara <mikioh.mikioh@gmail.com>
This commit is contained in:
parent
e4dcf5c8c2
commit
f7e51c1320
|
|
@ -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) }
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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 @@
|
|||
// 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -242,53 +242,49 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0
|
|||
MOVL $0xf1, 0xf1 // crash
|
||||
RET
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
// 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
|
||||
// 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 $runtime·badsignal(SB), AX
|
||||
CALL AX
|
||||
JMP ret
|
||||
|
||||
// save g
|
||||
MOVL DI, 20(SP)
|
||||
|
||||
// g = m->gsignal
|
||||
MOVL g_m(DI), BP
|
||||
MOVL m_gsignal(BP), BP
|
||||
MOVL BP, g(CX)
|
||||
|
||||
// copy arguments to sighandler
|
||||
MOVL sig+8(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 info+12(FP), BX
|
||||
MOVL BX, 12(SP)
|
||||
MOVL context+16(FP), BX
|
||||
MOVL BX, 16(SP)
|
||||
CALL runtime·sigtrampgo(SB)
|
||||
|
||||
MOVL handler+0(FP), BX
|
||||
CALL BX
|
||||
|
||||
// restore g
|
||||
get_tls(CX)
|
||||
MOVL 20(SP), DI
|
||||
MOVL DI, g(CX)
|
||||
|
||||
ret:
|
||||
// call sigreturn
|
||||
MOVL context+16(FP), CX
|
||||
MOVL style+4(FP), BX
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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·sigtrampgo(SB)
|
||||
|
||||
CALL runtime·sighandler(SB)
|
||||
|
||||
// restore g
|
||||
get_tls(CX)
|
||||
MOVL 20(SP), BX
|
||||
MOVL BX, g(CX)
|
||||
|
||||
ret:
|
||||
// call sigreturn
|
||||
MOVL context+8(FP), AX
|
||||
MOVL $0, 0(SP) // syscall gap
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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·sigtrampgo(SB)
|
||||
|
||||
CALL runtime·sighandler(SB)
|
||||
|
||||
// restore g
|
||||
get_tls(CX)
|
||||
MOVL 20(SP), BX
|
||||
MOVL BX, g(CX)
|
||||
|
||||
ret:
|
||||
// call sigreturn
|
||||
MOVL context+8(FP), AX
|
||||
MOVL $0, 0(SP) // syscall gap
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue