1
0
mirror of https://github.com/golang/go synced 2024-10-01 01:08:33 -06:00

[dev.link] cmd/link: support new dodata for PPC64

Add linux/{ppc64,ppc64le} and aix/ppc64 arch support for the new
dodata() phase.

This completes the picture in terms of architecture support for the
new dodata(), but to be safe this patch leaves the command line flag
in place there are problems on the builders (especially given that we
have a dead aix-ppc64 builder).

Change-Id: I78da615c3b540d8925ed7b3226e199280eb7451d
Reviewed-on: https://go-review.googlesource.com/c/go/+/229983
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Than McIntosh 2020-04-24 15:32:46 -04:00
parent a742d0ed5f
commit 8bd7c01417
6 changed files with 293 additions and 86 deletions

View File

@ -200,24 +200,6 @@ func Main(arch *sys.Arch, theArch Arch) {
bench.Start("Archinit")
thearch.Archinit(ctxt)
if *flagnewDoData {
// New dodata() is currently only implemented for selected targets.
switch {
case ctxt.IsElf():
switch {
case ctxt.Is386(), ctxt.IsAMD64(), ctxt.IsARM(), ctxt.IsARM64(),
ctxt.IsMIPS(), ctxt.IsMIPS64(), ctxt.IsRISCV64(), ctxt.IsS390X():
// supported
default:
*flagnewDoData = false
}
case ctxt.IsDarwin(), ctxt.IsPlan9(), ctxt.IsWasm():
// supported
default:
*flagnewDoData = false
}
}
if ctxt.linkShared && !ctxt.IsELF {
Exitf("-linkshared can only be used on elf systems")
}

View File

@ -360,7 +360,8 @@ type XcoffLdRel64 struct {
// xcoffLoaderReloc holds information about a relocation made by the loader.
type xcoffLoaderReloc struct {
sym *sym.Symbol
rel *sym.Reloc
sym2 loader.Sym
roff int32
rtype uint16
symndx int32
}
@ -1108,51 +1109,55 @@ func (f *xcoffFile) adddynimpsym(ctxt *Link, s loader.Sym) {
// Xcoffadddynrel adds a dynamic relocation in a XCOFF file.
// This relocation will be made by the loader.
func Xcoffadddynrel(target *Target, ldr *loader.Loader, s *sym.Symbol, r *sym.Reloc) bool {
func Xcoffadddynrel2(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, r *loader.Reloc2, rIdx int) bool {
if target.IsExternal() {
return true
}
if s.Type <= sym.SPCLNTAB {
Errorf(s, "cannot have a relocation to %s in a text section symbol", r.Sym.Name)
if ldr.SymType(s) <= sym.SPCLNTAB {
ldr.Errorf(s, "cannot have a relocation to %s in a text section symbol", ldr.SymName(r.Sym()))
return false
}
xldr := &xcoffLoaderReloc{
sym: s,
rel: r,
sym2: s,
roff: r.Off(),
}
targ := r.Sym()
var targType sym.SymKind
if targ != 0 {
targType = ldr.SymType(targ)
}
switch r.Type {
switch r.Type() {
default:
Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", r.Sym.Name, r.Type.String())
ldr.Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", ldr.SymName(targ), r.Type().String())
return false
case objabi.R_ADDR:
if s.Type == sym.SXCOFFTOC && r.Sym.Type == sym.SDYNIMPORT {
if ldr.SymType(s) == sym.SXCOFFTOC && targType == sym.SDYNIMPORT {
// Imported symbol relocation
for i, dynsym := range xfile.loaderSymbols {
if ldr.Syms[dynsym.sym].Name == r.Sym.Name {
if ldr.SymName(dynsym.sym) == ldr.SymName(targ) {
xldr.symndx = int32(i + 3) // +3 because of 3 section symbols
break
}
}
} else if s.Type == sym.SDATA {
switch r.Sym.Sect.Seg {
} else if ldr.SymType(s) == sym.SDATA {
switch ldr.SymSect(targ).Seg {
default:
Errorf(s, "unknown segment for .loader relocation with symbol %s", r.Sym.Name)
ldr.Errorf(s, "unknown segment for .loader relocation with symbol %s", ldr.SymName(targ))
case &Segtext:
case &Segrodata:
xldr.symndx = 0 // .text
case &Segdata:
if r.Sym.Type == sym.SBSS || r.Sym.Type == sym.SNOPTRBSS {
if targType == sym.SBSS || targType == sym.SNOPTRBSS {
xldr.symndx = 2 // .bss
} else {
xldr.symndx = 1 // .data
}
}
} else {
Errorf(s, "unexpected type for .loader relocation R_ADDR for symbol %s: %s to %s", r.Sym.Name, s.Type, r.Sym.Type)
ldr.Errorf(s, "unexpected type for .loader relocation R_ADDR for symbol %s: %s to %s", ldr.SymName(targ), ldr.SymType(s), ldr.SymType(targ))
return false
}
@ -1303,14 +1308,18 @@ func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
off += uint64(16 * len(f.loaderReloc))
for _, r := range f.loaderReloc {
symp := r.sym
if symp == nil {
symp = ctxt.loader.Syms[r.sym2]
}
xldr = &XcoffLdRel64{
Lvaddr: uint64(r.sym.Value + int64(r.rel.Off)),
Lvaddr: uint64(symp.Value + int64(r.roff)),
Lrtype: r.rtype,
Lsymndx: r.symndx,
}
if r.sym.Sect != nil {
xldr.Lrsecnm = f.getXCOFFscnum(r.sym.Sect)
if symp.Sect != nil {
xldr.Lrsecnm = f.getXCOFFscnum(symp.Sect)
}
reloctab = append(reloctab, xldr)

View File

@ -4,7 +4,11 @@
package ld
import "cmd/link/internal/sym"
import (
"cmd/internal/objabi"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
)
// Temporary dumping around for sym.Symbol version of helper
// functions in xcoff.go, still being used for some archs/oses.
@ -50,3 +54,60 @@ func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
}
}
// Xcoffadddynrel adds a dynamic relocation in a XCOFF file.
// This relocation will be made by the loader.
func Xcoffadddynrel(target *Target, ldr *loader.Loader, s *sym.Symbol, r *sym.Reloc) bool {
if target.IsExternal() {
return true
}
if s.Type <= sym.SPCLNTAB {
Errorf(s, "cannot have a relocation to %s in a text section symbol", r.Sym.Name)
return false
}
xldr := &xcoffLoaderReloc{
sym: s,
roff: r.Off,
}
switch r.Type {
default:
Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", r.Sym.Name, r.Type.String())
return false
case objabi.R_ADDR:
if s.Type == sym.SXCOFFTOC && r.Sym.Type == sym.SDYNIMPORT {
// Imported symbol relocation
for i, dynsym := range xfile.loaderSymbols {
if ldr.Syms[dynsym.sym].Name == r.Sym.Name {
xldr.symndx = int32(i + 3) // +3 because of 3 section symbols
break
}
}
} else if s.Type == sym.SDATA {
switch r.Sym.Sect.Seg {
default:
Errorf(s, "unknown segment for .loader relocation with symbol %s", r.Sym.Name)
case &Segtext:
case &Segrodata:
xldr.symndx = 0 // .text
case &Segdata:
if r.Sym.Type == sym.SBSS || r.Sym.Type == sym.SNOPTRBSS {
xldr.symndx = 2 // .bss
} else {
xldr.symndx = 1 // .data
}
}
} else {
Errorf(s, "unexpected type for .loader relocation R_ADDR for symbol %s: %s to %s", r.Sym.Name, s.Type, r.Sym.Type)
return false
}
xldr.rtype = 0x3F<<8 + XCOFF_R_POS
}
xfile.loaderReloc = append(xfile.loaderReloc, xldr)
return true
}

View File

@ -267,120 +267,134 @@ func gencallstub2(ctxt *ld.Link, ldr *loader.Loader, abicase int, stub *loader.S
stub.AddUint32(ctxt.Arch, 0x4e800420) // bctr
}
func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r *loader.Reloc2, rIdx int) bool {
if target.IsElf() {
return addelfdynrel(target, syms, s, r)
return addelfdynrel2(target, ldr, syms, s, r, rIdx)
} else if target.IsAIX() {
return ld.Xcoffadddynrel(target, ldr, s, r)
return ld.Xcoffadddynrel2(target, ldr, syms, s, r, rIdx)
}
return false
}
func addelfdynrel(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym
r.InitExt()
func addelfdynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r *loader.Reloc2, rIdx int) bool {
targ := r.Sym()
var targType sym.SymKind
if targ != 0 {
targType = ldr.SymType(targ)
}
switch r.Type {
switch r.Type() {
default:
if r.Type >= objabi.ElfRelocOffset {
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(target.Arch, r.Type))
if r.Type() >= objabi.ElfRelocOffset {
ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
return false
}
// Handle relocations found in ELF object files.
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
r.Type = objabi.R_CALLPOWER
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_CALLPOWER)
// This is a local call, so the caller isn't setting
// up r12 and r2 is the same for the caller and
// callee. Hence, we need to go to the local entry
// point. (If we don't do this, the callee will try
// to use r12 to compute r2.)
r.Add += int64(r.Sym.Localentry()) * 4
su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymLocalentry(targ))*4)
if targ.Type == sym.SDYNIMPORT {
if targType == sym.SDYNIMPORT {
// Should have been handled in elfsetupplt
ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
ldr.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
}
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
r.Type = objabi.R_PCREL
r.Add += 4
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_PCREL)
su.SetRelocAdd(rIdx, r.Add()+4)
if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
if targType == sym.SDYNIMPORT {
ldr.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
}
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64):
r.Type = objabi.R_ADDR
if targ.Type == sym.SDYNIMPORT {
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_ADDR)
if targType == sym.SDYNIMPORT {
// These happen in .toc sections
ld.Adddynsym(target, syms, targ)
ld.Adddynsym2(ldr, target, syms, targ)
rela := syms.Rela
rela.AddAddrPlus(target.Arch, s, int64(r.Off))
rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_PPC64_ADDR64)))
rela.AddUint64(target.Arch, uint64(r.Add))
r.Type = objabi.ElfRelocOffset // ignore during relocsym
rela := ldr.MakeSymbolUpdater(syms.Rela2)
rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64)))
rela.AddUint64(target.Arch, uint64(r.Add()))
su.SetRelocType(rIdx, objabi.ElfRelocOffset) // ignore during relocsym
}
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_LO | sym.RV_CHECK_OVERFLOW
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO|sym.RV_CHECK_OVERFLOW)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_LO
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_DS | sym.RV_CHECK_OVERFLOW
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS|sym.RV_CHECK_OVERFLOW)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_DS
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
r.Type = objabi.R_PCREL
r.Variant = sym.RV_POWER_LO
r.Add += 2 // Compensate for relocation size of 2
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_PCREL)
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
su.SetRelocAdd(rIdx, r.Add()+2) // Compensate for relocation size of 2
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
r.Type = objabi.R_PCREL
r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
r.Add += 2
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_PCREL)
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
su.SetRelocAdd(rIdx, r.Add()+2)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
r.Type = objabi.R_PCREL
r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
r.Add += 2
su := ldr.MakeSymbolUpdater(s)
su.SetRelocType(rIdx, objabi.R_PCREL)
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
su.SetRelocAdd(rIdx, r.Add()+2)
return true
}
// Handle references to ELF symbols from our own object files.
if targ.Type != sym.SDYNIMPORT {
if targType != sym.SDYNIMPORT {
return true
}

View File

@ -0,0 +1,140 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ppc64
import (
"cmd/internal/objabi"
"cmd/link/internal/ld"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"debug/elf"
)
// Temporary dumping ground for sym.Symbol version of helper
// functions in asm.go, still being used for some oses.
// FIXME: get rid of this file when dodata() is completely
// converted.
func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
if target.IsElf() {
return addelfdynrel(target, syms, s, r)
} else if target.IsAIX() {
return ld.Xcoffadddynrel(target, ldr, s, r)
}
return false
}
func addelfdynrel(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym
r.InitExt()
switch r.Type {
default:
if r.Type >= objabi.ElfRelocOffset {
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(target.Arch, r.Type))
return false
}
// Handle relocations found in ELF object files.
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
r.Type = objabi.R_CALLPOWER
// This is a local call, so the caller isn't setting
// up r12 and r2 is the same for the caller and
// callee. Hence, we need to go to the local entry
// point. (If we don't do this, the callee will try
// to use r12 to compute r2.)
r.Add += int64(r.Sym.Localentry()) * 4
if targ.Type == sym.SDYNIMPORT {
// Should have been handled in elfsetupplt
ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
}
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
r.Type = objabi.R_PCREL
r.Add += 4
if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
}
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64):
r.Type = objabi.R_ADDR
if targ.Type == sym.SDYNIMPORT {
// These happen in .toc sections
ld.Adddynsym(target, syms, targ)
rela := syms.Rela
rela.AddAddrPlus(target.Arch, s, int64(r.Off))
rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_PPC64_ADDR64)))
rela.AddUint64(target.Arch, uint64(r.Add))
r.Type = objabi.ElfRelocOffset // ignore during relocsym
}
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_LO | sym.RV_CHECK_OVERFLOW
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_LO
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_DS | sym.RV_CHECK_OVERFLOW
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
r.Type = objabi.R_POWER_TOC
r.Variant = sym.RV_POWER_DS
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
r.Type = objabi.R_PCREL
r.Variant = sym.RV_POWER_LO
r.Add += 2 // Compensate for relocation size of 2
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
r.Type = objabi.R_PCREL
r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
r.Add += 2
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
r.Type = objabi.R_PCREL
r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
r.Add += 2
return true
}
// Handle references to ELF symbols from our own object files.
if targ.Type != sym.SDYNIMPORT {
return true
}
// TODO(austin): Translate our relocations to ELF
return false
}

View File

@ -50,6 +50,7 @@ func Init() (*sys.Arch, ld.Arch) {
Dwarfreglr: dwarfRegLR,
Adddynrel: adddynrel,
Adddynrel2: adddynrel2,
Archinit: archinit,
Archreloc: archreloc,
Archrelocvariant: archrelocvariant,