summaryrefslogtreecommitdiffhomepage
path: root/pkg/safecopy
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/safecopy')
-rw-r--r--pkg/safecopy/atomic_amd64.s24
-rw-r--r--pkg/safecopy/atomic_arm64.s24
-rw-r--r--pkg/safecopy/memclr_amd64.s6
-rw-r--r--pkg/safecopy/memclr_arm64.s6
-rw-r--r--pkg/safecopy/memcpy_amd64.s6
-rw-r--r--pkg/safecopy/memcpy_arm64.s6
-rw-r--r--pkg/safecopy/safecopy.go22
-rw-r--r--pkg/safecopy/safecopy_unsafe.go12
-rw-r--r--pkg/safecopy/sighandler_amd64.s6
-rw-r--r--pkg/safecopy/sighandler_arm64.s6
10 files changed, 109 insertions, 9 deletions
diff --git a/pkg/safecopy/atomic_amd64.s b/pkg/safecopy/atomic_amd64.s
index a0cd78f33..290579e53 100644
--- a/pkg/safecopy/atomic_amd64.s
+++ b/pkg/safecopy/atomic_amd64.s
@@ -44,6 +44,12 @@ TEXT ·swapUint32(SB), NOSPLIT, $0-24
MOVL AX, old+16(FP)
RET
+// func addrOfSwapUint32() uintptr
+TEXT ·addrOfSwapUint32(SB), $0-8
+ MOVQ $·swapUint32(SB), AX
+ MOVQ AX, ret+0(FP)
+ RET
+
// handleSwapUint64Fault returns the value stored in DI. Control is transferred
// to it when swapUint64 below receives SIGSEGV or SIGBUS, with the signal
// number stored in DI.
@@ -74,6 +80,12 @@ TEXT ·swapUint64(SB), NOSPLIT, $0-28
MOVQ AX, old+16(FP)
RET
+// func addrOfSwapUint64() uintptr
+TEXT ·addrOfSwapUint64(SB), $0-8
+ MOVQ $·swapUint64(SB), AX
+ MOVQ AX, ret+0(FP)
+ RET
+
// handleCompareAndSwapUint32Fault returns the value stored in DI. Control is
// transferred to it when swapUint64 below receives SIGSEGV or SIGBUS, with the
// signal number stored in DI.
@@ -107,6 +119,12 @@ TEXT ·compareAndSwapUint32(SB), NOSPLIT, $0-24
MOVL AX, prev+16(FP)
RET
+// func addrOfCompareAndSwapUint32() uintptr
+TEXT ·addrOfCompareAndSwapUint32(SB), $0-8
+ MOVQ $·compareAndSwapUint32(SB), AX
+ MOVQ AX, ret+0(FP)
+ RET
+
// handleLoadUint32Fault returns the value stored in DI. Control is transferred
// to it when LoadUint32 below receives SIGSEGV or SIGBUS, with the signal
// number stored in DI.
@@ -134,3 +152,9 @@ TEXT ·loadUint32(SB), NOSPLIT, $0-16
MOVL (AX), BX
MOVL BX, val+8(FP)
RET
+
+// func addrOfLoadUint32() uintptr
+TEXT ·addrOfLoadUint32(SB), $0-8
+ MOVQ $·loadUint32(SB), AX
+ MOVQ AX, ret+0(FP)
+ RET
diff --git a/pkg/safecopy/atomic_arm64.s b/pkg/safecopy/atomic_arm64.s
index d58ed71f7..55c031a3c 100644
--- a/pkg/safecopy/atomic_arm64.s
+++ b/pkg/safecopy/atomic_arm64.s
@@ -33,6 +33,12 @@ again:
MOVW R2, old+16(FP)
RET
+// func addrOfSwapUint32() uintptr
+TEXT ·addrOfSwapUint32(SB), $0-8
+ MOVD $·swapUint32(SB), R0
+ MOVD R0, ret+0(FP)
+ RET
+
// handleSwapUint64Fault returns the value stored in R1. Control is transferred
// to it when swapUint64 below receives SIGSEGV or SIGBUS, with the signal
// number stored in R1.
@@ -62,6 +68,12 @@ again:
MOVD R2, old+16(FP)
RET
+// func addrOfSwapUint64() uintptr
+TEXT ·addrOfSwapUint64(SB), $0-8
+ MOVD $·swapUint64(SB), R0
+ MOVD R0, ret+0(FP)
+ RET
+
// handleCompareAndSwapUint32Fault returns the value stored in R1. Control is
// transferred to it when compareAndSwapUint32 below receives SIGSEGV or SIGBUS,
// with the signal number stored in R1.
@@ -97,6 +109,12 @@ done:
MOVW R3, prev+16(FP)
RET
+// func addrOfCompareAndSwapUint32() uintptr
+TEXT ·addrOfCompareAndSwapUint32(SB), $0-8
+ MOVD $·compareAndSwapUint32(SB), R0
+ MOVD R0, ret+0(FP)
+ RET
+
// handleLoadUint32Fault returns the value stored in DI. Control is transferred
// to it when LoadUint32 below receives SIGSEGV or SIGBUS, with the signal
// number stored in DI.
@@ -124,3 +142,9 @@ TEXT ·loadUint32(SB), NOSPLIT, $0-16
LDARW (R0), R1
MOVW R1, val+8(FP)
RET
+
+// func addrOfLoadUint32() uintptr
+TEXT ·addrOfLoadUint32(SB), $0-8
+ MOVD $·loadUint32(SB), R0
+ MOVD R0, ret+0(FP)
+ RET
diff --git a/pkg/safecopy/memclr_amd64.s b/pkg/safecopy/memclr_amd64.s
index 64cf32f05..4abaecaff 100644
--- a/pkg/safecopy/memclr_amd64.s
+++ b/pkg/safecopy/memclr_amd64.s
@@ -145,3 +145,9 @@ _129through256:
MOVOU X0, -32(DI)(BX*1)
MOVOU X0, -16(DI)(BX*1)
RET
+
+// func addrOfMemclr() uintptr
+TEXT ·addrOfMemclr(SB), $0-8
+ MOVQ $·memclr(SB), AX
+ MOVQ AX, ret+0(FP)
+ RET
diff --git a/pkg/safecopy/memclr_arm64.s b/pkg/safecopy/memclr_arm64.s
index 7361b9067..c789bfeb3 100644
--- a/pkg/safecopy/memclr_arm64.s
+++ b/pkg/safecopy/memclr_arm64.s
@@ -72,3 +72,9 @@ head_loop:
CMP $16, R1
BLT tail_zero
B aligned_to_16
+
+// func addrOfMemclr() uintptr
+TEXT ·addrOfMemclr(SB), $0-8
+ MOVD $·memclr(SB), R0
+ MOVD R0, ret+0(FP)
+ RET
diff --git a/pkg/safecopy/memcpy_amd64.s b/pkg/safecopy/memcpy_amd64.s
index 00b46c18f..1d63ca1fd 100644
--- a/pkg/safecopy/memcpy_amd64.s
+++ b/pkg/safecopy/memcpy_amd64.s
@@ -217,3 +217,9 @@ move_129through256:
MOVOU -16(SI)(BX*1), X15
MOVOU X15, -16(DI)(BX*1)
RET
+
+// func addrOfMemcpy() uintptr
+TEXT ·addrOfMemcpy(SB), $0-8
+ MOVQ $·memcpy(SB), AX
+ MOVQ AX, ret+0(FP)
+ RET
diff --git a/pkg/safecopy/memcpy_arm64.s b/pkg/safecopy/memcpy_arm64.s
index e7e541565..7b3f50aa5 100644
--- a/pkg/safecopy/memcpy_arm64.s
+++ b/pkg/safecopy/memcpy_arm64.s
@@ -76,3 +76,9 @@ forwardtailloop:
CMP R3, R9
BNE forwardtailloop
RET
+
+// func addrOfMemcpy() uintptr
+TEXT ·addrOfMemcpy(SB), $0-8
+ MOVD $·memcpy(SB), R0
+ MOVD R0, ret+0(FP)
+ RET
diff --git a/pkg/safecopy/safecopy.go b/pkg/safecopy/safecopy.go
index 1e0af5889..df63dd5f1 100644
--- a/pkg/safecopy/safecopy.go
+++ b/pkg/safecopy/safecopy.go
@@ -18,7 +18,6 @@ package safecopy
import (
"fmt"
- "reflect"
"runtime"
"golang.org/x/sys/unix"
@@ -91,6 +90,11 @@ var (
// signals.
func signalHandler()
+// addrOfSignalHandler returns the start address of signalHandler.
+//
+// See comment on addrOfMemcpy for more details.
+func addrOfSignalHandler() uintptr
+
// FindEndAddress returns the end address (one byte beyond the last) of the
// function that contains the specified address (begin).
func FindEndAddress(begin uintptr) uintptr {
@@ -111,26 +115,26 @@ func initializeAddresses() {
// The following functions are written in assembly language, so they won't
// be inlined by the existing compiler/linker. Tests will fail if this
// assumption is violated.
- memcpyBegin = reflect.ValueOf(memcpy).Pointer()
+ memcpyBegin = addrOfMemcpy()
memcpyEnd = FindEndAddress(memcpyBegin)
- memclrBegin = reflect.ValueOf(memclr).Pointer()
+ memclrBegin = addrOfMemclr()
memclrEnd = FindEndAddress(memclrBegin)
- swapUint32Begin = reflect.ValueOf(swapUint32).Pointer()
+ swapUint32Begin = addrOfSwapUint32()
swapUint32End = FindEndAddress(swapUint32Begin)
- swapUint64Begin = reflect.ValueOf(swapUint64).Pointer()
+ swapUint64Begin = addrOfSwapUint64()
swapUint64End = FindEndAddress(swapUint64Begin)
- compareAndSwapUint32Begin = reflect.ValueOf(compareAndSwapUint32).Pointer()
+ compareAndSwapUint32Begin = addrOfCompareAndSwapUint32()
compareAndSwapUint32End = FindEndAddress(compareAndSwapUint32Begin)
- loadUint32Begin = reflect.ValueOf(loadUint32).Pointer()
+ loadUint32Begin = addrOfLoadUint32()
loadUint32End = FindEndAddress(loadUint32Begin)
}
func init() {
initializeAddresses()
- if err := ReplaceSignalHandler(unix.SIGSEGV, reflect.ValueOf(signalHandler).Pointer(), &savedSigSegVHandler); err != nil {
+ if err := ReplaceSignalHandler(unix.SIGSEGV, addrOfSignalHandler(), &savedSigSegVHandler); err != nil {
panic(fmt.Sprintf("Unable to set handler for SIGSEGV: %v", err))
}
- if err := ReplaceSignalHandler(unix.SIGBUS, reflect.ValueOf(signalHandler).Pointer(), &savedSigBusHandler); err != nil {
+ if err := ReplaceSignalHandler(unix.SIGBUS, addrOfSignalHandler(), &savedSigBusHandler); err != nil {
panic(fmt.Sprintf("Unable to set handler for SIGBUS: %v", err))
}
syserror.AddErrorUnwrapper(func(e error) (unix.Errno, bool) {
diff --git a/pkg/safecopy/safecopy_unsafe.go b/pkg/safecopy/safecopy_unsafe.go
index a075cf88e..efbc2ddc1 100644
--- a/pkg/safecopy/safecopy_unsafe.go
+++ b/pkg/safecopy/safecopy_unsafe.go
@@ -89,6 +89,18 @@ func compareAndSwapUint32(ptr unsafe.Pointer, old, new uint32) (prev uint32, sig
//go:noescape
func loadUint32(ptr unsafe.Pointer) (val uint32, sig int32)
+// Return the start address of the functions above.
+//
+// In Go 1.17+, Go references to assembly functions resolve to an ABIInternal
+// wrapper function rather than the function itself. We must reference from
+// assembly to get the ABI0 (i.e., primary) address.
+func addrOfMemcpy() uintptr
+func addrOfMemclr() uintptr
+func addrOfSwapUint32() uintptr
+func addrOfSwapUint64() uintptr
+func addrOfCompareAndSwapUint32() uintptr
+func addrOfLoadUint32() uintptr
+
// CopyIn copies len(dst) bytes from src to dst. It returns the number of bytes
// copied and an error if SIGSEGV or SIGBUS is received while reading from src.
func CopyIn(dst []byte, src unsafe.Pointer) (int, error) {
diff --git a/pkg/safecopy/sighandler_amd64.s b/pkg/safecopy/sighandler_amd64.s
index 475ae48e9..0b5e8df66 100644
--- a/pkg/safecopy/sighandler_amd64.s
+++ b/pkg/safecopy/sighandler_amd64.s
@@ -131,3 +131,9 @@ handle_fault:
MOVL DI, REG_RDI(DX)
RET
+
+// func addrOfSignalHandler() uintptr
+TEXT ·addrOfSignalHandler(SB), $0-8
+ MOVQ $·signalHandler(SB), AX
+ MOVQ AX, ret+0(FP)
+ RET
diff --git a/pkg/safecopy/sighandler_arm64.s b/pkg/safecopy/sighandler_arm64.s
index 53e4ac2c1..41ed70ff9 100644
--- a/pkg/safecopy/sighandler_arm64.s
+++ b/pkg/safecopy/sighandler_arm64.s
@@ -141,3 +141,9 @@ handle_fault:
MOVW R0, REG_R1(R2)
RET
+
+// func addrOfSignalHandler() uintptr
+TEXT ·addrOfSignalHandler(SB), $0-8
+ MOVD $·signalHandler(SB), R0
+ MOVD R0, ret+0(FP)
+ RET