Skip to content

Commit

Permalink
cmd/link, runtime: apply a delta to RODATA->DATA relocations
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
cherrymui committed Dec 23, 2024
1 parent eef35e3 commit b9955f0
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/cmd/link/internal/ld/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
11 changes: 11 additions & 0 deletions src/cmd/link/internal/ld/symtab.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
12 changes: 12 additions & 0 deletions src/runtime/symtab.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions src/runtime/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit b9955f0

Please sign in to comment.