Skip to content

Commit

Permalink
runtime: avoid cgo_unsafe_args for syscall.syscall functions on darwi…
Browse files Browse the repository at this point in the history
…n/arm64

Currently, syscall.syscall-like functions are defined as
cgo_unsafe_args, which makes them ABI0, as it takes the address of
the argument area based on ABI0 layout. Those functions are
linkname'd to the syscall package. When compiling the syscall
package, the compiler doesn't know they are ABI0 therefore
generate an ABIInternal call, which will use the wrapper. As some
of the functions (e.g. syscall6) has many arguments, the wrapper
would take a good amount of stack space. And those functions must
be nosplit. This causes nosplit overflow when building with -N -l
and -race.

Avoid that by rewriting the functions to not use cgo_unsafe_args.
Instead, make a struct locally and pass the address of that
struct. This way the functions are ABIInternal and the call will
not use the wrapper.

Fixes #51247.

Change-Id: I76c1ab86b9d28664fa7d5b9c7928fbb2fd8d1417
Reviewed-on: https://go-review.googlesource.com/c/go/+/386719
Trust: Cherry Mui <[email protected]>
Run-TryBot: Cherry Mui <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Michael Knyszek <[email protected]>
  • Loading branch information
cherrymui committed Feb 28, 2022
1 parent 06a43e4 commit 57e3809
Showing 1 changed file with 28 additions and 24 deletions.
52 changes: 28 additions & 24 deletions src/runtime/sys_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,85 +17,89 @@ import (

//go:linkname syscall_syscall syscall.syscall
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscall()

//go:linkname syscall_syscallX syscall.syscallX
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscallX()

//go:linkname syscall_syscall6 syscall.syscall6
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscall6()

//go:linkname syscall_syscall6X syscall.syscall6X
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscall6X()

//go:linkname syscall_syscallPtr syscall.syscallPtr
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1, args.r2, args.err
}
func syscallPtr()

//go:linkname syscall_rawSyscall syscall.rawSyscall
//go:nosplit
//go:cgo_unsafe_args
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn))
return
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
return args.r1, args.r2, args.err
}

//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:nosplit
//go:cgo_unsafe_args
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn))
return
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
return args.r1, args.r2, args.err
}

// syscallNoErr is used in crypto/x509 to call into Security.framework and CF.

//go:linkname crypto_x509_syscall crypto/x509/internal/macos.syscall
//go:nosplit
//go:cgo_unsafe_args
func crypto_x509_syscall(fn, a1, a2, a3, a4, a5 uintptr, f1 float64) (r1 uintptr) {
args := struct {
fn, a1, a2, a3, a4, a5 uintptr
f1 float64
r1 uintptr
}{fn, a1, a2, a3, a4, a5, f1, r1}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_x509)), unsafe.Pointer(&fn))
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_x509)), unsafe.Pointer(&args))
exitsyscall()
return
return args.r1
}
func syscall_x509()

Expand Down

0 comments on commit 57e3809

Please sign in to comment.