From: Ian Lance Taylor Date: Sat, 31 Jan 2026 02:42:27 +0000 (-0800) Subject: reflect, runtime: adjust user-created GCData on AIX X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=bd1b41eb8131a503a1a8d2fc41d3e79bce159468;p=gostls13.git reflect, runtime: adjust user-created GCData on AIX On AIX the runtime adjusts the GCData field in getGCMaskOnDemand to account for the AIX dynamic loader moving the data section. That works fine for statically generated types, but it breaks user generated types. The user generated type will have a normal, correct, pointer, and adjusting the pointer will make it point elsewhere. This all happens to work OK when doing an external link, because in that case we do have dynamic relocs and there is no adjustment. But it fails with an internal link. This CL fixes the problem by applying a reverse adjustment to user generated types, so that the adjustment winds up with the original pointer value. Change-Id: Ibf3199b9ffb36e79af134fbed41db2853297de74 Reviewed-on: https://go-review.googlesource.com/c/go/+/740800 Reviewed-by: Keith Randall Reviewed-by: Keith Randall Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker --- diff --git a/src/reflect/type.go b/src/reflect/type.go index a2cab6eb7a..cf22152ab2 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -2580,6 +2580,9 @@ func StructOf(fields []StructField) Type { // space to store it. typ.TFlag |= abi.TFlagGCMaskOnDemand typ.GCData = (*byte)(unsafe.Pointer(new(uintptr))) + if runtime.GOOS == "aix" { + typ.GCData = adjustAIXGCData(typ.GCData) + } } typ.Equal = nil @@ -2745,6 +2748,9 @@ func ArrayOf(length int, elem Type) Type { // space to store it. array.TFlag |= abi.TFlagGCMaskOnDemand array.GCData = (*byte)(unsafe.Pointer(new(uintptr))) + if runtime.GOOS == "aix" { + array.GCData = adjustAIXGCData(array.GCData) + } } etyp := typ @@ -2776,6 +2782,34 @@ func ArrayOf(length int, elem Type) Type { return ti.(Type) } +// adjustAIXGCData adjusts the GCData field pointer for AIX. +// See runtime.getGCMaskOnDemand. +func adjustAIXGCData(addr *byte) *byte { + adjusted := adjustAIXGCDataForRuntime(addr) + if adjusted != addr { + pinAIXGCDataMu.Lock() + pinAIXGCData = append(pinAIXGCData, addr) + pinAIXGCDataMu.Unlock() + } + return adjusted +} + +// adjustAIXGCDataForRuntime adjusts the GCData field pointer +// as the runtime requires for AIX. See runtime.getGCMaskOnDemand. +// +//go:linkname adjustAIXGCDataForRuntime +//go:noescape +func adjustAIXGCDataForRuntime(*byte) *byte + +// pinAIXGCDataMu proects pinAIXGCData. +var pinAIXGCDataMu sync.Mutex + +// pinAIXGCData keeps the actual GCData pointer alive on AIX. +// On AIX we need to use adjustAIXGCData to convert the GC pointer +// to the value that the runtime expects. That means that the rtype +// no longer refers to the original pointer. This slice keeps it alive. +var pinAIXGCData []*byte + func appendVarint(x []byte, v uintptr) []byte { for ; v >= 0x80; v >>= 7 { x = append(x, byte(v|0x80)) diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index 9b1dd585ca..d5bce17563 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -732,6 +732,15 @@ func reflect_addReflectOff(ptr unsafe.Pointer) int32 { return id } +// reflect_adjustAIXGCDataForRuntime takes a type.GCData address and returns +// the new address to use. This is only called on AIX. +// See getGCMaskOnDemand. +// +//go:linkname reflect_adjustAIXGCDataForRuntime reflect.adjustAIXGCDataForRuntime +func reflect_adjustAIXGCDataForRuntime(addr *byte) *byte { + return (*byte)(add(unsafe.Pointer(addr), aixStaticDataBase-firstmoduledata.data)) +} + //go:linkname fips_getIndicator crypto/internal/fips140.getIndicator func fips_getIndicator() uint8 { return getg().fipsIndicator