]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: support new dodata for elf/{arm,arm64}
authorThan McIntosh <thanm@google.com>
Fri, 24 Apr 2020 15:01:10 +0000 (11:01 -0400)
committerThan McIntosh <thanm@google.com>
Mon, 27 Apr 2020 13:38:54 +0000 (13:38 +0000)
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>
src/cmd/link/internal/arm/asm.go
src/cmd/link/internal/arm/asm2.go [new file with mode: 0644]
src/cmd/link/internal/arm/obj.go
src/cmd/link/internal/arm64/asm.go
src/cmd/link/internal/arm64/asm2.go [new file with mode: 0644]
src/cmd/link/internal/arm64/obj.go
src/cmd/link/internal/ld/main.go
src/cmd/link/internal/ld/target.go

index 446691f31856ea8e0f11b0f954aefecc2fa1bd13..e1edc9e45da66c761c35b132b1cf30371cea1bc4 100644 (file)
@@ -103,24 +103,30 @@ func braddoff(a int32, b int32) int32 {
        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
@@ -130,113 +136,112 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.
                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
                }
        }
@@ -592,90 +597,88 @@ func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym
        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")
        }
 }
 
diff --git a/src/cmd/link/internal/arm/asm2.go b/src/cmd/link/internal/arm/asm2.go
new file mode 100644 (file)
index 0000000..a8c26c6
--- /dev/null
@@ -0,0 +1,246 @@
+// 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")
+       }
+}
index b277fb2a43a2bd0c0dc8cafd3aebe512baf2205d..d6fa64de667859a6176f1445aa7a34302f528a58 100644 (file)
@@ -47,6 +47,7 @@ func Init() (*sys.Arch, ld.Arch) {
                Dwarfreglr: dwarfRegLR,
 
                Adddynrel:        adddynrel,
+               Adddynrel2:       adddynrel2,
                Archinit:         archinit,
                Archreloc:        archreloc,
                Archrelocvariant: archrelocvariant,
index 46bda74c4c5118b3d4c8c36c6e07871a6015257c..a0f06b6aa67aaebae214d4b5a19381ead36fdf1d 100644 (file)
@@ -78,86 +78,97 @@ func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
        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
@@ -167,39 +178,48 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.
                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
                }
@@ -209,14 +229,14 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.
                }
 
        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
                }
 
@@ -253,7 +273,7 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.
                        // 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
                        }
@@ -264,7 +284,7 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.
                        // 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
                        }
                }
@@ -287,14 +307,14 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.
                        // 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
@@ -737,71 +757,76 @@ func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loade
        }
 }
 
-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")
        }
 }
 
diff --git a/src/cmd/link/internal/arm64/asm2.go b/src/cmd/link/internal/arm64/asm2.go
new file mode 100644 (file)
index 0000000..b093958
--- /dev/null
@@ -0,0 +1,312 @@
+// 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")
+       }
+}
index c2ac6e7ad19054fad7202e429e225faf4bac950c..1895fbe0c2504c0c26fc0bda9824705d2958da8f 100644 (file)
@@ -47,6 +47,7 @@ func Init() (*sys.Arch, ld.Arch) {
                Dwarfreglr: dwarfRegLR,
 
                Adddynrel:        adddynrel,
+               Adddynrel2:       adddynrel2,
                Archinit:         archinit,
                Archreloc:        archreloc,
                Archrelocvariant: archrelocvariant,
index 96860ce4d8be2dfcfbb0712fa64a0ce55bacd381..8744291d71cad9a3b3e263a9471a61a0c47e146c 100644 (file)
@@ -204,7 +204,8 @@ func Main(arch *sys.Arch, theArch Arch) {
                // 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():
index 8c07d77fd880222eb9d9abd015d7a07f5478d3bf..78e41f09be614993dd74ba051789bd8d87475286 100644 (file)
@@ -92,6 +92,10 @@ func (t *Target) IsARM() bool {
        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
 }