diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 837cfe59ca..b97ccf0ec9 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -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") } diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go index 379ecec6e7..f156cbf439 100644 --- a/src/cmd/link/internal/ld/xcoff.go +++ b/src/cmd/link/internal/ld/xcoff.go @@ -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) diff --git a/src/cmd/link/internal/ld/xcoff2.go b/src/cmd/link/internal/ld/xcoff2.go index f2c893feca..a8c2268fb7 100644 --- a/src/cmd/link/internal/ld/xcoff2.go +++ b/src/cmd/link/internal/ld/xcoff2.go @@ -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 +} diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 8f7fe35220..be124acaf8 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -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 } diff --git a/src/cmd/link/internal/ppc64/asm2.go b/src/cmd/link/internal/ppc64/asm2.go new file mode 100644 index 0000000000..0940df92f5 --- /dev/null +++ b/src/cmd/link/internal/ppc64/asm2.go @@ -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 +} diff --git a/src/cmd/link/internal/ppc64/obj.go b/src/cmd/link/internal/ppc64/obj.go index cff1e9cc73..51620b87a0 100644 --- a/src/cmd/link/internal/ppc64/obj.go +++ b/src/cmd/link/internal/ppc64/obj.go @@ -50,6 +50,7 @@ func Init() (*sys.Arch, ld.Arch) { Dwarfreglr: dwarfRegLR, Adddynrel: adddynrel, + Adddynrel2: adddynrel2, Archinit: archinit, Archreloc: archreloc, Archrelocvariant: archrelocvariant,