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")
}
// 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
}
// 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
}
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)
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.
}
}
+
+// 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
+}
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
}
--- /dev/null
+// 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
+}
Dwarfreglr: dwarfRegLR,
Adddynrel: adddynrel,
+ Adddynrel2: adddynrel2,
Archinit: archinit,
Archreloc: archreloc,
Archrelocvariant: archrelocvariant,