1
0
mirror of https://github.com/golang/go synced 2024-09-25 09:20:18 -06:00

cmd/link: fix moduledata symbols for aix/ppc64 and external linking

Moduledata symbols like runtime.data or runtime.text must have the
same position in the final executable (as some symbol accesses are made
by offset from them).
ld on AIX might move them randomly if there are nil size symbols.

ld will also remove unreachable symbols like runtime.epclntab or
runtime.rodata. In order to keep them, R_REF relocations are created
between firstmoduledata and these symbols. This relocation tells ld to
keep these symbols even if there aren't reachable.

Change-Id: Ie5a28cf406977131cec6442f7f5b6fd89fb775a3
Reviewed-on: https://go-review.googlesource.com/c/go/+/164004
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Clément Chigot 2019-02-20 16:20:56 +01:00 committed by Ian Lance Taylor
parent 80f10965ee
commit f0749c74fd
6 changed files with 101 additions and 13 deletions

View File

@ -196,6 +196,11 @@ const (
// R_WASMIMPORT resolves to the index of the WebAssembly function import. // R_WASMIMPORT resolves to the index of the WebAssembly function import.
R_WASMIMPORT R_WASMIMPORT
// R_XCOFFREF (only used on aix/ppc64) prevents garbage collection by ld
// of a symbol. This isn't a real relocation, it can be placed in anywhere
// in a symbol and target any symbols.
R_XCOFFREF
) )
// IsDirectJump reports whether r is a relocation for a direct jump. // IsDirectJump reports whether r is a relocation for a direct jump.

View File

@ -478,6 +478,21 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
o += r.Add - (s.Value + int64(r.Off) + int64(r.Siz)) o += r.Add - (s.Value + int64(r.Off) + int64(r.Siz))
case objabi.R_SIZE: case objabi.R_SIZE:
o = r.Sym.Size + r.Add o = r.Sym.Size + r.Add
case objabi.R_XCOFFREF:
if ctxt.HeadType != objabi.Haix {
Errorf(s, "find XCOFF R_REF on non-XCOFF files")
}
if ctxt.LinkMode != LinkExternal {
Errorf(s, "find XCOFF R_REF with internal linking")
}
r.Xsym = r.Sym
r.Xadd = r.Add
r.Done = false
// This isn't a real relocation so it must not update
// its offset value.
continue
} }
if r.Variant != sym.RV_NONE { if r.Variant != sym.RV_NONE {
@ -1115,7 +1130,7 @@ func (ctxt *Link) dodata() {
ctxt.Logf("%5.2f dodata\n", Cputime()) ctxt.Logf("%5.2f dodata\n", Cputime())
} }
if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin { if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
// The values in moduledata are filled out by relocations // The values in moduledata are filled out by relocations
// pointing to the addresses of these special symbols. // pointing to the addresses of these special symbols.
// Typically these symbols have no size and are not laid // Typically these symbols have no size and are not laid
@ -1133,6 +1148,12 @@ func (ctxt *Link) dodata() {
// To work around this we lay out the symbls whose // To work around this we lay out the symbls whose
// addresses are vital for multi-module programs to work // addresses are vital for multi-module programs to work
// as normal symbols, and give them a little size. // as normal symbols, and give them a little size.
//
// On AIX, as all DATA sections are merged together, ld might not put
// these symbols at the beginning of their respective section if there
// aren't real symbols, their alignment might not match the
// first symbol alignment. Therefore, there are explicitly put at the
// beginning of their section with the same alignment.
bss := ctxt.Syms.Lookup("runtime.bss", 0) bss := ctxt.Syms.Lookup("runtime.bss", 0)
bss.Size = 8 bss.Size = 8
bss.Attr.Set(sym.AttrSpecial, false) bss.Attr.Set(sym.AttrSpecial, false)
@ -1143,7 +1164,12 @@ func (ctxt *Link) dodata() {
data.Size = 8 data.Size = 8
data.Attr.Set(sym.AttrSpecial, false) data.Attr.Set(sym.AttrSpecial, false)
ctxt.Syms.Lookup("runtime.edata", 0).Attr.Set(sym.AttrSpecial, false) edata := ctxt.Syms.Lookup("runtime.edata", 0)
edata.Attr.Set(sym.AttrSpecial, false)
if ctxt.HeadType == objabi.Haix {
// XCOFFTOC symbols are part of .data section.
edata.Type = sym.SXCOFFTOC
}
types := ctxt.Syms.Lookup("runtime.types", 0) types := ctxt.Syms.Lookup("runtime.types", 0)
types.Type = sym.STYPE types.Type = sym.STYPE
@ -1153,6 +1179,16 @@ func (ctxt *Link) dodata() {
etypes := ctxt.Syms.Lookup("runtime.etypes", 0) etypes := ctxt.Syms.Lookup("runtime.etypes", 0)
etypes.Type = sym.SFUNCTAB etypes.Type = sym.SFUNCTAB
etypes.Attr.Set(sym.AttrSpecial, false) etypes.Attr.Set(sym.AttrSpecial, false)
if ctxt.HeadType == objabi.Haix {
rodata := ctxt.Syms.Lookup("runtime.rodata", 0)
rodata.Type = sym.SSTRING
rodata.Size = 8
rodata.Attr.Set(sym.AttrSpecial, false)
ctxt.Syms.Lookup("runtime.erodata", 0).Attr.Set(sym.AttrSpecial, false)
}
} }
// Collect data symbols by type into data. // Collect data symbols by type into data.
@ -1196,6 +1232,12 @@ func (ctxt *Link) dodata() {
// that an Outer symbol has been changed to a // that an Outer symbol has been changed to a
// relro Type before it reaches here. // relro Type before it reaches here.
isRelro = true isRelro = true
case sym.SFUNCTAB:
if ctxt.HeadType == objabi.Haix && s.Name == "runtime.etypes" {
// runtime.etypes must be at the end of
// the relro datas.
isRelro = true
}
} }
if isRelro { if isRelro {
s.Type = symnrelro s.Type = symnrelro
@ -1237,6 +1279,13 @@ func (ctxt *Link) dodata() {
} }
wg.Wait() wg.Wait()
if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
// These symbols must have the same alignment as their section.
// Otherwize, ld might change the layout of Go sections.
ctxt.Syms.ROLookup("runtime.data", 0).Align = dataMaxAlign[sym.SDATA]
ctxt.Syms.ROLookup("runtime.bss", 0).Align = dataMaxAlign[sym.SBSS]
}
// Allocate sections. // Allocate sections.
// Data is processed before segtext, because we need // Data is processed before segtext, because we need
// to see all symbols in the .data and .bss sections in order // to see all symbols in the .data and .bss sections in order
@ -1350,7 +1399,9 @@ func (ctxt *Link) dodata() {
gc.AddSym(s) gc.AddSym(s)
datsize += s.Size datsize += s.Size
} }
gc.End(datsize - int64(sect.Vaddr))
// On AIX, TOC entries must be the last of .data // On AIX, TOC entries must be the last of .data
// These aren't part of gc as they won't change during the runtime.
for _, s := range data[sym.SXCOFFTOC] { for _, s := range data[sym.SXCOFFTOC] {
s.Sect = sect s.Sect = sect
s.Type = sym.SDATA s.Type = sym.SDATA
@ -1360,7 +1411,6 @@ func (ctxt *Link) dodata() {
} }
checkdatsize(ctxt, datsize, sym.SDATA) checkdatsize(ctxt, datsize, sym.SDATA)
sect.Length = uint64(datsize) - sect.Vaddr sect.Length = uint64(datsize) - sect.Vaddr
gc.End(int64(sect.Length))
/* bss */ /* bss */
sect = addsection(ctxt.Arch, &Segdata, ".bss", 06) sect = addsection(ctxt.Arch, &Segdata, ".bss", 06)
@ -1555,8 +1605,15 @@ func (ctxt *Link) dodata() {
sect = addrelrosection("") sect = addrelrosection("")
sect.Vaddr = 0 sect.Vaddr = 0
if ctxt.HeadType == objabi.Haix {
// datsize must be reset because relro datas will end up
// in data segment.
datsize = 0
}
ctxt.Syms.Lookup("runtime.types", 0).Sect = sect ctxt.Syms.Lookup("runtime.types", 0).Sect = sect
ctxt.Syms.Lookup("runtime.etypes", 0).Sect = sect ctxt.Syms.Lookup("runtime.etypes", 0).Sect = sect
for _, symnro := range sym.ReadOnly { for _, symnro := range sym.ReadOnly {
symn := sym.RelROMap[symnro] symn := sym.RelROMap[symnro]
align := dataMaxAlign[symn] align := dataMaxAlign[symn]
@ -1778,12 +1835,12 @@ func dodataSect(ctxt *Link, symn sym.SymKind, syms []*sym.Symbol) (result []*sym
// If the usually-special section-marker symbols are being laid // If the usually-special section-marker symbols are being laid
// out as regular symbols, put them either at the beginning or // out as regular symbols, put them either at the beginning or
// end of their section. // end of their section.
if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin { if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
switch s.Name { switch s.Name {
case "runtime.text", "runtime.bss", "runtime.data", "runtime.types": case "runtime.text", "runtime.bss", "runtime.data", "runtime.types", "runtime.rodata":
head = s head = s
continue continue
case "runtime.etext", "runtime.ebss", "runtime.edata", "runtime.etypes": case "runtime.etext", "runtime.ebss", "runtime.edata", "runtime.etypes", "runtime.erodata":
tail = s tail = s
continue continue
} }
@ -1898,8 +1955,15 @@ func (ctxt *Link) textaddress() {
text := ctxt.Syms.Lookup("runtime.text", 0) text := ctxt.Syms.Lookup("runtime.text", 0)
text.Sect = sect text.Sect = sect
if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
// Setting runtime.text has a real symbol prevents ld to
// change its base address resulting in wrong offsets for
// reflect methods.
text.Align = sect.Align
text.Size = 0x8
}
if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin { if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
etext := ctxt.Syms.Lookup("runtime.etext", 0) etext := ctxt.Syms.Lookup("runtime.etext", 0)
etext.Sect = sect etext.Sect = sect

View File

@ -2137,9 +2137,10 @@ func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int6
s := ctxt.Syms.Lookup("runtime.text", 0) s := ctxt.Syms.Lookup("runtime.text", 0)
if s.Type == sym.STEXT { if s.Type == sym.STEXT {
// We've already included this symbol in ctxt.Textp // We've already included this symbol in ctxt.Textp
// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin. // if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin or
// on AIX with external linker.
// See data.go:/textaddress // See data.go:/textaddress
if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) { if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) && !(ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
put(ctxt, s, s.Name, TextSym, s.Value, nil) put(ctxt, s, s.Name, TextSym, s.Value, nil)
} }
} }
@ -2168,9 +2169,10 @@ func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int6
s = ctxt.Syms.Lookup("runtime.etext", 0) s = ctxt.Syms.Lookup("runtime.etext", 0)
if s.Type == sym.STEXT { if s.Type == sym.STEXT {
// We've already included this symbol in ctxt.Textp // We've already included this symbol in ctxt.Textp
// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin. // if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin or
// on AIX with external linker.
// See data.go:/textaddress // See data.go:/textaddress
if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) { if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) && !(ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
put(ctxt, s, s.Name, TextSym, s.Value, nil) put(ctxt, s, s.Name, TextSym, s.Value, nil)
} }
} }

View File

@ -562,6 +562,20 @@ func (ctxt *Link) symtab() {
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0)) moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0)) moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0))
if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
// Add R_REF relocation to prevent ld's garbage collection of
// runtime.rodata, runtime.erodata and runtime.epclntab.
addRef := func(name string) {
r := moduledata.AddRel()
r.Sym = ctxt.Syms.Lookup(name, 0)
r.Type = objabi.R_XCOFFREF
r.Siz = uint8(ctxt.Arch.PtrSize)
}
addRef("runtime.rodata")
addRef("runtime.erodata")
addRef("runtime.epclntab")
}
// text section information // text section information
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0)) moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0))
moduledata.AddUint(ctxt.Arch, uint64(nsections)) moduledata.AddUint(ctxt.Arch, uint64(nsections))

View File

@ -585,7 +585,8 @@ func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
fallthrough fallthrough
case sym.STYPE: case sym.STYPE:
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
outerSymSize["type.*"] = size // runtime.types size must be removed.
outerSymSize["type.*"] = size - ctxt.Syms.ROLookup("runtime.types", 0).Size
} }
case sym.SGOSTRING: case sym.SGOSTRING:
outerSymSize["go.string.*"] = size outerSymSize["go.string.*"] = size
@ -1571,7 +1572,6 @@ func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
r := &s.R[ri] r := &s.R[ri]
// ctxt.Logf("%s reloc %d(%s)/%d to %s\n", s, r.Type, r.Type.String(), r.Siz, r.Sym.Name)
if r.Done { if r.Done {
continue continue
} }

View File

@ -414,6 +414,9 @@ func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se
return false return false
} }
emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0) emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
case objabi.R_XCOFFREF:
emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
} }
return true return true