mirror of
https://github.com/golang/go
synced 2024-11-26 07:17:59 -07:00
cmd/link: rework .TOC. handling for ppc64le
Setup .TOC. to point to the same place for all objects. Today, the linker assumes all call relocations can use the local function entry point of imported object files. This requires a consistent pointer across all objects. This intentionally computes the .TOC. pointer in all linking configurations. In some cases the .TOC. is not used today (e.g linking position-dependent go only code). It is harmless and simple to compute in all cases, so just do it for easier maintenance. Notably, .TOC. is used in some cases when static linking is requested on ppc64le/linux: * Position-independent C code using a PC-rel relocation against .TOC.. cgo generated C object files are usually compiled PIC even if the go binary itself is not. * Anything which causes PLT stub generation. The stubs always generate a .TOC. relative relocation. * The race detector. Today, this links in an externally compiled archive which contains position-independent object files. Similarly, position-independent linking is always punted to the external linker on ppc64 today. Updates #21961 Fixes #15409 Change-Id: Ifd8294b9249e16ba8b92eaf876d15d162f9c61fd Reviewed-on: https://go-review.googlesource.com/c/go/+/304458 Reviewed-by: Cherry Mui <cherryyz@google.com> Trust: Lynn Boger <laboger@linux.vnet.ibm.com>
This commit is contained in:
parent
50c69cc3a9
commit
9295723079
@ -1710,21 +1710,9 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
|
||||
}
|
||||
ldr := ctxt.loader
|
||||
|
||||
// .got (and .toc on ppc64)
|
||||
// .got
|
||||
if len(state.data[sym.SELFGOT]) > 0 {
|
||||
sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06)
|
||||
if ctxt.IsPPC64() {
|
||||
for _, s := range state.data[sym.SELFGOT] {
|
||||
// Resolve .TOC. symbol for this object file (ppc64)
|
||||
|
||||
toc := ldr.Lookup(".TOC.", int(ldr.SymVersion(s)))
|
||||
if toc != 0 {
|
||||
ldr.SetSymSect(toc, sect)
|
||||
ldr.AddInteriorSym(s, toc)
|
||||
ldr.SetSymValue(toc, 0x8000)
|
||||
}
|
||||
}
|
||||
}
|
||||
state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06)
|
||||
}
|
||||
|
||||
/* pointer-free data */
|
||||
@ -2690,6 +2678,24 @@ func (ctxt *Link) address() []*sym.Segment {
|
||||
ldr.SetSymSect(ldr.Lookup("_end", 0), ldr.SymSect(end))
|
||||
}
|
||||
|
||||
if ctxt.IsPPC64() && ctxt.IsElf() {
|
||||
// Resolve .TOC. symbols for all objects. Only one TOC region is supported. If a
|
||||
// GOT section is present, compute it as suggested by the ELFv2 ABI. Otherwise,
|
||||
// choose a similar offset from the start of the data segment.
|
||||
tocAddr := int64(Segdata.Vaddr) + 0x8000
|
||||
if gotAddr := ldr.SymValue(ctxt.GOT); gotAddr != 0 {
|
||||
tocAddr = gotAddr + 0x8000
|
||||
}
|
||||
for i, _ := range ctxt.DotTOC {
|
||||
if i >= sym.SymVerABICount && i < sym.SymVerStatic { // these versions are not used currently
|
||||
continue
|
||||
}
|
||||
if toc := ldr.Lookup(".TOC.", i); toc != 0 {
|
||||
ldr.SetSymValue(toc, tocAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return order
|
||||
}
|
||||
|
||||
|
@ -149,16 +149,9 @@ func (ctxt *Link) setArchSyms() {
|
||||
if ctxt.IsPPC64() {
|
||||
ctxt.mkArchSym("TOC", 0, &ctxt.TOC)
|
||||
|
||||
// NB: note the +2 below for DotTOC2 compared to the +1 for
|
||||
// DocTOC. This is because loadlibfull() creates an additional
|
||||
// syms version during conversion of loader.Sym symbols to
|
||||
// *sym.Symbol symbols. Symbols that are assigned this final
|
||||
// version are not going to have TOC references, so it should
|
||||
// be ok for them to inherit an invalid .TOC. symbol.
|
||||
// TODO: revisit the +2, now that loadlibfull is gone.
|
||||
ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+2)
|
||||
ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+1)
|
||||
for i := 0; i <= ctxt.MaxVersion(); i++ {
|
||||
if i >= 2 && i < sym.SymVerStatic { // these versions are not used currently
|
||||
if i >= sym.SymVerABICount && i < sym.SymVerStatic { // these versions are not used currently
|
||||
continue
|
||||
}
|
||||
ctxt.mkArchSymVec(".TOC.", i, ctxt.DotTOC)
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
const (
|
||||
SymVerABI0 = 0
|
||||
SymVerABIInternal = 1
|
||||
SymVerABICount = 2 // Number of internal ABIs
|
||||
SymVerStatic = 10 // Minimum version used by static (file-local) syms
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user