aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2024-05-21 23:02:51 -0400
committerGopher Robot <gobot@golang.org>2024-05-22 21:17:41 +0000
commit5fee159bc2e60736ce967560ee5be738fe5d5bd2 (patch)
treee6ebbad97d446072a6d06b3c5f8a5748b7014b96 /src
parent4c589d93ad6f77e31cccc237c20133f0d8d8492f (diff)
downloadgo-5fee159bc2e60736ce967560ee5be738fe5d5bd2.tar.xz
all: document legacy //go:linkname for modules with ≥50,000 dependents
Note that this depends on the revert of CL 581395 to move zeroVal back. For #67401. Change-Id: I507c27c2404ad1348aabf1ffa3740e6b1957495b Reviewed-on: https://go-review.googlesource.com/c/go/+/587217 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Russ Cox <rsc@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/internal/cpu/badlinkname_linux_arm64.go15
-rw-r--r--src/internal/cpu/cpu_arm64_hwcap.go11
-rw-r--r--src/reflect/badlinkname.go25
-rw-r--r--src/reflect/type.go26
-rw-r--r--src/reflect/value.go1
-rw-r--r--src/runtime/badlinkname.go7
-rw-r--r--src/runtime/malloc.go22
-rw-r--r--src/runtime/map.go84
-rw-r--r--src/runtime/map_fast32.go27
-rw-r--r--src/runtime/map_fast64.go27
-rw-r--r--src/runtime/map_faststr.go18
-rw-r--r--src/runtime/mbarrier.go10
-rw-r--r--src/runtime/runtime.go8
-rw-r--r--src/runtime/runtime1.go1
-rw-r--r--src/runtime/slice.go10
-rw-r--r--src/runtime/stubs.go15
-rw-r--r--src/runtime/trace.go4
-rw-r--r--src/runtime/tracetime.go8
18 files changed, 277 insertions, 42 deletions
diff --git a/src/internal/cpu/badlinkname_linux_arm64.go b/src/internal/cpu/badlinkname_linux_arm64.go
deleted file mode 100644
index 9e2cfcef06..0000000000
--- a/src/internal/cpu/badlinkname_linux_arm64.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package cpu
-
-import _ "unsafe"
-
-// As of Go 1.22, the symbols below are found to be pulled via
-// linkname in the wild. We provide a push linkname here, to
-// keep them accessible with pull linknames.
-// This may change in the future. Please do not depend on them
-// in new code.
-
-//go:linkname HWCap
diff --git a/src/internal/cpu/cpu_arm64_hwcap.go b/src/internal/cpu/cpu_arm64_hwcap.go
index 7f0504ca16..34edf3eeb2 100644
--- a/src/internal/cpu/cpu_arm64_hwcap.go
+++ b/src/internal/cpu/cpu_arm64_hwcap.go
@@ -6,8 +6,19 @@
package cpu
+import _ "unsafe" // for linkname
+
// HWCap may be initialized by archauxv and
// should not be changed after it was initialized.
+//
+// Other widely used packages
+// access HWCap using linkname as well, most notably:
+// - github.com/klauspost/cpuid/v2
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname HWCap
var HWCap uint
// HWCAP bits. These are exposed by Linux.
diff --git a/src/reflect/badlinkname.go b/src/reflect/badlinkname.go
index e8fb4ff8c6..e05208ead7 100644
--- a/src/reflect/badlinkname.go
+++ b/src/reflect/badlinkname.go
@@ -9,17 +9,26 @@ import (
_ "unsafe"
)
-// As of Go 1.22, the symbols below are found to be pulled via
-// linkname in the wild. We provide a push linkname here, to
-// keep them accessible with pull linknames.
-// This may change in the future. Please do not depend on them
-// in new code.
+// Widely used packages access these symbols using linkname,
+// most notably:
+// - github.com/goccy/go-json
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401
+// and go.dev/issue/67279.
//go:linkname add
-//go:linkname ifaceIndir
-//go:linkname rtypeOff
-//go:linkname toType
//go:linkname typesByString
+
+// ifaceIndir reports whether t is stored indirectly in an interface value.
+// It is no longer used by this package and is here entirely for the
+// linkname uses.
+//
+//go:linkname unusedIfaceIndir reflect.ifaceIndir
+func unusedIfaceIndir(t *abi.Type) bool {
+ return t.Kind_&abi.KindDirectIface == 0
+}
+
//go:linkname valueInterface
// The compiler doesn't allow linknames on methods, for good reasons.
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 6ad2ace266..7789aa2f91 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -1632,6 +1632,15 @@ func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
// pointers, channels, maps, slices, and arrays.
func typelinks() (sections []unsafe.Pointer, offset [][]int32)
+// rtypeOff should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/goccy/go-json
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname rtypeOff
func rtypeOff(section unsafe.Pointer, off int32) *abi.Type {
return (*abi.Type)(add(section, uintptr(off), "sizeof(rtype) > 0"))
}
@@ -2887,6 +2896,16 @@ func appendVarint(x []byte, v uintptr) []byte {
// a nil *rtype must be replaced by a nil Type, but in gccgo this
// function takes care of ensuring that multiple *rtype for the same
// type are coalesced into a single Type.
+//
+// toType should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/goccy/go-json
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname toType
func toType(t *abi.Type) Type {
if t == nil {
return nil
@@ -3031,10 +3050,3 @@ func TypeFor[T any]() Type {
}
return TypeOf((*T)(nil)).Elem() // only for an interface kind
}
-
-// ifaceIndir reports whether t is stored indirectly in an interface value.
-// This function is no longer called by the reflect package,
-// and https://go.dev/issue/67279 tracks its deletion.
-func ifaceIndir(t *abi.Type) bool {
- return t.Kind_&abi.KindDirectIface == 0
-}
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 56d8ba708c..0854371ed4 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -3877,6 +3877,7 @@ func mapassign0(t *abi.Type, m unsafe.Pointer, key, val unsafe.Pointer)
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
+// - github.com/goccy/go-json
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
diff --git a/src/runtime/badlinkname.go b/src/runtime/badlinkname.go
index 291f64eb2e..9e34086517 100644
--- a/src/runtime/badlinkname.go
+++ b/src/runtime/badlinkname.go
@@ -23,11 +23,6 @@ import _ "unsafe"
//go:linkname gopark
//go:linkname goready
//go:linkname goyield
-//go:linkname mapassign
-//go:linkname mapassign_faststr
-//go:linkname mapiterinit
-//go:linkname mapiternext
-//go:linkname newarray
//go:linkname nilinterhash
//go:linkname noescape
//go:linkname procPin
@@ -36,8 +31,6 @@ import _ "unsafe"
//go:linkname startTheWorld
//go:linkname stopTheWorld
//go:linkname stringHash
-//go:linkname traceAdvance
-//go:linkname traceClockNow
//go:linkname typedmemmove
//go:linkname typedslicecopy
//go:linkname typehash
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index 4034060424..0e43b7acf4 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -965,6 +965,16 @@ func (c *mcache) nextFree(spc spanClass) (v gclinkptr, s *mspan, shouldhelpgc bo
// Allocate an object of size bytes.
// Small objects are allocated from the per-P cache's free lists.
// Large objects (> 32 kB) are allocated straight from the heap.
+//
+// mallocgc should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mallocgc
func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
if gcphase == _GCmarktermination {
throw("mallocgc called with gcphase == _GCmarktermination")
@@ -1374,6 +1384,7 @@ func newobject(typ *_type) unsafe.Pointer {
// 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/goccy/json
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
@@ -1390,6 +1401,16 @@ func reflectlite_unsafe_New(typ *_type) unsafe.Pointer {
}
// newarray allocates an array of n elements of type typ.
+//
+// newarray should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname newarray
func newarray(typ *_type, n int) unsafe.Pointer {
if n == 1 {
return mallocgc(typ.Size_, typ, true)
@@ -1404,6 +1425,7 @@ func newarray(typ *_type, n int) unsafe.Pointer {
// 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/goccy/json
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
diff --git a/src/runtime/map.go b/src/runtime/map.go
index 7be27fd569..d284acf803 100644
--- a/src/runtime/map.go
+++ b/src/runtime/map.go
@@ -294,6 +294,16 @@ func makemap_small() *hmap {
// can be created on the stack, h and/or bucket may be non-nil.
// If h != nil, the map can be created directly in h.
// If h.buckets != nil, bucket pointed to can be used as the first bucket.
+//
+// makemap should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname makemap
func makemap(t *maptype, hint int, h *hmap) *hmap {
mem, overflow := math.MulUintptr(uintptr(hint), t.Bucket.Size_)
if overflow || mem > maxAlloc {
@@ -446,6 +456,15 @@ bucketloop:
return unsafe.Pointer(&zeroVal[0])
}
+// mapaccess2 should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapaccess2
func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool) {
if raceenabled && h != nil {
callerpc := getcallerpc()
@@ -568,6 +587,16 @@ func mapaccess2_fat(t *maptype, h *hmap, key, zero unsafe.Pointer) (unsafe.Point
}
// Like mapaccess, but allocates a slot for the key if it is not present in the map.
+//
+// mapassign should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapassign
func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
@@ -685,6 +714,15 @@ done:
return elem
}
+// mapdelete should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapdelete
func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
if raceenabled && h != nil {
callerpc := getcallerpc()
@@ -805,6 +843,17 @@ search:
// The hiter struct pointed to by 'it' is allocated on the stack
// by the compilers order pass or on the heap by reflect_mapiterinit.
// Both need to have zeroed hiter since the struct contains pointers.
+//
+// mapiterinit should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/goccy/go-json
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapiterinit
func mapiterinit(t *maptype, h *hmap, it *hiter) {
if raceenabled && h != nil {
callerpc := getcallerpc()
@@ -851,6 +900,15 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) {
mapiternext(it)
}
+// mapiternext should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapiternext
func mapiternext(it *hiter) {
h := it.h
if raceenabled {
@@ -1297,6 +1355,7 @@ func advanceEvacuationMark(h *hmap, t *maptype, newbit uintptr) {
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
+// - github.com/goccy/go-json
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
@@ -1407,6 +1466,7 @@ func reflect_mapiterinit(t *maptype, h *hmap, it *hiter) {
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/modern-go/reflect2
+// - github.com/goccy/go-json
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
@@ -1416,16 +1476,40 @@ func reflect_mapiternext(it *hiter) {
mapiternext(it)
}
+// reflect_mapiterkey is for package reflect,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/goccy/go-json
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
//go:linkname reflect_mapiterkey reflect.mapiterkey
func reflect_mapiterkey(it *hiter) unsafe.Pointer {
return it.key
}
+// reflect_mapiterelem is for package reflect,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/goccy/go-json
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
//go:linkname reflect_mapiterelem reflect.mapiterelem
func reflect_mapiterelem(it *hiter) unsafe.Pointer {
return it.elem
}
+// reflect_maplen is for package reflect,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/goccy/go-json
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
//go:linkname reflect_maplen reflect.maplen
func reflect_maplen(h *hmap) int {
if h == nil {
diff --git a/src/runtime/map_fast32.go b/src/runtime/map_fast32.go
index 7e52240e77..98aa42ff6b 100644
--- a/src/runtime/map_fast32.go
+++ b/src/runtime/map_fast32.go
@@ -50,6 +50,15 @@ func mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer {
return unsafe.Pointer(&zeroVal[0])
}
+// mapaccess2_fast32 should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapaccess2_fast32
func mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool) {
if raceenabled && h != nil {
callerpc := getcallerpc()
@@ -90,6 +99,15 @@ func mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool) {
return unsafe.Pointer(&zeroVal[0]), false
}
+// mapassign_fast32 should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapassign_fast32
func mapassign_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
@@ -180,6 +198,15 @@ done:
return elem
}
+// mapassign_fast32ptr should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapassign_fast32ptr
func mapassign_fast32ptr(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
diff --git a/src/runtime/map_fast64.go b/src/runtime/map_fast64.go
index 2c365183cb..ae3a8123c4 100644
--- a/src/runtime/map_fast64.go
+++ b/src/runtime/map_fast64.go
@@ -50,6 +50,15 @@ func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
return unsafe.Pointer(&zeroVal[0])
}
+// mapaccess2_fast64 should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapaccess2_fast64
func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) {
if raceenabled && h != nil {
callerpc := getcallerpc()
@@ -90,6 +99,15 @@ func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) {
return unsafe.Pointer(&zeroVal[0]), false
}
+// mapassign_fast64 should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapassign_fast64
func mapassign_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
@@ -180,6 +198,15 @@ done:
return elem
}
+// mapassign_fast64ptr should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapassign_fast64ptr
func mapassign_fast64ptr(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
diff --git a/src/runtime/map_faststr.go b/src/runtime/map_faststr.go
index d989190f71..bef5d7f95a 100644
--- a/src/runtime/map_faststr.go
+++ b/src/runtime/map_faststr.go
@@ -105,6 +105,15 @@ dohash:
return unsafe.Pointer(&zeroVal[0])
}
+// mapaccess2_faststr should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapaccess2_faststr
func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {
if raceenabled && h != nil {
callerpc := getcallerpc()
@@ -200,6 +209,15 @@ dohash:
return unsafe.Pointer(&zeroVal[0]), false
}
+// mapassign_faststr should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname mapassign_faststr
func mapassign_faststr(t *maptype, h *hmap, s string) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go
index 89c45cfd29..5876d86fbd 100644
--- a/src/runtime/mbarrier.go
+++ b/src/runtime/mbarrier.go
@@ -202,7 +202,9 @@ func wbMove(typ *_type, dst, src unsafe.Pointer) {
// 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/goccy/json
// - github.com/modern-go/reflect2
+// - github.com/ugorji/go/codec
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
@@ -348,6 +350,14 @@ func typedmemclr(typ *_type, ptr unsafe.Pointer) {
memclrNoHeapPointers(ptr, typ.Size_)
}
+// 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/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
//go:linkname reflect_typedmemclr reflect.typedmemclr
func reflect_typedmemclr(typ *_type, ptr unsafe.Pointer) {
typedmemclr(typ, ptr)
diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go
index 6cf903d2c1..9b3ca719ea 100644
--- a/src/runtime/runtime.go
+++ b/src/runtime/runtime.go
@@ -305,5 +305,13 @@ func getAuxv() []uintptr { return auxv }
// zeroVal is used by reflect via linkname.
//
+// zeroVal should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
//go:linkname zeroVal
var zeroVal [abi.ZeroValSize]byte
diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go
index 1a6f0366c4..7eeddfdf2c 100644
--- a/src/runtime/runtime1.go
+++ b/src/runtime/runtime1.go
@@ -617,6 +617,7 @@ 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/goccy/json
// - github.com/modern-go/reflect2
//
// Do not remove or change the type signature.
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
index 4fbe056b78..3439a0d751 100644
--- a/src/runtime/slice.go
+++ b/src/runtime/slice.go
@@ -152,6 +152,16 @@ func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
// new length so that the old length is not live (does not need to be
// spilled/restored) and the new length is returned (also does not need
// to be spilled/restored).
+//
+// growslice should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname growslice
func growslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, et *_type) slice {
oldLen := newLen - num
if raceenabled {
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
index 34984d86ff..8196eb0c90 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -103,12 +103,19 @@ func reflect_memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) {
//
// Implementations are in memmove_*.s.
//
-//go:noescape
-func memmove(to, from unsafe.Pointer, n uintptr)
-
-// Outside assembly calls memmove. Make sure it has ABI wrappers.
+// Outside assembly calls memmove.
+//
+// memmove should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/ugorji/go/codec
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
//
//go:linkname memmove
+//go:noescape
+func memmove(to, from unsafe.Pointer, n uintptr)
//go:linkname reflect_memmove reflect.memmove
func reflect_memmove(to, from unsafe.Pointer, n uintptr) {
diff --git a/src/runtime/trace.go b/src/runtime/trace.go
index e893525bd0..adf7b0951d 100644
--- a/src/runtime/trace.go
+++ b/src/runtime/trace.go
@@ -323,6 +323,10 @@ func StopTrace() {
// altogether instead of advancing to the next generation.
//
// traceAdvanceSema must not be held.
+//
+// traceAdvance is called by golang.org/x/exp/trace using linkname.
+//
+//go:linkname traceAdvance
func traceAdvance(stopTrace bool) {
semacquire(&traceAdvanceSema)
diff --git a/src/runtime/tracetime.go b/src/runtime/tracetime.go
index baef630ab5..571012413f 100644
--- a/src/runtime/tracetime.go
+++ b/src/runtime/tracetime.go
@@ -6,7 +6,10 @@
package runtime
-import "internal/goarch"
+import (
+ "internal/goarch"
+ _ "unsafe"
+)
// Timestamps in trace are produced through either nanotime or cputicks
// and divided by traceTimeDiv. nanotime is used everywhere except on
@@ -46,6 +49,9 @@ type traceTime uint64
//
// nosplit because it's called from exitsyscall, which is nosplit.
//
+// traceClockNow is called by golang.org/x/exp/trace using linkname.
+//
+//go:linkname traceClockNow
//go:nosplit
func traceClockNow() traceTime {
if osHasLowResClock {