Commit 29cb7215 authored by Bryan C. Mills's avatar Bryan C. Mills Committed by Ian Lance Taylor

runtime: preserve callee-saved C registers in sigtramp

This fixes Linux and the *BSD platforms on 386/amd64.

A few OS/arch combinations were already saving registers and/or doing
something that doesn't clearly resemble the SysV C ABI; those have
been left alone.

Fixes #18328.

Change-Id: I6398f6c71020de108fc8b26ca5946f0ba0258667
Reviewed-on: https://go-review.googlesource.com/34501
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent c1d449c4
...@@ -6,7 +6,8 @@ package main ...@@ -6,7 +6,8 @@ package main
// This program failed when run under the C/C++ ThreadSanitizer. The // This program failed when run under the C/C++ ThreadSanitizer. The
// TSAN library was not keeping track of whether signals should be // TSAN library was not keeping track of whether signals should be
// delivered on the alternate signal stack. // delivered on the alternate signal stack, and the Go signal handler
// was not preserving callee-saved registers from C callers.
/* /*
#cgo CFLAGS: -g -fsanitize=thread #cgo CFLAGS: -g -fsanitize=thread
...@@ -19,10 +20,14 @@ void spin() { ...@@ -19,10 +20,14 @@ void spin() {
size_t n; size_t n;
struct timeval tvstart, tvnow; struct timeval tvstart, tvnow;
int diff; int diff;
void *prev = NULL, *cur;
gettimeofday(&tvstart, NULL); gettimeofday(&tvstart, NULL);
for (n = 0; n < 1<<20; n++) { for (n = 0; n < 1<<20; n++) {
free(malloc(n)); cur = malloc(n);
free(prev);
prev = cur;
gettimeofday(&tvnow, NULL); gettimeofday(&tvnow, NULL);
diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec); diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec);
...@@ -32,6 +37,8 @@ void spin() { ...@@ -32,6 +37,8 @@ void spin() {
break; break;
} }
} }
free(prev);
} }
*/ */
import "C" import "C"
......
...@@ -200,11 +200,28 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 ...@@ -200,11 +200,28 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
POPQ BP POPQ BP
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$24 TEXT runtime·sigtramp(SB),NOSPLIT,$72
MOVQ DI, 0(SP) // Save callee-saved C registers, since the caller may be a C signal handler.
MOVQ SI, 8(SP) MOVQ BX, bx-8(SP)
MOVQ DX, 16(SP) MOVQ BP, bp-16(SP) // save in case GOEXPERIMENT=noframepointer is set
MOVQ R12, r12-24(SP)
MOVQ R13, r13-32(SP)
MOVQ R14, r14-40(SP)
MOVQ R15, r15-48(SP)
// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
// modify them.
MOVQ DX, ctx-56(SP)
MOVQ SI, info-64(SP)
MOVQ DI, signum-72(SP)
CALL runtime·sigtrampgo(SB) CALL runtime·sigtrampgo(SB)
MOVQ r15-48(SP), R15
MOVQ r14-40(SP), R14
MOVQ r13-32(SP), R13
MOVQ r12-24(SP), R12
MOVQ bp-16(SP), BP
MOVQ bx-8(SP), BX
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$0 TEXT runtime·mmap(SB),NOSPLIT,$0
......
...@@ -196,11 +196,28 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 ...@@ -196,11 +196,28 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
POPQ BP POPQ BP
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$24 TEXT runtime·sigtramp(SB),NOSPLIT,$72
MOVQ DI, 0(SP) // Save callee-saved C registers, since the caller may be a C signal handler.
MOVQ SI, 8(SP) MOVQ BX, bx-8(SP)
MOVQ DX, 16(SP) MOVQ BP, bp-16(SP) // save in case GOEXPERIMENT=noframepointer is set
MOVQ R12, r12-24(SP)
MOVQ R13, r13-32(SP)
MOVQ R14, r14-40(SP)
MOVQ R15, r15-48(SP)
// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
// modify them.
MOVQ DX, ctx-56(SP)
MOVQ SI, info-64(SP)
MOVQ DI, signum-72(SP)
CALL runtime·sigtrampgo(SB) CALL runtime·sigtrampgo(SB)
MOVQ r15-48(SP), R15
MOVQ r14-40(SP), R14
MOVQ r13-32(SP), R13
MOVQ r12-24(SP), R12
MOVQ bp-16(SP), BP
MOVQ bx-8(SP), BX
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$0 TEXT runtime·mmap(SB),NOSPLIT,$0
......
...@@ -228,7 +228,15 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$12-16 ...@@ -228,7 +228,15 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
MOVL AX, SP MOVL AX, SP
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$12 TEXT runtime·sigtramp(SB),NOSPLIT,$28
// Save callee-saved C registers, since the caller may be a C signal handler.
MOVL BX, bx-4(SP)
MOVL BP, bp-8(SP)
MOVL SI, si-12(SP)
MOVL DI, di-16(SP)
// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
// modify them.
MOVL sig+0(FP), BX MOVL sig+0(FP), BX
MOVL BX, 0(SP) MOVL BX, 0(SP)
MOVL info+4(FP), BX MOVL info+4(FP), BX
...@@ -236,6 +244,11 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$12 ...@@ -236,6 +244,11 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$12
MOVL ctx+8(FP), BX MOVL ctx+8(FP), BX
MOVL BX, 8(SP) MOVL BX, 8(SP)
CALL runtime·sigtrampgo(SB) CALL runtime·sigtrampgo(SB)
MOVL di-16(SP), DI
MOVL si-12(SP), SI
MOVL bp-8(SP), BP
MOVL bx-4(SP), BX
RET RET
TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
......
...@@ -244,12 +244,29 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 ...@@ -244,12 +244,29 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
POPQ BP POPQ BP
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$24 TEXT runtime·sigtramp(SB),NOSPLIT,$72
MOVQ DI, 0(SP) // signum // Save callee-saved C registers, since the caller may be a C signal handler.
MOVQ SI, 8(SP) // info MOVQ BX, bx-8(SP)
MOVQ DX, 16(SP) // ctx MOVQ BP, bp-16(SP) // save in case GOEXPERIMENT=noframepointer is set
MOVQ R12, r12-24(SP)
MOVQ R13, r13-32(SP)
MOVQ R14, r14-40(SP)
MOVQ R15, r15-48(SP)
// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
// modify them.
MOVQ DX, ctx-56(SP)
MOVQ SI, info-64(SP)
MOVQ DI, signum-72(SP)
MOVQ $runtime·sigtrampgo(SB), AX MOVQ $runtime·sigtrampgo(SB), AX
CALL AX CALL AX
MOVQ r15-48(SP), R15
MOVQ r14-40(SP), R14
MOVQ r13-32(SP), R13
MOVQ r12-24(SP), R12
MOVQ bp-16(SP), BP
MOVQ bx-8(SP), BX
RET RET
// Used instead of sigtramp in programs that use cgo. // Used instead of sigtramp in programs that use cgo.
......
...@@ -232,7 +232,15 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$12-16 ...@@ -232,7 +232,15 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
MOVL AX, SP MOVL AX, SP
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$12 TEXT runtime·sigtramp(SB),NOSPLIT,$28
// Save callee-saved C registers, since the caller may be a C signal handler.
MOVL BX, bx-4(SP)
MOVL BP, bp-8(SP)
MOVL SI, si-12(SP)
MOVL DI, di-16(SP)
// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
// modify them.
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
...@@ -240,6 +248,11 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$12 ...@@ -240,6 +248,11 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$12
MOVL context+8(FP), BX MOVL context+8(FP), BX
MOVL BX, 8(SP) MOVL BX, 8(SP)
CALL runtime·sigtrampgo(SB) CALL runtime·sigtrampgo(SB)
MOVL di-16(SP), DI
MOVL si-12(SP), SI
MOVL bp-8(SP), BP
MOVL bx-4(SP), BX
RET RET
// int32 lwp_create(void *context, uintptr flags, void *lwpid); // int32 lwp_create(void *context, uintptr flags, void *lwpid);
......
...@@ -250,13 +250,28 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 ...@@ -250,13 +250,28 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
POPQ BP POPQ BP
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$32 TEXT runtime·sigtramp(SB),NOSPLIT,$72
MOVQ DI, 0(SP) // signum // Save callee-saved C registers, since the caller may be a C signal handler.
MOVQ SI, 8(SP) // info MOVQ BX, bx-8(SP)
MOVQ DX, 16(SP) // ctx MOVQ BP, bp-16(SP) // save in case GOEXPERIMENT=noframepointer is set
MOVQ R15, 24(SP) // for sigreturn MOVQ R12, r12-24(SP)
MOVQ R13, r13-32(SP)
MOVQ R14, r14-40(SP)
MOVQ R15, r15-48(SP)
// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
// modify them.
MOVQ DX, ctx-56(SP)
MOVQ SI, info-64(SP)
MOVQ DI, signum-72(SP)
CALL runtime·sigtrampgo(SB) CALL runtime·sigtrampgo(SB)
MOVQ 24(SP), R15
MOVQ r15-48(SP), R15
MOVQ r14-40(SP), R14
MOVQ r13-32(SP), R13
MOVQ r12-24(SP), R12
MOVQ bp-16(SP), BP
MOVQ bx-8(SP), BX
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$0 TEXT runtime·mmap(SB),NOSPLIT,$0
......
...@@ -213,7 +213,15 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$12-16 ...@@ -213,7 +213,15 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
MOVL AX, SP MOVL AX, SP
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$12 TEXT runtime·sigtramp(SB),NOSPLIT,$28
// Save callee-saved C registers, since the caller may be a C signal handler.
MOVL BX, bx-4(SP)
MOVL BP, bp-8(SP)
MOVL SI, si-12(SP)
MOVL DI, di-16(SP)
// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
// modify them.
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
...@@ -221,6 +229,11 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$12 ...@@ -221,6 +229,11 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$12
MOVL context+8(FP), BX MOVL context+8(FP), BX
MOVL BX, 8(SP) MOVL BX, 8(SP)
CALL runtime·sigtrampgo(SB) CALL runtime·sigtrampgo(SB)
MOVL di-16(SP), DI
MOVL si-12(SP), SI
MOVL bp-8(SP), BP
MOVL bx-4(SP), BX
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));
......
...@@ -242,11 +242,28 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 ...@@ -242,11 +242,28 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
POPQ BP POPQ BP
RET RET
TEXT runtime·sigtramp(SB),NOSPLIT,$24 TEXT runtime·sigtramp(SB),NOSPLIT,$72
MOVQ DI, 0(SP) // Save callee-saved C registers, since the caller may be a C signal handler.
MOVQ SI, 8(SP) MOVQ BX, bx-8(SP)
MOVQ DX, 16(SP) MOVQ BP, bp-16(SP) // save in case GOEXPERIMENT=noframepointer is set
MOVQ R12, r12-24(SP)
MOVQ R13, r13-32(SP)
MOVQ R14, r14-40(SP)
MOVQ R15, r15-48(SP)
// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
// modify them.
MOVQ DX, ctx-56(SP)
MOVQ SI, info-64(SP)
MOVQ DI, signum-72(SP)
CALL runtime·sigtrampgo(SB) CALL runtime·sigtrampgo(SB)
MOVQ r15-48(SP), R15
MOVQ r14-40(SP), R14
MOVQ r13-32(SP), R13
MOVQ r12-24(SP), R12
MOVQ bp-16(SP), BP
MOVQ bx-8(SP), BX
RET RET
TEXT runtime·mmap(SB),NOSPLIT,$0 TEXT runtime·mmap(SB),NOSPLIT,$0
......
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