// 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)
                                }
 
                // 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))
 
 // 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
 
 
        // 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 {