Skip to content

Commit

Permalink
all: document legacy //go:linkname for modules with ≥100,000 dependents
Browse files Browse the repository at this point in the history
For #67401.

Change-Id: I51f5b561ee11eb242e3b1585d591281d0df4fc24
Reviewed-on: https://go-review.googlesource.com/c/go/+/587215
Auto-Submit: Russ Cox <[email protected]>
Reviewed-by: Cherry Mui <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
rsc authored and gopherbot committed May 22, 2024
1 parent dca577d commit ef225d1
Show file tree
Hide file tree
Showing 15 changed files with 166 additions and 10 deletions.
1 change: 0 additions & 1 deletion src/reflect/badlinkname.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (

//go:linkname add
//go:linkname ifaceIndir
//go:linkname mapassign
//go:linkname rtypeOff
//go:linkname toType
//go:linkname typesByString
Expand Down
9 changes: 9 additions & 0 deletions src/reflect/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -3870,6 +3870,15 @@ func mapaccess_faststr(t *abi.Type, m unsafe.Pointer, key string) (val unsafe.Po
//go:noescape
func mapassign0(t *abi.Type, m unsafe.Pointer, key, val unsafe.Pointer)

// mapassign should be an internal detail,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname mapassign
func mapassign(t *abi.Type, m unsafe.Pointer, key, val unsafe.Pointer) {
contentEscapes(key)
contentEscapes(val)
Expand Down
7 changes: 7 additions & 0 deletions src/runtime/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,13 @@ func buildInterfaceSwitchCache(oldC *abi.InterfaceSwitchCache, typ *_type, case_
// causes a cache lookup to fail immediately.)
var emptyInterfaceSwitchCache = abi.InterfaceSwitchCache{Mask: 0}

// reflect_ifaceE2I is for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
//
//go:linkname reflect_ifaceE2I reflect.ifaceE2I
func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
*dst = iface{assertE2I(inter, e._type), e.data}
Expand Down
3 changes: 0 additions & 3 deletions src/runtime/linkname.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ import _ "unsafe"
// used in runtime/coverage and in tests
//go:linkname addExitHook

// used in x/sys/cpu
//go:linkname getAuxv

// used in tests
//go:linkname extraMInUse
//go:linkname getm
Expand Down
16 changes: 16 additions & 0 deletions src/runtime/malloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,14 @@ func newobject(typ *_type) unsafe.Pointer {
return mallocgc(typ.Size_, typ, true)
}

// reflect_unsafe_New is meant for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_unsafe_New reflect.unsafe_New
func reflect_unsafe_New(typ *_type) unsafe.Pointer {
return mallocgc(typ.Size_, typ, true)
Expand All @@ -1393,6 +1401,14 @@ func newarray(typ *_type, n int) unsafe.Pointer {
return mallocgc(mem, typ, true)
}

// reflect_unsafe_NewArray is meant for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_unsafe_NewArray reflect.unsafe_NewArray
func reflect_unsafe_NewArray(typ *_type, n int) unsafe.Pointer {
return newarray(typ, n)
Expand Down
32 changes: 32 additions & 0 deletions src/runtime/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,14 @@ func advanceEvacuationMark(h *hmap, t *maptype, newbit uintptr) {

// Reflect stubs. Called from ../reflect/asm_*.s

// reflect_makemap is for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_makemap reflect.makemap
func reflect_makemap(t *maptype, cap int) *hmap {
// Check invariants and reflects math.
Expand Down Expand Up @@ -1332,6 +1340,14 @@ func reflect_makemap(t *maptype, cap int) *hmap {
return makemap(t, cap, nil)
}

// reflect_mapaccess is for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_mapaccess reflect.mapaccess
func reflect_mapaccess(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
elem, ok := mapaccess2(t, h, key)
Expand Down Expand Up @@ -1374,11 +1390,27 @@ func reflect_mapdelete_faststr(t *maptype, h *hmap, key string) {
mapdelete_faststr(t, h, key)
}

// reflect_mapiterinit is for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_mapiterinit reflect.mapiterinit
func reflect_mapiterinit(t *maptype, h *hmap, it *hiter) {
mapiterinit(t, h, it)
}

// reflect_mapiternext is for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_mapiternext reflect.mapiternext
func reflect_mapiternext(it *hiter) {
mapiternext(it)
Expand Down
16 changes: 16 additions & 0 deletions src/runtime/mbarrier.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,14 @@ func wbMove(typ *_type, dst, src unsafe.Pointer) {
bulkBarrierPreWrite(uintptr(dst), uintptr(src), typ.PtrBytes, typ)
}

// reflect_typedmemmove is meant for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_typedmemmove reflect.typedmemmove
func reflect_typedmemmove(typ *_type, dst, src unsafe.Pointer) {
if raceenabled {
Expand Down Expand Up @@ -303,6 +311,14 @@ func typedslicecopy(typ *_type, dstPtr unsafe.Pointer, dstLen int, srcPtr unsafe
return n
}

// reflect_typedslicecopy is meant for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_typedslicecopy reflect.typedslicecopy
func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
if !elemType.Pointers() {
Expand Down
7 changes: 6 additions & 1 deletion src/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,9 @@ func setCrashFD(fd uintptr) uintptr {
// It contains an even number of elements, (tag, value) pairs.
var auxv []uintptr

func getAuxv() []uintptr { return auxv } // accessed from x/sys/cpu; see issue 57336
// golang.org/x/sys/cpu uses getAuxv via linkname.
// Do not remove or change the type signature.
// (See go.dev/issue/57336.)
//
//go:linkname getAuxv
func getAuxv() []uintptr { return auxv }
16 changes: 16 additions & 0 deletions src/runtime/runtime1.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,14 @@ func releasem(mp *m) {
}
}

// reflect_typelinks is meant for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_typelinks reflect.typelinks
func reflect_typelinks() ([]unsafe.Pointer, [][]int32) {
modules := activeModules()
Expand All @@ -635,6 +643,14 @@ func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointe

// reflect_resolveTypeOff resolves an *rtype offset from a base type.
//
// reflect_resolveTypeOff is meant for package reflect,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname reflect_resolveTypeOff reflect.resolveTypeOff
func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
Expand Down
24 changes: 24 additions & 0 deletions src/runtime/sys_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import (
// and we need to know whether to check 32 or 64 bits of the result.
// (Some libc functions that return 32 bits put junk in the upper 32 bits of AX.)

// golang.org/x/sys linknames syscall_syscall
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_syscall syscall.syscall
//go:nosplit
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
Expand All @@ -38,6 +42,10 @@ func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
}
func syscallX()

// golang.org/x/sys linknames syscall.syscall6
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_syscall6 syscall.syscall6
//go:nosplit
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
Expand All @@ -49,6 +57,10 @@ func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
}
func syscall6()

// golang.org/x/sys linknames syscall.syscall9
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_syscall9 syscall.syscall9
//go:nosplit
//go:cgo_unsafe_args
Expand All @@ -71,6 +83,10 @@ func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
}
func syscall6X()

// golang.org/x/sys linknames syscall.syscallPtr
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_syscallPtr syscall.syscallPtr
//go:nosplit
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
Expand All @@ -82,6 +98,10 @@ func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
}
func syscallPtr()

// golang.org/x/sys linknames syscall_rawSyscall
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_rawSyscall syscall.rawSyscall
//go:nosplit
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
Expand All @@ -90,6 +110,10 @@ func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
return args.r1, args.r2, args.err
}

// golang.org/x/sys linknames syscall_rawSyscall6
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:nosplit
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
Expand Down
20 changes: 20 additions & 0 deletions src/runtime/sys_openbsd3.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import (
// and we need to know whether to check 32 or 64 bits of the result.
// (Some libc functions that return 32 bits put junk in the upper 32 bits of AX.)

// golang.org/x/sys linknames syscall_syscall
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_syscall syscall.syscall
//go:nosplit
//go:cgo_unsafe_args
Expand All @@ -39,6 +43,10 @@ func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
}
func syscallX()

// golang.org/x/sys linknames syscall.syscall6
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_syscall6 syscall.syscall6
//go:nosplit
//go:cgo_unsafe_args
Expand All @@ -61,6 +69,10 @@ func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
}
func syscall6X()

// golang.org/x/sys linknames syscall.syscall10
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_syscall10 syscall.syscall10
//go:nosplit
//go:cgo_unsafe_args
Expand All @@ -83,6 +95,10 @@ func syscall_syscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1
}
func syscall10X()

// golang.org/x/sys linknames syscall_rawSyscall
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_rawSyscall syscall.rawSyscall
//go:nosplit
//go:cgo_unsafe_args
Expand All @@ -91,6 +107,10 @@ func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
return
}

// golang.org/x/sys linknames syscall_rawSyscall6
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:nosplit
//go:cgo_unsafe_args
Expand Down
8 changes: 8 additions & 0 deletions src/runtime/syscall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,10 @@ func syscall_loadsystemlibrary(filename *uint16) (handle, err uintptr) {
return
}

// golang.org/x/sys linknames syscall.loadlibrary
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_loadlibrary syscall.loadlibrary
func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
handle, _, err = syscall_SyscallN(uintptr(unsafe.Pointer(_LoadLibraryW)), uintptr(unsafe.Pointer(filename)))
Expand All @@ -433,6 +437,10 @@ func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
return
}

// golang.org/x/sys linknames syscall.getprocaddress
// (in addition to standard package syscall).
// Do not remove or change the type signature.
//
//go:linkname syscall_getprocaddress syscall.getprocaddress
func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
outhandle, _, err = syscall_SyscallN(uintptr(unsafe.Pointer(_GetProcAddress)), handle, uintptr(unsafe.Pointer(procname)))
Expand Down
4 changes: 4 additions & 0 deletions src/syscall/badlinkname_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ import _ "unsafe"
// This may change in the future. Please do not depend on them
// in new code.

// golang.org/x/sys linknames getsockopt.
// Do not remove or change the type signature.
//
//go:linkname getsockopt

//go:linkname setsockopt
4 changes: 3 additions & 1 deletion src/syscall/linkname_bsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ import _ "unsafe"
// used by internal/syscall/unix
//go:linkname ioctlPtr

// used by x/net/route
// golang.org/x/net linknames sysctl.
// Do not remove or change the type signature.
//
//go:linkname sysctl
9 changes: 5 additions & 4 deletions src/syscall/syscall_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -1284,12 +1284,13 @@ func Munmap(b []byte) (err error) {
//sys Mlockall(flags int) (err error)
//sys Munlockall() (err error)

// prlimit is accessed from x/sys/unix.
//go:linkname prlimit

// prlimit changes a resource limit. We use a single definition so that
// we can tell StartProcess to not restore the original NOFILE limit.
// This is unexported but can be called from x/sys/unix.
//
// golang.org/x/sys linknames prlimit.
// Do not remove or change the type signature.
//
//go:linkname prlimit
func prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) {
err = prlimit1(pid, resource, newlimit, old)
if err == nil && newlimit != nil && resource == RLIMIT_NOFILE && (pid == 0 || pid == Getpid()) {
Expand Down

0 comments on commit ef225d1

Please sign in to comment.