1
0
mirror of https://github.com/golang/go synced 2024-09-29 13:34:30 -06:00

runtime: mark all Go symbols called from assembly in other packages

This marks all Go symbols called from assembly in other packages with
"go:linkname" directives to ensure they get ABI wrappers.

Now that we have this go:linkname convention, this also removes the
abi0Syms definition in the runtime, which was used to give morestackc
an ABI0 wrapper. Instead, we now just mark morestackc with a
go:linkname directive.

This was tested with buildall.bash in the default configuration, with
-race, and with -gcflags=all=-d=ssa/intrinsics/off. Since I couldn't
test cgo on non-Linux configurations, I manually grepped for runtime
symbols in runtime/cgo.

Updates #31230.

Change-Id: I6c8aa56be2ca6802dfa2bf159e49c411b9071bf1
Reviewed-on: https://go-review.googlesource.com/c/go/+/179862
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Austin Clements 2019-05-31 16:38:56 -04:00
parent dde7c770ef
commit f5e5bc1a42
13 changed files with 106 additions and 8 deletions

View File

@ -38,11 +38,3 @@ GLOBL runtime·memstats(SB), NOPTR, $0
// This function must be sizeofSkipFunction bytes.
TEXT runtime·skipPleaseUseCallersFrames(SB),NOSPLIT,$0-0
SKIP64; SKIP64; SKIP64; SKIP64
// abi0Syms is a dummy symbol that creates ABI0 wrappers for Go
// functions called from assembly in other packages.
TEXT abi0Syms<>(SB),NOSPLIT,$0-0
// obj assumes it can call morestack* using ABI0, but
// morestackc is actually defined in Go.
CALL ·morestackc(SB)
// References from syscall are automatically collected by cmd/go.

View File

@ -8,6 +8,10 @@ package atomic
import "unsafe"
// Export some functions via linkname to assembly in sync/atomic.
//go:linkname Load
//go:linkname Loadp
//go:nosplit
//go:noinline
func Load(ptr *uint32) uint32 {

View File

@ -8,6 +8,11 @@ package atomic
import "unsafe"
// Export some functions via linkname to assembly in sync/atomic.
//go:linkname Load
//go:linkname Loadp
//go:linkname Load64
//go:nosplit
//go:noinline
func Load(ptr *uint32) uint32 {

View File

@ -4,6 +4,13 @@
// +build mips mipsle
// Export some functions via linkname to assembly in sync/atomic.
//go:linkname Xadd64
//go:linkname Xchg64
//go:linkname Cas64
//go:linkname Load64
//go:linkname Store64
package atomic
import (

View File

@ -6,6 +6,13 @@ package atomic
import "unsafe"
// Export some functions via linkname to assembly in sync/atomic.
//go:linkname Load
//go:linkname Loadp
//go:linkname Load64
//go:linkname Store
//go:linkname Store64
//go:nosplit
//go:noinline
func Load(ptr *uint32) uint32 {

View File

@ -5,6 +5,24 @@
// TODO(neelance): implement with actual atomic operations as soon as threads are available
// See https://github.com/WebAssembly/design/issues/1073
// Export some functions via linkname to assembly in sync/atomic.
//go:linkname Load
//go:linkname Loadp
//go:linkname Load64
//go:linkname Loaduintptr
//go:linkname Xadd
//go:linkname Xadd64
//go:linkname Xadduintptr
//go:linkname Xchg
//go:linkname Xchg64
//go:linkname Xchguintptr
//go:linkname Cas
//go:linkname Cas64
//go:linkname Casuintptr
//go:linkname Store
//go:linkname Store64
//go:linkname Storeuintptr
package atomic
import "unsafe"

View File

@ -2850,7 +2850,11 @@ func reentersyscall(pc, sp uintptr) {
}
// Standard syscall entry used by the go syscall library and normal cgo calls.
//
// This is exported via linkname to assembly in the syscall package.
//
//go:nosplit
//go:linkname entersyscall
func entersyscall() {
reentersyscall(getcallerpc(), getcallersp())
}
@ -2940,8 +2944,11 @@ func entersyscallblock_handoff() {
//
// Write barriers are not allowed because our P may have been stolen.
//
// This is exported via linkname to assembly in the syscall package.
//
//go:nosplit
//go:nowritebarrierrec
//go:linkname exitsyscall
func exitsyscall() {
_g_ := getg()

View File

@ -369,6 +369,9 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
//
// The signal handler must not inject a call to sigpanic if
// getg().throwsplit, since sigpanic may need to grow the stack.
//
// This is exported via linkname to assembly in runtime/cgo.
//go:linkname sigpanic
func sigpanic() {
g := getg()
if !canpanic(g) {
@ -843,7 +846,11 @@ func signalstack(s *stack) {
}
// setsigsegv is used on darwin/arm{,64} to fake a segmentation fault.
//
// This is exported via linkname to assembly in runtime/cgo.
//
//go:nosplit
//go:linkname setsigsegv
func setsigsegv(pc uintptr) {
g := getg()
g.sig = _SIGSEGV

View File

@ -1295,7 +1295,10 @@ type stackObjectRecord struct {
typ *_type
}
// This is exported as ABI0 via linkname so obj can call it.
//
//go:nosplit
//go:linkname morestackc
func morestackc() {
throw("attempt to execute system stack code on user stack")
}

View File

@ -310,6 +310,8 @@ func gobytes(p *byte, n int) (b []byte) {
return
}
// This is exported via linkname to assembly in syscall (for Plan9).
//go:linkname gostring
func gostring(p *byte) string {
l := findnull(p)
if l == 0 {

View File

@ -206,6 +206,9 @@ func close_trampoline()
//go:nosplit
//go:cgo_unsafe_args
//
// This is exported via linkname to assembly in runtime/cgo.
//go:linkname exit
func exit(code int32) {
libcCall(unsafe.Pointer(funcPC(exit_trampoline)), unsafe.Pointer(&code))
}

View File

@ -57,19 +57,30 @@ var (
// Syscall is needed because some packages (like net) need it too.
// The best way is to return EINVAL and let Golang handles its failure
// If the syscall can't fail, this function can redirect it to a real syscall.
//
// This is exported via linkname to assembly in the syscall package.
//
//go:nosplit
//go:linkname syscall_Syscall
func syscall_Syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
return 0, 0, _EINVAL
}
// This is syscall.RawSyscall, it exists to satisfy some build dependency,
// but it doesn't work.
//
// This is exported via linkname to assembly in the syscall package.
//
//go:linkname syscall_RawSyscall
func syscall_RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
panic("RawSyscall not available on AIX")
}
// This is exported via linkname to assembly in the syscall package.
//
//go:nosplit
//go:cgo_unsafe_args
//go:linkname syscall_syscall6
func syscall_syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
c := libcall{
fn: fn,
@ -83,8 +94,11 @@ func syscall_syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err ui
return c.r1, 0, c.err
}
// This is exported via linkname to assembly in the syscall package.
//
//go:nosplit
//go:cgo_unsafe_args
//go:linkname syscall_rawSyscall6
func syscall_rawSyscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
c := libcall{
fn: fn,

View File

@ -31,7 +31,11 @@ var pipe1x libcFunc // name to take addr of pipe1
func pipe1() // declared for vet; do NOT call
// Many of these are exported via linkname to assembly in the syscall
// package.
//go:nosplit
//go:linkname syscall_sysvicall6
func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
call := libcall{
fn: fn,
@ -45,6 +49,7 @@ func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err
}
//go:nosplit
//go:linkname syscall_rawsysvicall6
func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
call := libcall{
fn: fn,
@ -60,6 +65,7 @@ func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, e
// with calls to sysvicallN.
//go:nosplit
//go:linkname syscall_chdir
func syscall_chdir(path uintptr) (err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_chdir)),
@ -71,6 +77,7 @@ func syscall_chdir(path uintptr) (err uintptr) {
}
//go:nosplit
//go:linkname syscall_chroot
func syscall_chroot(path uintptr) (err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_chroot)),
@ -83,6 +90,7 @@ func syscall_chroot(path uintptr) (err uintptr) {
// like close, but must not split stack, for forkx.
//go:nosplit
//go:linkname syscall_close
func syscall_close(fd int32) int32 {
return int32(sysvicall1(&libc_close, uintptr(fd)))
}
@ -90,11 +98,13 @@ func syscall_close(fd int32) int32 {
const _F_DUP2FD = 0x9
//go:nosplit
//go:linkname syscall_dup2
func syscall_dup2(oldfd, newfd uintptr) (val, err uintptr) {
return syscall_fcntl(oldfd, _F_DUP2FD, newfd)
}
//go:nosplit
//go:linkname syscall_execve
func syscall_execve(path, argv, envp uintptr) (err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_execve)),
@ -107,11 +117,13 @@ func syscall_execve(path, argv, envp uintptr) (err uintptr) {
// like exit, but must not split stack, for forkx.
//go:nosplit
//go:linkname syscall_exit
func syscall_exit(code uintptr) {
sysvicall1(&libc_exit, code)
}
//go:nosplit
//go:linkname syscall_fcntl
func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_fcntl)),
@ -123,6 +135,7 @@ func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
}
//go:nosplit
//go:linkname syscall_forkx
func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_forkx)),
@ -133,6 +146,7 @@ func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
return call.r1, call.err
}
//go:linkname syscall_gethostname
func syscall_gethostname() (name string, err uintptr) {
cname := new([_MAXHOSTNAMELEN]byte)
var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN}
@ -152,6 +166,7 @@ func syscall_gethostname() (name string, err uintptr) {
}
//go:nosplit
//go:linkname syscall_getpid
func syscall_getpid() (pid, err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_getpid)),
@ -163,6 +178,7 @@ func syscall_getpid() (pid, err uintptr) {
}
//go:nosplit
//go:linkname syscall_ioctl
func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_ioctl)),
@ -173,6 +189,7 @@ func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
return call.err
}
//go:linkname syscall_pipe
func syscall_pipe() (r, w, err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&pipe1x)),
@ -187,17 +204,22 @@ func syscall_pipe() (r, w, err uintptr) {
// This is syscall.RawSyscall, it exists to satisfy some build dependency,
// but it doesn't work.
//
//go:linkname syscall_rawsyscall
func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
panic("RawSyscall not available on Solaris")
}
// This is syscall.RawSyscall6, it exists to avoid a linker error because
// syscall.RawSyscall6 is already declared. See golang.org/issue/24357
//
//go:linkname syscall_rawsyscall6
func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
panic("RawSyscall6 not available on Solaris")
}
//go:nosplit
//go:linkname syscall_setgid
func syscall_setgid(gid uintptr) (err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setgid)),
@ -209,6 +231,7 @@ func syscall_setgid(gid uintptr) (err uintptr) {
}
//go:nosplit
//go:linkname syscall_setgroups
func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setgroups)),
@ -220,6 +243,7 @@ func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
}
//go:nosplit
//go:linkname syscall_setsid
func syscall_setsid() (pid, err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setsid)),
@ -231,6 +255,7 @@ func syscall_setsid() (pid, err uintptr) {
}
//go:nosplit
//go:linkname syscall_setuid
func syscall_setuid(uid uintptr) (err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setuid)),
@ -242,6 +267,7 @@ func syscall_setuid(uid uintptr) (err uintptr) {
}
//go:nosplit
//go:linkname syscall_setpgid
func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setpgid)),
@ -252,6 +278,7 @@ func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
return call.err
}
//go:linkname syscall_syscall
func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_syscall)),
@ -264,6 +291,7 @@ func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
return call.r1, call.r2, call.err
}
//go:linkname syscall_wait4
func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_wait4)),
@ -277,6 +305,7 @@ func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.
}
//go:nosplit
//go:linkname syscall_write
func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) {
call := libcall{
fn: uintptr(unsafe.Pointer(&libc_write)),