Add elf/ARM arch support for the new dodata() phase.
Change-Id: Iadd772b01036c6c5be95bcc6017f6c05d45a24c0
Reviewed-on: https://go-review.googlesource.com/c/go/+/229868
Reviewed-by: Cherry Zhang <cherryyz@google.com>
return int32((uint32(a))&0xff000000 | 0x00ffffff&uint32(a+b))
}
-func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
- targ := r.Sym
+func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r *loader.Reloc2, rIdx int) bool {
- switch r.Type {
+ targ := r.Sym()
+ var targType sym.SymKind
+ if targ != 0 {
+ targType = ldr.SymType(targ)
+ }
+
+ 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_ARM_PLT32):
- r.Type = objabi.R_CALLARM
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_CALLARM)
- if targ.Type == sym.SDYNIMPORT {
- addpltsym(target, syms, targ)
- r.Sym = syms.PLT
- r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
+ if targType == sym.SDYNIMPORT {
+ addpltsym2(target, ldr, syms, targ)
+ su.SetRelocSym(rIdx, syms.PLT2)
+ su.SetRelocAdd(rIdx, int64(braddoff(int32(r.Add()), ldr.SymPlt(targ)/4)))
}
return true
return false
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT32): // R_ARM_GOT_BREL
- if targ.Type != sym.SDYNIMPORT {
- addgotsyminternal(target, syms, targ)
+ if targType != sym.SDYNIMPORT {
+ addgotsyminternal2(target, ldr, syms, targ)
} else {
- addgotsym(target, syms, targ)
+ addgotsym2(target, ldr, syms, targ)
}
- r.Type = objabi.R_CONST // write r->add during relocsym
- r.Sym = nil
- r.Add += int64(targ.Got())
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_CONST) // write r->add during relocsym
+ su.SetRelocSym(rIdx, 0)
+ su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT_PREL): // GOT(nil) + A - nil
- if targ.Type != sym.SDYNIMPORT {
- addgotsyminternal(target, syms, targ)
+ if targType != sym.SDYNIMPORT {
+ addgotsyminternal2(target, ldr, syms, targ)
} else {
- addgotsym(target, syms, targ)
+ addgotsym2(target, ldr, syms, targ)
}
-
- r.Type = objabi.R_PCREL
- r.Sym = syms.GOT
- r.Add += int64(targ.Got()) + 4
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_PCREL)
+ su.SetRelocSym(rIdx, syms.GOT2)
+ su.SetRelocAdd(rIdx, r.Add()+4+int64(ldr.SymGot(targ)))
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOTOFF): // R_ARM_GOTOFF32
- r.Type = objabi.R_GOTOFF
-
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_GOTOFF)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOTPC): // R_ARM_BASE_PREL
- r.Type = objabi.R_PCREL
-
- r.Sym = syms.GOT
- r.Add += 4
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_PCREL)
+ su.SetRelocSym(rIdx, syms.GOT2)
+ su.SetRelocAdd(rIdx, r.Add()+4)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_CALL):
- r.Type = objabi.R_CALLARM
- if targ.Type == sym.SDYNIMPORT {
- addpltsym(target, syms, targ)
- r.Sym = syms.PLT
- r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_CALLARM)
+ if targType == sym.SDYNIMPORT {
+ addpltsym2(target, ldr, syms, targ)
+ su.SetRelocSym(rIdx, syms.PLT2)
+ su.SetRelocAdd(rIdx, int64(braddoff(int32(r.Add()), ldr.SymPlt(targ)/4)))
}
-
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_REL32): // R_ARM_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)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_ABS32):
- if targ.Type == sym.SDYNIMPORT {
- ld.Errorf(s, "unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ.Name)
+ if targType == sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected R_ARM_ABS32 relocation for dynamic symbol %s", ldr.SymName(targ))
}
- r.Type = objabi.R_ADDR
- return true
-
- // we can just ignore this, because we are targeting ARM V5+ anyway
- case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_V4BX):
- if r.Sym != nil {
- // R_ARM_V4BX is ABS relocation, so this symbol is a dummy symbol, ignore it
- r.Sym.Type = 0
- }
-
- r.Sym = nil
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_ADDR)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_PC24),
objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_JUMP24):
- r.Type = objabi.R_CALLARM
- if targ.Type == sym.SDYNIMPORT {
- addpltsym(target, syms, targ)
- r.Sym = syms.PLT
- r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_CALLARM)
+ if targType == sym.SDYNIMPORT {
+ addpltsym2(target, ldr, syms, targ)
+ su.SetRelocSym(rIdx, syms.PLT2)
+ su.SetRelocAdd(rIdx, int64(braddoff(int32(r.Add()), ldr.SymPlt(targ)/4)))
}
return true
}
// Handle references to ELF symbols from our own object files.
- if targ.Type != sym.SDYNIMPORT {
+ if targType != sym.SDYNIMPORT {
return true
}
- switch r.Type {
+ // Reread the reloc to incorporate any changes in type above.
+ relocs := ldr.Relocs(s)
+ *r = relocs.At2(rIdx)
+
+ switch r.Type() {
case objabi.R_CALLARM:
if target.IsExternal() {
// External linker will do this relocation.
return true
}
- addpltsym(target, syms, targ)
- r.Sym = syms.PLT
- r.Add = int64(targ.Plt())
+ addpltsym2(target, ldr, syms, targ)
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocSym(rIdx, syms.PLT2)
+ su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
return true
case objabi.R_ADDR:
- if s.Type != sym.SDATA {
+ if ldr.SymType(s) != sym.SDATA {
break
}
if target.IsElf() {
- ld.Adddynsym(target, syms, targ)
- rel := syms.Rel
- rel.AddAddrPlus(target.Arch, s, int64(r.Off))
- rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(targ.Dynid), uint32(elf.R_ARM_GLOB_DAT))) // we need a nil + A dynamic reloc
- r.Type = objabi.R_CONST // write r->add during relocsym
- r.Sym = nil
+ ld.Adddynsym2(ldr, target, syms, targ)
+ rel := ldr.MakeSymbolUpdater(syms.Rel2)
+ rel.AddAddrPlus(target.Arch, s, int64(r.Off()))
+ rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_ARM_GLOB_DAT))) // we need a nil + A dynamic reloc
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_CONST) // write r->add during relocsym
+ su.SetRelocSym(rIdx, 0)
return true
}
}
return t
}
-func addpltreloc(plt *sym.Symbol, got *sym.Symbol, s *sym.Symbol, typ objabi.RelocType) {
- r := plt.AddRel()
- r.Sym = got
- r.Off = int32(plt.Size)
- r.Siz = 4
- r.Type = typ
- r.Add = int64(s.Got()) - 8
-
- plt.Attr |= sym.AttrReachable
- plt.Size += 4
- plt.Grow(plt.Size)
+func addpltreloc2(ldr *loader.Loader, plt *loader.SymbolBuilder, got *loader.SymbolBuilder, s loader.Sym, typ objabi.RelocType) {
+ r, _ := plt.AddRel(typ)
+ r.SetSym(got.Sym())
+ r.SetOff(int32(plt.Size()))
+ r.SetSiz(4)
+ r.SetAdd(int64(ldr.SymGot(s)) - 8)
+
+ plt.SetReachable(true)
+ plt.SetSize(plt.Size() + 4)
+ plt.Grow(plt.Size())
}
-func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
- if s.Plt() >= 0 {
+func addpltsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+ if ldr.SymPlt(s) >= 0 {
return
}
- ld.Adddynsym(target, syms, s)
+ ld.Adddynsym2(ldr, target, syms, s)
if target.IsElf() {
- plt := syms.PLT
- got := syms.GOTPLT
- rel := syms.RelPLT
- if plt.Size == 0 {
+ plt := ldr.MakeSymbolUpdater(syms.PLT2)
+ got := ldr.MakeSymbolUpdater(syms.GOTPLT2)
+ rel := ldr.MakeSymbolUpdater(syms.RelPLT2)
+ if plt.Size() == 0 {
panic("plt is not set up")
}
// .got entry
- s.SetGot(int32(got.Size))
+ ldr.SetGot(s, int32(got.Size()))
// In theory, all GOT should point to the first PLT entry,
// Linux/ARM's dynamic linker will do that for us, but FreeBSD/ARM's
// dynamic linker won't, so we'd better do it ourselves.
- got.AddAddrPlus(target.Arch, plt, 0)
+ got.AddAddrPlus(target.Arch, plt.Sym(), 0)
// .plt entry, this depends on the .got entry
- s.SetPlt(int32(plt.Size))
+ ldr.SetPlt(s, int32(plt.Size()))
- addpltreloc(plt, got, s, objabi.R_PLT0) // add lr, pc, #0xXX00000
- addpltreloc(plt, got, s, objabi.R_PLT1) // add lr, lr, #0xYY000
- addpltreloc(plt, got, s, objabi.R_PLT2) // ldr pc, [lr, #0xZZZ]!
+ addpltreloc2(ldr, plt, got, s, objabi.R_PLT0) // add lr, pc, #0xXX00000
+ addpltreloc2(ldr, plt, got, s, objabi.R_PLT1) // add lr, lr, #0xYY000
+ addpltreloc2(ldr, plt, got, s, objabi.R_PLT2) // ldr pc, [lr, #0xZZZ]!
// rel
- rel.AddAddrPlus(target.Arch, got, int64(s.Got()))
+ rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
- rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_JUMP_SLOT)))
+ rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_ARM_JUMP_SLOT)))
} else {
- ld.Errorf(s, "addpltsym: unsupported binary format")
+ ldr.Errorf(s, "addpltsym: unsupported binary format")
}
}
-func addgotsyminternal(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
- if s.Got() >= 0 {
+func addgotsyminternal2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+ if ldr.SymGot(s) >= 0 {
return
}
- got := syms.GOT
- s.SetGot(int32(got.Size))
-
+ got := ldr.MakeSymbolUpdater(syms.GOT2)
+ ldr.SetGot(s, int32(got.Size()))
got.AddAddrPlus(target.Arch, s, 0)
if target.IsElf() {
} else {
- ld.Errorf(s, "addgotsyminternal: unsupported binary format")
+ ldr.Errorf(s, "addgotsyminternal: unsupported binary format")
}
}
-func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
- if s.Got() >= 0 {
+func addgotsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+ if ldr.SymGot(s) >= 0 {
return
}
- ld.Adddynsym(target, syms, s)
- got := syms.GOT
- s.SetGot(int32(got.Size))
- got.AddUint32(target.Arch, 0)
+ ld.Adddynsym2(ldr, target, syms, s)
+ got := ldr.MakeSymbolUpdater(syms.GOT2)
+ ldr.SetGot(s, int32(got.Size()))
+ got.AddUint64(target.Arch, 0)
if target.IsElf() {
- rel := syms.Rel
- rel.AddAddrPlus(target.Arch, got, int64(s.Got()))
- rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_GLOB_DAT)))
+ rel := ldr.MakeSymbolUpdater(syms.Rel2)
+ rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
+ rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_ARM_GLOB_DAT)))
} else {
- ld.Errorf(s, "addgotsym: unsupported binary format")
+ ldr.Errorf(s, "addgotsym: unsupported binary format")
}
}
--- /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 arm
+
+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 {
+ targ := r.Sym
+
+ 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_ARM_PLT32):
+ r.Type = objabi.R_CALLARM
+
+ if targ.Type == sym.SDYNIMPORT {
+ addpltsym(target, syms, targ)
+ r.Sym = syms.PLT
+ r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
+ }
+
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_THM_PC22): // R_ARM_THM_CALL
+ ld.Exitf("R_ARM_THM_CALL, are you using -marm?")
+ return false
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT32): // R_ARM_GOT_BREL
+ if targ.Type != sym.SDYNIMPORT {
+ addgotsyminternal(target, syms, targ)
+ } else {
+ addgotsym(target, syms, targ)
+ }
+
+ r.Type = objabi.R_CONST // write r->add during relocsym
+ r.Sym = nil
+ r.Add += int64(targ.Got())
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT_PREL): // GOT(nil) + A - nil
+ if targ.Type != sym.SDYNIMPORT {
+ addgotsyminternal(target, syms, targ)
+ } else {
+ addgotsym(target, syms, targ)
+ }
+
+ r.Type = objabi.R_PCREL
+ r.Sym = syms.GOT
+ r.Add += int64(targ.Got()) + 4
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOTOFF): // R_ARM_GOTOFF32
+ r.Type = objabi.R_GOTOFF
+
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOTPC): // R_ARM_BASE_PREL
+ r.Type = objabi.R_PCREL
+
+ r.Sym = syms.GOT
+ r.Add += 4
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_CALL):
+ r.Type = objabi.R_CALLARM
+ if targ.Type == sym.SDYNIMPORT {
+ addpltsym(target, syms, targ)
+ r.Sym = syms.PLT
+ r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
+ }
+
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_REL32): // R_ARM_REL32
+ r.Type = objabi.R_PCREL
+
+ r.Add += 4
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_ABS32):
+ if targ.Type == sym.SDYNIMPORT {
+ ld.Errorf(s, "unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ.Name)
+ }
+ r.Type = objabi.R_ADDR
+ return true
+
+ // we can just ignore this, because we are targeting ARM V5+ anyway
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_V4BX):
+ if r.Sym != nil {
+ // R_ARM_V4BX is ABS relocation, so this symbol is a dummy symbol, ignore it
+ r.Sym.Type = 0
+ }
+
+ r.Sym = nil
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_PC24),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_JUMP24):
+ r.Type = objabi.R_CALLARM
+ if targ.Type == sym.SDYNIMPORT {
+ addpltsym(target, syms, targ)
+ r.Sym = syms.PLT
+ r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
+ }
+
+ return true
+ }
+
+ // Handle references to ELF symbols from our own object files.
+ if targ.Type != sym.SDYNIMPORT {
+ return true
+ }
+
+ switch r.Type {
+ case objabi.R_CALLARM:
+ if target.IsExternal() {
+ // External linker will do this relocation.
+ return true
+ }
+ addpltsym(target, syms, targ)
+ r.Sym = syms.PLT
+ r.Add = int64(targ.Plt())
+ return true
+
+ case objabi.R_ADDR:
+ if s.Type != sym.SDATA {
+ break
+ }
+ if target.IsElf() {
+ ld.Adddynsym(target, syms, targ)
+ rel := syms.Rel
+ rel.AddAddrPlus(target.Arch, s, int64(r.Off))
+ rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(targ.Dynid), uint32(elf.R_ARM_GLOB_DAT))) // we need a nil + A dynamic reloc
+ r.Type = objabi.R_CONST // write r->add during relocsym
+ r.Sym = nil
+ return true
+ }
+ }
+
+ return false
+}
+
+func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
+ if s.Plt() >= 0 {
+ return
+ }
+
+ ld.Adddynsym(target, syms, s)
+
+ if target.IsElf() {
+ plt := syms.PLT
+ got := syms.GOTPLT
+ rel := syms.RelPLT
+ if plt.Size == 0 {
+ panic("plt is not set up")
+ }
+
+ // .got entry
+ s.SetGot(int32(got.Size))
+
+ // In theory, all GOT should point to the first PLT entry,
+ // Linux/ARM's dynamic linker will do that for us, but FreeBSD/ARM's
+ // dynamic linker won't, so we'd better do it ourselves.
+ got.AddAddrPlus(target.Arch, plt, 0)
+
+ // .plt entry, this depends on the .got entry
+ s.SetPlt(int32(plt.Size))
+
+ addpltreloc(plt, got, s, objabi.R_PLT0) // add lr, pc, #0xXX00000
+ addpltreloc(plt, got, s, objabi.R_PLT1) // add lr, lr, #0xYY000
+ addpltreloc(plt, got, s, objabi.R_PLT2) // ldr pc, [lr, #0xZZZ]!
+
+ // rel
+ rel.AddAddrPlus(target.Arch, got, int64(s.Got()))
+
+ rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_JUMP_SLOT)))
+ } else {
+ ld.Errorf(s, "addpltsym: unsupported binary format")
+ }
+}
+
+func addpltreloc(plt *sym.Symbol, got *sym.Symbol, s *sym.Symbol, typ objabi.RelocType) {
+ r := plt.AddRel()
+ r.Sym = got
+ r.Off = int32(plt.Size)
+ r.Siz = 4
+ r.Type = typ
+ r.Add = int64(s.Got()) - 8
+
+ plt.Attr |= sym.AttrReachable
+ plt.Size += 4
+ plt.Grow(plt.Size)
+}
+
+func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
+ if s.Got() >= 0 {
+ return
+ }
+
+ ld.Adddynsym(target, syms, s)
+ got := syms.GOT
+ s.SetGot(int32(got.Size))
+ got.AddUint32(target.Arch, 0)
+
+ if target.IsElf() {
+ rel := syms.Rel
+ rel.AddAddrPlus(target.Arch, got, int64(s.Got()))
+ rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_GLOB_DAT)))
+ } else {
+ ld.Errorf(s, "addgotsym: unsupported binary format")
+ }
+}
+
+func addgotsyminternal(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
+ if s.Got() >= 0 {
+ return
+ }
+
+ got := syms.GOT
+ s.SetGot(int32(got.Size))
+
+ got.AddAddrPlus(target.Arch, s, 0)
+
+ if target.IsElf() {
+ } else {
+ ld.Errorf(s, "addgotsyminternal: unsupported binary format")
+ }
+}
Dwarfreglr: dwarfRegLR,
Adddynrel: adddynrel,
+ Adddynrel2: adddynrel2,
Archinit: archinit,
Archreloc: archreloc,
Archrelocvariant: archrelocvariant,
initfunc.AddReloc(rel2)
}
-func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
- targ := r.Sym
+func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r *loader.Reloc2, rIdx int) bool {
- switch r.Type {
+ targ := r.Sym()
+ var targType sym.SymKind
+ if targ != 0 {
+ targType = ldr.SymType(targ)
+ }
+
+ 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_AARCH64_PREL32):
- if targ.Type == sym.SDYNIMPORT {
- ld.Errorf(s, "unexpected R_AARCH64_PREL32 relocation for dynamic symbol %s", targ.Name)
+ if targType == sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected R_AARCH64_PREL32 relocation for dynamic symbol %s", ldr.SymName(targ))
}
// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
// sense and should be removed when someone has thought about it properly.
- if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
- ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
+ if (targType == 0 || targType == sym.SXREF) && !ldr.AttrVisibilityHidden(targ) {
+ ldr.Errorf(s, "unknown symbol %s in pcrel", ldr.SymName(targ))
}
- r.Type = objabi.R_PCREL
- r.Add += 4
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_PCREL)
+ su.SetRelocAdd(rIdx, r.Add()+4)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_PREL64):
- if targ.Type == sym.SDYNIMPORT {
- ld.Errorf(s, "unexpected R_AARCH64_PREL64 relocation for dynamic symbol %s", targ.Name)
+ if targType == sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected R_AARCH64_PREL64 relocation for dynamic symbol %s", ldr.SymName(targ))
}
- if targ.Type == 0 || targ.Type == sym.SXREF {
- ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
+ if targType == 0 || targType == sym.SXREF {
+ ldr.Errorf(s, "unknown symbol %s in pcrel", ldr.SymName(targ))
}
- r.Type = objabi.R_PCREL
- r.Add += 8
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_PCREL)
+ su.SetRelocAdd(rIdx, r.Add()+8)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26):
- if targ.Type == sym.SDYNIMPORT {
- addpltsym(target, syms, targ)
- r.Sym = syms.PLT
- r.Add += int64(targ.Plt())
+ if targType == sym.SDYNIMPORT {
+ addpltsym2(target, ldr, syms, targ)
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocSym(rIdx, syms.PLT2)
+ su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
}
- if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
- ld.Errorf(s, "unknown symbol %s in callarm64", targ.Name)
+ if (targType == 0 || targType == sym.SXREF) && !ldr.AttrVisibilityHidden(targ) {
+ ldr.Errorf(s, "unknown symbol %s in callarm64", ldr.SymName(targ))
}
- r.Type = objabi.R_CALLARM64
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_CALLARM64)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_GOT_PAGE),
objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LD64_GOT_LO12_NC):
- if targ.Type != sym.SDYNIMPORT {
+ if targType != sym.SDYNIMPORT {
// have symbol
// TODO: turn LDR of GOT entry into ADR of symbol itself
}
// fall back to using GOT
// TODO: just needs relocation, no need to put in .dynsym
- addgotsym(target, syms, targ)
-
- r.Type = objabi.R_ARM64_GOT
- r.Sym = syms.GOT
- r.Add += int64(targ.Got())
+ addgotsym2(target, ldr, syms, targ)
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_ARM64_GOT)
+ su.SetRelocSym(rIdx, syms.GOT2)
+ su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_PREL_PG_HI21),
objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADD_ABS_LO12_NC):
- if targ.Type == sym.SDYNIMPORT {
- ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ if targType == sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
}
- if targ.Type == 0 || targ.Type == sym.SXREF {
- ld.Errorf(s, "unknown symbol %s", targ.Name)
+ if targType == 0 || targType == sym.SXREF {
+ ldr.Errorf(s, "unknown symbol %s", ldr.SymName(targ))
}
- r.Type = objabi.R_ARM64_PCREL
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_ARM64_PCREL)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ABS64):
- if targ.Type == sym.SDYNIMPORT {
- ld.Errorf(s, "unexpected R_AARCH64_ABS64 relocation for dynamic symbol %s", targ.Name)
+ if targType == sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected R_AARCH64_ABS64 relocation for dynamic symbol %s", ldr.SymName(targ))
}
- r.Type = objabi.R_ADDR
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_ADDR)
if target.IsPIE() && target.IsInternal() {
// For internal linking PIE, this R_ADDR relocation cannot
// be resolved statically. We need to generate a dynamic
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST8_ABS_LO12_NC):
- if targ.Type == sym.SDYNIMPORT {
- ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ if targType == sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
}
- r.Type = objabi.R_ARM64_LDST8
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_ARM64_LDST8)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST32_ABS_LO12_NC):
- if targ.Type == sym.SDYNIMPORT {
- ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ if targType == sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
}
- r.Type = objabi.R_ARM64_LDST32
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_ARM64_LDST32)
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST64_ABS_LO12_NC):
- if targ.Type == sym.SDYNIMPORT {
- ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ if targType == sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
}
- r.Type = objabi.R_ARM64_LDST64
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_ARM64_LDST64)
+
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST128_ABS_LO12_NC):
- if targ.Type == sym.SDYNIMPORT {
- ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ if targType == sym.SDYNIMPORT {
+ ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
}
- r.Type = objabi.R_ARM64_LDST128
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocType(rIdx, objabi.R_ARM64_LDST128)
return true
}
- switch r.Type {
+ // Reread the reloc to incorporate any changes in type above.
+ relocs := ldr.Relocs(s)
+ *r = relocs.At2(rIdx)
+
+ switch r.Type() {
case objabi.R_CALL,
objabi.R_PCREL,
objabi.R_CALLARM64:
- if targ.Type != sym.SDYNIMPORT {
+ if targType != sym.SDYNIMPORT {
// nothing to do, the relocation will be laid out in reloc
return true
}
}
case objabi.R_ADDR:
- if s.Type == sym.STEXT && target.IsElf() {
+ if ldr.SymType(s) == sym.STEXT && target.IsElf() {
// The code is asking for the address of an external
// function. We provide it with the address of the
// correspondent GOT symbol.
- addgotsym(target, syms, targ)
-
- r.Sym = syms.GOT
- r.Add += int64(targ.Got())
+ addgotsym2(target, ldr, syms, targ)
+ su := ldr.MakeSymbolUpdater(s)
+ su.SetRelocSym(rIdx, syms.GOT2)
+ su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
return true
}
// symbol offset as determined by reloc(), not the
// final dynamically linked address as a dynamic
// relocation would provide.
- switch s.Name {
+ switch ldr.SymName(s) {
case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
return false
}
// linking, in which case the relocation will be
// prepared in the 'reloc' phase and passed to the
// external linker in the 'asmb' phase.
- if s.Type != sym.SDATA && s.Type != sym.SRODATA {
+ if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA {
break
}
}
// AddAddrPlus is used for r_offset and r_addend to
// generate new R_ADDR relocations that will update
// these fields in the 'reloc' phase.
- rela := syms.Rela
- rela.AddAddrPlus(target.Arch, s, int64(r.Off))
- if r.Siz == 8 {
+ rela := ldr.MakeSymbolUpdater(syms.Rela2)
+ rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
+ if r.Siz() == 8 {
rela.AddUint64(target.Arch, ld.ELF64_R_INFO(0, uint32(elf.R_AARCH64_RELATIVE)))
} else {
- ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
}
- rela.AddAddrPlus(target.Arch, targ, int64(r.Add))
+ rela.AddAddrPlus(target.Arch, targ, int64(r.Add()))
// Not mark r done here. So we still apply it statically,
// so in the file content we'll also have the right offset
// to the relocation target. So it can be examined statically
}
}
-func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
- if s.Plt() >= 0 {
+func addpltsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+ if ldr.SymPlt(s) >= 0 {
return
}
- ld.Adddynsym(target, syms, s)
+ ld.Adddynsym2(ldr, target, syms, s)
if target.IsElf() {
- plt := syms.PLT
- gotplt := syms.GOTPLT
- rela := syms.RelaPLT
- if plt.Size == 0 {
+ plt := ldr.MakeSymbolUpdater(syms.PLT2)
+ gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT2)
+ rela := ldr.MakeSymbolUpdater(syms.RelaPLT2)
+ if plt.Size() == 0 {
panic("plt is not set up")
}
// adrp x16, &got.plt[0]
- plt.AddAddrPlus4(gotplt, gotplt.Size)
- plt.SetUint32(target.Arch, plt.Size-4, 0x90000010)
- plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
+ plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
+ plt.SetUint32(target.Arch, plt.Size()-4, 0x90000010)
+ relocs := plt.Relocs()
+ plt.SetRelocType(relocs.Count()-1, objabi.R_ARM64_GOT)
// <offset> is the offset value of &got.plt[n] to &got.plt[0]
// ldr x17, [x16, <offset>]
- plt.AddAddrPlus4(gotplt, gotplt.Size)
- plt.SetUint32(target.Arch, plt.Size-4, 0xf9400211)
- plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
+ plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
+ plt.SetUint32(target.Arch, plt.Size()-4, 0xf9400211)
+ relocs = plt.Relocs()
+ plt.SetRelocType(relocs.Count()-1, objabi.R_ARM64_GOT)
// add x16, x16, <offset>
- plt.AddAddrPlus4(gotplt, gotplt.Size)
- plt.SetUint32(target.Arch, plt.Size-4, 0x91000210)
- plt.R[len(plt.R)-1].Type = objabi.R_ARM64_PCREL
+ plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
+ plt.SetUint32(target.Arch, plt.Size()-4, 0x91000210)
+ relocs = plt.Relocs()
+ plt.SetRelocType(relocs.Count()-1, objabi.R_ARM64_PCREL)
// br x17
plt.AddUint32(target.Arch, 0xd61f0220)
// add to got.plt: pointer to plt[0]
- gotplt.AddAddrPlus(target.Arch, plt, 0)
+ gotplt.AddAddrPlus(target.Arch, plt.Sym(), 0)
// rela
- rela.AddAddrPlus(target.Arch, gotplt, gotplt.Size-8)
- rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_JUMP_SLOT)))
+ rela.AddAddrPlus(target.Arch, gotplt.Sym(), gotplt.Size()-8)
+ sDynid := ldr.SymDynid(s)
+
+ rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(sDynid), uint32(elf.R_AARCH64_JUMP_SLOT)))
rela.AddUint64(target.Arch, 0)
- s.SetPlt(int32(plt.Size - 16))
+ ldr.SetPlt(s, int32(plt.Size()-16))
} else {
- ld.Errorf(s, "addpltsym: unsupported binary format")
+ ldr.Errorf(s, "addpltsym: unsupported binary format")
}
}
-func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
- if s.Got() >= 0 {
+func addgotsym2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+ if ldr.SymGot(s) >= 0 {
return
}
- ld.Adddynsym(target, syms, s)
- got := syms.GOT
- s.SetGot(int32(got.Size))
+ ld.Adddynsym2(ldr, target, syms, s)
+ got := ldr.MakeSymbolUpdater(syms.GOT2)
+ ldr.SetGot(s, int32(got.Size()))
got.AddUint64(target.Arch, 0)
if target.IsElf() {
- rela := syms.Rela
- rela.AddAddrPlus(target.Arch, got, int64(s.Got()))
- rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_GLOB_DAT)))
+ rela := ldr.MakeSymbolUpdater(syms.Rela2)
+ rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
+ rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_AARCH64_GLOB_DAT)))
rela.AddUint64(target.Arch, 0)
} else {
- ld.Errorf(s, "addgotsym: unsupported binary format")
+ ldr.Errorf(s, "addgotsym: unsupported binary format")
}
}
--- /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 arm64
+
+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 {
+ targ := r.Sym
+
+ 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_AARCH64_PREL32):
+ if targ.Type == sym.SDYNIMPORT {
+ ld.Errorf(s, "unexpected R_AARCH64_PREL32 relocation for dynamic symbol %s", targ.Name)
+ }
+ // TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
+ // sense and should be removed when someone has thought about it properly.
+ if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
+ ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
+ }
+ r.Type = objabi.R_PCREL
+ r.Add += 4
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_PREL64):
+ if targ.Type == sym.SDYNIMPORT {
+ ld.Errorf(s, "unexpected R_AARCH64_PREL64 relocation for dynamic symbol %s", targ.Name)
+ }
+ if targ.Type == 0 || targ.Type == sym.SXREF {
+ ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
+ }
+ r.Type = objabi.R_PCREL
+ r.Add += 8
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26):
+ if targ.Type == sym.SDYNIMPORT {
+ addpltsym(target, syms, targ)
+ r.Sym = syms.PLT
+ r.Add += int64(targ.Plt())
+ }
+ if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
+ ld.Errorf(s, "unknown symbol %s in callarm64", targ.Name)
+ }
+ r.Type = objabi.R_CALLARM64
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_GOT_PAGE),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LD64_GOT_LO12_NC):
+ if targ.Type != sym.SDYNIMPORT {
+ // have symbol
+ // TODO: turn LDR of GOT entry into ADR of symbol itself
+ }
+
+ // fall back to using GOT
+ // TODO: just needs relocation, no need to put in .dynsym
+ addgotsym(target, syms, targ)
+
+ r.Type = objabi.R_ARM64_GOT
+ r.Sym = syms.GOT
+ r.Add += int64(targ.Got())
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_PREL_PG_HI21),
+ objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADD_ABS_LO12_NC):
+ if targ.Type == sym.SDYNIMPORT {
+ ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ }
+ if targ.Type == 0 || targ.Type == sym.SXREF {
+ ld.Errorf(s, "unknown symbol %s", targ.Name)
+ }
+ r.Type = objabi.R_ARM64_PCREL
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ABS64):
+ if targ.Type == sym.SDYNIMPORT {
+ ld.Errorf(s, "unexpected R_AARCH64_ABS64 relocation for dynamic symbol %s", targ.Name)
+ }
+ r.Type = objabi.R_ADDR
+ if target.IsPIE() && target.IsInternal() {
+ // For internal linking PIE, this R_ADDR relocation cannot
+ // be resolved statically. We need to generate a dynamic
+ // relocation. Let the code below handle it.
+ break
+ }
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST8_ABS_LO12_NC):
+ if targ.Type == sym.SDYNIMPORT {
+ ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ }
+ r.Type = objabi.R_ARM64_LDST8
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST32_ABS_LO12_NC):
+ if targ.Type == sym.SDYNIMPORT {
+ ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ }
+ r.Type = objabi.R_ARM64_LDST32
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST64_ABS_LO12_NC):
+ if targ.Type == sym.SDYNIMPORT {
+ ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ }
+ r.Type = objabi.R_ARM64_LDST64
+ return true
+
+ case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST128_ABS_LO12_NC):
+ if targ.Type == sym.SDYNIMPORT {
+ ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ }
+ r.Type = objabi.R_ARM64_LDST128
+ return true
+ }
+
+ switch r.Type {
+ case objabi.R_CALL,
+ objabi.R_PCREL,
+ objabi.R_CALLARM64:
+ if targ.Type != sym.SDYNIMPORT {
+ // nothing to do, the relocation will be laid out in reloc
+ return true
+ }
+ if target.IsExternal() {
+ // External linker will do this relocation.
+ return true
+ }
+
+ case objabi.R_ADDR:
+ if s.Type == sym.STEXT && target.IsElf() {
+ // The code is asking for the address of an external
+ // function. We provide it with the address of the
+ // correspondent GOT symbol.
+ addgotsym(target, syms, targ)
+
+ r.Sym = syms.GOT
+ r.Add += int64(targ.Got())
+ return true
+ }
+
+ // Process dynamic relocations for the data sections.
+ if target.IsPIE() && target.IsInternal() {
+ // When internally linking, generate dynamic relocations
+ // for all typical R_ADDR relocations. The exception
+ // are those R_ADDR that are created as part of generating
+ // the dynamic relocations and must be resolved statically.
+ //
+ // There are three phases relevant to understanding this:
+ //
+ // dodata() // we are here
+ // address() // symbol address assignment
+ // reloc() // resolution of static R_ADDR relocs
+ //
+ // At this point symbol addresses have not been
+ // assigned yet (as the final size of the .rela section
+ // will affect the addresses), and so we cannot write
+ // the Elf64_Rela.r_offset now. Instead we delay it
+ // until after the 'address' phase of the linker is
+ // complete. We do this via Addaddrplus, which creates
+ // a new R_ADDR relocation which will be resolved in
+ // the 'reloc' phase.
+ //
+ // These synthetic static R_ADDR relocs must be skipped
+ // now, or else we will be caught in an infinite loop
+ // of generating synthetic relocs for our synthetic
+ // relocs.
+ //
+ // Furthermore, the rela sections contain dynamic
+ // relocations with R_ADDR relocations on
+ // Elf64_Rela.r_offset. This field should contain the
+ // symbol offset as determined by reloc(), not the
+ // final dynamically linked address as a dynamic
+ // relocation would provide.
+ switch s.Name {
+ case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
+ return false
+ }
+ } else {
+ // Either internally linking a static executable,
+ // in which case we can resolve these relocations
+ // statically in the 'reloc' phase, or externally
+ // linking, in which case the relocation will be
+ // prepared in the 'reloc' phase and passed to the
+ // external linker in the 'asmb' phase.
+ if s.Type != sym.SDATA && s.Type != sym.SRODATA {
+ break
+ }
+ }
+
+ if target.IsElf() {
+ // Generate R_AARCH64_RELATIVE relocations for best
+ // efficiency in the dynamic linker.
+ //
+ // As noted above, symbol addresses have not been
+ // assigned yet, so we can't generate the final reloc
+ // entry yet. We ultimately want:
+ //
+ // r_offset = s + r.Off
+ // r_info = R_AARCH64_RELATIVE
+ // r_addend = targ + r.Add
+ //
+ // The dynamic linker will set *offset = base address +
+ // addend.
+ //
+ // AddAddrPlus is used for r_offset and r_addend to
+ // generate new R_ADDR relocations that will update
+ // these fields in the 'reloc' phase.
+ rela := syms.Rela
+ rela.AddAddrPlus(target.Arch, s, int64(r.Off))
+ if r.Siz == 8 {
+ rela.AddUint64(target.Arch, ld.ELF64_R_INFO(0, uint32(elf.R_AARCH64_RELATIVE)))
+ } else {
+ ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
+ }
+ rela.AddAddrPlus(target.Arch, targ, int64(r.Add))
+ // Not mark r done here. So we still apply it statically,
+ // so in the file content we'll also have the right offset
+ // to the relocation target. So it can be examined statically
+ // (e.g. go version).
+ return true
+ }
+ }
+ return false
+}
+func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
+ if s.Plt() >= 0 {
+ return
+ }
+
+ ld.Adddynsym(target, syms, s)
+
+ if target.IsElf() {
+ plt := syms.PLT
+ gotplt := syms.GOTPLT
+ rela := syms.RelaPLT
+ if plt.Size == 0 {
+ panic("plt is not set up")
+ }
+
+ // adrp x16, &got.plt[0]
+ plt.AddAddrPlus4(gotplt, gotplt.Size)
+ plt.SetUint32(target.Arch, plt.Size-4, 0x90000010)
+ plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
+
+ // <offset> is the offset value of &got.plt[n] to &got.plt[0]
+ // ldr x17, [x16, <offset>]
+ plt.AddAddrPlus4(gotplt, gotplt.Size)
+ plt.SetUint32(target.Arch, plt.Size-4, 0xf9400211)
+ plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
+
+ // add x16, x16, <offset>
+ plt.AddAddrPlus4(gotplt, gotplt.Size)
+ plt.SetUint32(target.Arch, plt.Size-4, 0x91000210)
+ plt.R[len(plt.R)-1].Type = objabi.R_ARM64_PCREL
+
+ // br x17
+ plt.AddUint32(target.Arch, 0xd61f0220)
+
+ // add to got.plt: pointer to plt[0]
+ gotplt.AddAddrPlus(target.Arch, plt, 0)
+
+ // rela
+ rela.AddAddrPlus(target.Arch, gotplt, gotplt.Size-8)
+ rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_JUMP_SLOT)))
+ rela.AddUint64(target.Arch, 0)
+
+ s.SetPlt(int32(plt.Size - 16))
+ } else {
+ ld.Errorf(s, "addpltsym: unsupported binary format")
+ }
+}
+
+func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
+ if s.Got() >= 0 {
+ return
+ }
+
+ ld.Adddynsym(target, syms, s)
+ got := syms.GOT
+ s.SetGot(int32(got.Size))
+ got.AddUint64(target.Arch, 0)
+
+ if target.IsElf() {
+ rela := syms.Rela
+ rela.AddAddrPlus(target.Arch, got, int64(s.Got()))
+ rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_GLOB_DAT)))
+ rela.AddUint64(target.Arch, 0)
+ } else {
+ ld.Errorf(s, "addgotsym: unsupported binary format")
+ }
+}
Dwarfreglr: dwarfRegLR,
Adddynrel: adddynrel,
+ Adddynrel2: adddynrel2,
Archinit: archinit,
Archreloc: archreloc,
Archrelocvariant: archrelocvariant,
// New dodata() is currently only implemented for selected targets.
switch {
case ctxt.IsElf():
- if !(ctxt.IsAMD64() || ctxt.Is386()) {
+ if !(ctxt.IsAMD64() || ctxt.Is386() ||
+ ctxt.IsARM() || ctxt.IsARM64()) {
*flagnewDoData = false
}
case ctxt.IsDarwin():
return t.Arch.Family == sys.ARM
}
+func (t *Target) IsARM64() bool {
+ return t.Arch.Family == sys.ARM64
+}
+
func (t *Target) IsAMD64() bool {
return t.Arch.Family == sys.AMD64
}