Skip to content

Commit b9955f0

Browse files
committed
cmd/link, runtime: apply a delta to RODATA->DATA relocations
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 <[email protected]> Reviewed-by: Keith Randall <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent eef35e3 commit b9955f0

File tree

4 files changed

+30
-0
lines changed

4 files changed

+30
-0
lines changed

src/cmd/link/internal/ld/data.go

+3
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,9 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
424424
// FIXME: It should be forbidden to have R_ADDR from a
425425
// symbol which isn't in .data. However, as .text has the
426426
// same address once loaded, this is possible.
427+
// TODO: .text (including rodata) to .data relocation
428+
// doesn't work correctly, so we should really disallow it.
429+
// See also aixStaticDataBase in symtab.go and in runtime.
427430
if ldr.SymSect(s).Seg == &Segdata {
428431
Xcoffadddynrel(target, ldr, syms, s, r, ri)
429432
}

src/cmd/link/internal/ld/symtab.go

+11
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,17 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
707707
// except go:buildid which is generated late and not used by the program.
708708
addRef("go:buildid")
709709
}
710+
if ctxt.IsAIX() {
711+
// On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol
712+
// does not work. See data.go:relocsym, case R_ADDR.
713+
// Here we record the unrelocated address in aixStaticDataBase (it is
714+
// unrelocated as it is in RODATA) so we can compute the delta at
715+
// run time.
716+
sb := ldr.CreateSymForUpdate("runtime.aixStaticDataBase", 0)
717+
sb.SetSize(0)
718+
sb.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0))
719+
sb.SetType(sym.SRODATA)
720+
}
710721

711722
// text section information
712723
slice(textsectionmapSym, uint64(nsections))

src/runtime/symtab.go

+12
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,18 @@ type modulehash struct {
468468
// To make sure the map isn't collected, we keep a second reference here.
469469
var pinnedTypemaps []map[typeOff]*_type
470470

471+
// aixStaticDataBase (used only on AIX) holds the unrelocated address
472+
// of the data section, set by the linker.
473+
//
474+
// On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol
475+
// does not work, as the dynamic loader can change the address of the
476+
// data section, and it is not possible to apply a dynamic relocation
477+
// to RODATA. In order to get the correct address, we need to apply
478+
// the delta between unrelocated and relocated data section addresses.
479+
// aixStaticDataBase is the unrelocated address, and moduledata.data is
480+
// the relocated one.
481+
var aixStaticDataBase uintptr // linker symbol
482+
471483
var firstmoduledata moduledata // linker symbol
472484
var lastmoduledatap *moduledata // linker symbol
473485

src/runtime/type.go

+4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ func getGCMaskOnDemand(t *_type) *byte {
104104
// in read-only memory currently.
105105
addr := unsafe.Pointer(t.GCData)
106106

107+
if GOOS == "aix" {
108+
addr = add(addr, firstmoduledata.data-aixStaticDataBase)
109+
}
110+
107111
for {
108112
p := (*byte)(atomic.Loadp(addr))
109113
switch p {

0 commit comments

Comments
 (0)