]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link, runtime: apply a delta to RODATA->DATA relocations
authorCherry Mui <cherryyz@google.com>
Sat, 21 Dec 2024 03:33:15 +0000 (22:33 -0500)
committerCherry Mui <cherryyz@google.com>
Mon, 23 Dec 2024 17:49:40 +0000 (09:49 -0800)
On AIX, an R_ADDR relocation from an RODATA symbol to a DATA
symbol does not work, as the dynamic loader can change the address
of the data section, and it is not possible to apply a dynamic
relocation to RODATA. In order to get the correct address, we
apply the delta between unrelocated and relocated data section
addresses at run time. The linker saves both the unrelocated and
the relocated addresses, so we can compute the delta.

This is possible because RODATA symbols are generated by the
compiler and so we have full control of. On AIX, the only case
is the on-demand GC pointer masks from the type descriptors, for
very large types.

Perhaps there is a better way.

Fixes #70483.

Change-Id: I2664c0a813b38f7b146794cb1e73ccf5e238ca65
Reviewed-on: https://go-review.googlesource.com/c/go/+/638016
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/symtab.go
src/runtime/symtab.go
src/runtime/type.go

index 5c4497cdd75b0f7172bfc4505be30514f90f3c1a..a6b94a829f1442202d8156754c1dc57222797c8e 100644 (file)
@@ -424,6 +424,9 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
                                // FIXME: It should be forbidden to have R_ADDR from a
                                // symbol which isn't in .data. However, as .text has the
                                // same address once loaded, this is possible.
+                               // TODO: .text (including rodata) to .data relocation
+                               // doesn't work correctly, so we should really disallow it.
+                               // See also aixStaticDataBase in symtab.go and in runtime.
                                if ldr.SymSect(s).Seg == &Segdata {
                                        Xcoffadddynrel(target, ldr, syms, s, r, ri)
                                }
index 8156f83a7a3267c5ad7e0238a986322d20a03685..b89a7802a2c62adca2020d7de2bc7455993b7892 100644 (file)
@@ -707,6 +707,17 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
                // except go:buildid which is generated late and not used by the program.
                addRef("go:buildid")
        }
+       if ctxt.IsAIX() {
+               // On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol
+               // does not work. See data.go:relocsym, case R_ADDR.
+               // Here we record the unrelocated address in aixStaticDataBase (it is
+               // unrelocated as it is in RODATA) so we can compute the delta at
+               // run time.
+               sb := ldr.CreateSymForUpdate("runtime.aixStaticDataBase", 0)
+               sb.SetSize(0)
+               sb.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0))
+               sb.SetType(sym.SRODATA)
+       }
 
        // text section information
        slice(textsectionmapSym, uint64(nsections))
index c78b044264742d97ea9c15343787f03dad2215ba..c3bd5103205cf694e4d0c7b9048629c8c1cf53a2 100644 (file)
@@ -468,6 +468,18 @@ type modulehash struct {
 // To make sure the map isn't collected, we keep a second reference here.
 var pinnedTypemaps []map[typeOff]*_type
 
+// aixStaticDataBase (used only on AIX) holds the unrelocated address
+// of the data section, set by the linker.
+//
+// On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol
+// does not work, as the dynamic loader can change the address of the
+// data section, and it is not possible to apply a dynamic relocation
+// to RODATA. In order to get the correct address, we need to apply
+// the delta between unrelocated and relocated data section addresses.
+// aixStaticDataBase is the unrelocated address, and moduledata.data is
+// the relocated one.
+var aixStaticDataBase uintptr // linker symbol
+
 var firstmoduledata moduledata  // linker symbol
 var lastmoduledatap *moduledata // linker symbol
 
index 9702164b1a261af25c294340053ef2383344f2a1..1edf9c9dd6d85cea66d5ddd9063d254e76de805a 100644 (file)
@@ -104,6 +104,10 @@ func getGCMaskOnDemand(t *_type) *byte {
        // in read-only memory currently.
        addr := unsafe.Pointer(t.GCData)
 
+       if GOOS == "aix" {
+               addr = add(addr, firstmoduledata.data-aixStaticDataBase)
+       }
+
        for {
                p := (*byte)(atomic.Loadp(addr))
                switch p {