]> Cypherpunks.ru repositories - gostls13.git/commitdiff
runtime: mark all Go symbols called from assembly in other packages
authorAustin Clements <austin@google.com>
Fri, 31 May 2019 20:38:56 +0000 (16:38 -0400)
committerAustin Clements <austin@google.com>
Thu, 6 Jun 2019 19:44:12 +0000 (19:44 +0000)
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>
13 files changed:
src/runtime/asm.s
src/runtime/internal/atomic/atomic_386.go
src/runtime/internal/atomic/atomic_amd64x.go
src/runtime/internal/atomic/atomic_mipsx.go
src/runtime/internal/atomic/atomic_s390x.go
src/runtime/internal/atomic/atomic_wasm.go
src/runtime/proc.go
src/runtime/signal_unix.go
src/runtime/stack.go
src/runtime/string.go
src/runtime/sys_darwin.go
src/runtime/syscall_aix.go
src/runtime/syscall_solaris.go

index 314f99d69be4feb7d6d7f2d8b843e704978da0d7..6b209b2d1f463a52e4289325fbf88e7770164472 100644 (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.
index 143cd45e6125e628c414252e730f40bc6e3a0aea..d7f82cc752971cbf4f04ffda8e937c32af60b9a4 100644 (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 {
index b7e01a3ad5dbac878a236a59790503f853167cca..31c1636b2ef9178aa2e3ad3d6e38b6c5835d8e06 100644 (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 {
index 210fc27d9b74005bacbf5990593229c2aba2689c..6e39262c15027220cfea8dca358903b5b381ff43 100644 (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 (
index 5a1f411ca10a8479272837f2de8cdf9ff6b271cb..f6758082a9137f19fa6e7e84eee0115d8f0948f3 100644 (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 {
index 9ce4892cb6e47c5df511f59545dd8899e16cea46..0731763ac16aaec453d9f1dcfb0166e8775d9a9e 100644 (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"
index e9eca23138845cad4043a313a88e1c03a0c0d92b..b5cf9d442d62b337048e24b64d5ee18a0217da83 100644 (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()
 
index f34008ff5ffdf6645a26f004f3fac6bc305430a6..ad51dc1800fef0746f705994a64dd4082ad61d9b 100644 (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
index d5d09ba7d7bef9757b530d3bdba2b1053f015cfa..22a0053fdbe336dfeb21bc3ee99a9434837059f9 100644 (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")
 }
index 839e882cdcd19f27c891452b7441e76a1041d92e..d198f73756b787a274015da79b8514e5cbabc819 100644 (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 {
index 0bf17c47af2a02054db40c320fb7e548ea75b022..b50d441d92a7af1131e6bcba653410b54756e717 100644 (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))
 }
index 1ed1dfa0bb9651700319e147866f5cfb7b18e868..79b51240e906c3c1a5897db6614b3d5dc04833df 100644 (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,
index b1592c511a58e28578a6ade184d78be381072149..35381801c55b808e6aa512bdecf6291106625fbd 100644 (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)),