From a3e965ce8addeb6a0b690069522a0487f68ee316 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 11 Mar 2020 12:12:41 -0400 Subject: [PATCH] [dev.link] cmd/link: convert doelf to new style Change-Id: I448fe632ae73ddcb79c05793c96f48e358060305 Reviewed-on: https://go-review.googlesource.com/c/go/+/222977 Reviewed-by: Than McIntosh --- src/cmd/link/internal/amd64/asm.go | 15 +- src/cmd/link/internal/arm/asm.go | 11 +- src/cmd/link/internal/arm64/asm.go | 30 +- src/cmd/link/internal/ld/dwarf2.go | 11 +- src/cmd/link/internal/ld/elf.go | 335 ++++++++++-------- src/cmd/link/internal/ld/lib.go | 2 +- src/cmd/link/internal/ld/main.go | 4 +- src/cmd/link/internal/ld/target.go | 8 + src/cmd/link/internal/loader/symbolbuilder.go | 32 +- src/cmd/link/internal/mips/asm.go | 3 +- src/cmd/link/internal/mips64/asm.go | 3 +- src/cmd/link/internal/ppc64/asm.go | 10 +- src/cmd/link/internal/riscv64/asm.go | 3 +- src/cmd/link/internal/s390x/asm.go | 13 +- src/cmd/link/internal/x86/asm.go | 15 +- 15 files changed, 278 insertions(+), 217 deletions(-) diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index 34eb6f1001..06c4a362a9 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -34,6 +34,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "debug/elf" "log" @@ -572,27 +573,25 @@ func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym return t } -func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { - plt := ctxt.Syms.Lookup(".plt", 0) - got := ctxt.Syms.Lookup(".got.plt", 0) - if plt.Size == 0 { +func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) { + if plt.Size() == 0 { // pushq got+8(IP) plt.AddUint8(0xff) plt.AddUint8(0x35) - plt.AddPCRelPlus(ctxt.Arch, got, 8) + plt.AddPCRelPlus(ctxt.Arch, got.Sym(), 8) // jmpq got+16(IP) plt.AddUint8(0xff) plt.AddUint8(0x25) - plt.AddPCRelPlus(ctxt.Arch, got, 16) + plt.AddPCRelPlus(ctxt.Arch, got.Sym(), 16) // nopl 0(AX) plt.AddUint32(ctxt.Arch, 0x00401f0f) // assume got->size == 0 too - got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0) + got.AddAddrPlus(ctxt.Arch, dynamic, 0) got.AddUint64(ctxt.Arch, 0) got.AddUint64(ctxt.Arch, 0) @@ -611,7 +610,7 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) { got := ctxt.Syms.Lookup(".got.plt", 0) rela := ctxt.Syms.Lookup(".rela.plt", 0) if plt.Size == 0 { - elfsetupplt(ctxt, &ctxt.Target, &ctxt.ArchSyms) + panic("plt is not set up") } // jmpq *got+size(IP) diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go index 56c0a5c664..e4a52e5589 100644 --- a/src/cmd/link/internal/arm/asm.go +++ b/src/cmd/link/internal/arm/asm.go @@ -34,6 +34,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "debug/elf" "fmt" @@ -300,10 +301,8 @@ func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool { return true } -func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { - plt := ctxt.Syms.Lookup(".plt", 0) - got := ctxt.Syms.Lookup(".got.plt", 0) - if plt.Size == 0 { +func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) { + if plt.Size() == 0 { // str lr, [sp, #-4]! plt.AddUint32(ctxt.Arch, 0xe52de004) @@ -317,7 +316,7 @@ func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { plt.AddUint32(ctxt.Arch, 0xe5bef008) // .word &GLOBAL_OFFSET_TABLE[0] - . - plt.AddPCRelPlus(ctxt.Arch, got, 4) + plt.AddPCRelPlus(ctxt.Arch, got.Sym(), 4) // the first .plt entry requires 3 .plt.got entries got.AddUint32(ctxt.Arch, 0) @@ -697,7 +696,7 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) { got := ctxt.Syms.Lookup(".got.plt", 0) rel := ctxt.Syms.Lookup(".rel.plt", 0) if plt.Size == 0 { - elfsetupplt(ctxt, &ctxt.Target, &ctxt.ArchSyms) + panic("plt is not set up") } // .got entry diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index 0e5da99b97..0b4ecd6c5f 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -34,6 +34,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "debug/elf" "fmt" @@ -711,30 +712,25 @@ func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym return -1 } -func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { - plt := ctxt.Syms.Lookup(".plt", 0) - gotplt := ctxt.Syms.Lookup(".got.plt", 0) - if plt.Size == 0 { +func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) { + if plt.Size() == 0 { // stp x16, x30, [sp, #-16]! // identifying information plt.AddUint32(ctxt.Arch, 0xa9bf7bf0) // the following two instructions (adrp + ldr) load *got[2] into x17 // adrp x16, &got[0] - plt.AddAddrPlus4(gotplt, 16) - plt.SetUint32(ctxt.Arch, plt.Size-4, 0x90000010) - plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT + plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 16, objabi.R_ARM64_GOT, 4) + plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x90000010) // is the offset value of &got[2] to &got[0], the same below // ldr x17, [x16, ] - plt.AddAddrPlus4(gotplt, 16) - plt.SetUint32(ctxt.Arch, plt.Size-4, 0xf9400211) - plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT + plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 16, objabi.R_ARM64_GOT, 4) + plt.SetUint32(ctxt.Arch, plt.Size()-4, 0xf9400211) // add x16, x16, - plt.AddAddrPlus4(gotplt, 16) - plt.SetUint32(ctxt.Arch, plt.Size-4, 0x91000210) - plt.R[len(plt.R)-1].Type = objabi.R_ARM64_PCREL + plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 16, objabi.R_ARM64_PCREL, 4) + plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x91000210) // br x17 plt.AddUint32(ctxt.Arch, 0xd61f0220) @@ -745,10 +741,10 @@ func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { plt.AddUint32(ctxt.Arch, 0xd503201f) // check gotplt.size == 0 - if gotplt.Size != 0 { - ld.Errorf(gotplt, "got.plt is not empty at the very beginning") + if gotplt.Size() != 0 { + ctxt.Errorf(gotplt.Sym(), "got.plt is not empty at the very beginning") } - gotplt.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0) + gotplt.AddAddrPlus(ctxt.Arch, dynamic, 0) gotplt.AddUint64(ctxt.Arch, 0) gotplt.AddUint64(ctxt.Arch, 0) @@ -767,7 +763,7 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) { gotplt := ctxt.Syms.Lookup(".got.plt", 0) rela := ctxt.Syms.Lookup(".rela.plt", 0) if plt.Size == 0 { - elfsetupplt(ctxt, &ctxt.Target, &ctxt.ArchSyms) + panic("plt is not set up") } // adrp x16, &got.plt[0] diff --git a/src/cmd/link/internal/ld/dwarf2.go b/src/cmd/link/internal/ld/dwarf2.go index ac971849b4..233cd6a784 100644 --- a/src/cmd/link/internal/ld/dwarf2.go +++ b/src/cmd/link/internal/ld/dwarf2.go @@ -15,6 +15,7 @@ package ld import ( "cmd/internal/objabi" + "cmd/link/internal/loader" "cmd/link/internal/sym" "log" ) @@ -28,18 +29,18 @@ var dwarfp []*sym.Symbol /* * Elf. */ -func dwarfaddshstrings(ctxt *Link, shstrtab *sym.Symbol) { +func dwarfaddshstrings(ctxt *Link, shstrtab *loader.SymbolBuilder) { if *FlagW { // disable dwarf return } secs := []string{"abbrev", "frame", "info", "loc", "line", "pubnames", "pubtypes", "gdb_scripts", "ranges"} for _, sec := range secs { - Addstring(shstrtab, ".debug_"+sec) - if ctxt.LinkMode == LinkExternal { - Addstring(shstrtab, elfRelType+".debug_"+sec) + shstrtab.Addstring(".debug_" + sec) + if ctxt.IsExternal() { + shstrtab.Addstring(elfRelType + ".debug_" + sec) } else { - Addstring(shstrtab, ".zdebug_"+sec) + shstrtab.Addstring(".zdebug_" + sec) } } } diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index 6146bed284..b071089254 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -7,6 +7,7 @@ package ld import ( "cmd/internal/objabi" "cmd/internal/sys" + "cmd/link/internal/loader" "cmd/link/internal/sym" "crypto/sha1" "encoding/binary" @@ -774,6 +775,39 @@ func elfWriteDynEntSymSize(arch *sys.Arch, s *sym.Symbol, tag int, t *sym.Symbol s.AddSize(arch, t) } +// temporary +func Elfwritedynent2(ctxt *Link, s *loader.SymbolBuilder, tag int, val uint64) { + if elf64 { + s.AddUint64(ctxt.Arch, uint64(tag)) + s.AddUint64(ctxt.Arch, val) + } else { + s.AddUint32(ctxt.Arch, uint32(tag)) + s.AddUint32(ctxt.Arch, uint32(val)) + } +} + +func elfwritedynentsym2(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym) { + Elfwritedynentsymplus2(ctxt, s, tag, t, 0) +} + +func Elfwritedynentsymplus2(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym, add int64) { + if elf64 { + s.AddUint64(ctxt.Arch, uint64(tag)) + } else { + s.AddUint32(ctxt.Arch, uint32(tag)) + } + s.AddAddrPlus(ctxt.Arch, t, add) +} + +func elfwritedynentsymsize2(ctxt *Link, s *loader.SymbolBuilder, tag int, t loader.Sym) { + if elf64 { + s.AddUint64(ctxt.Arch, uint64(tag)) + } else { + s.AddUint32(ctxt.Arch, uint32(tag)) + } + s.AddSize(ctxt.Arch, t) +} + func elfinterp(sh *ElfShdr, startva uint64, resoff uint64, p string) int { interp = p n := len(interp) + 1 @@ -1400,9 +1434,10 @@ func Elfemitreloc(ctxt *Link) { } func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) { - s := ctxt.Syms.Lookup(sectionName, 0) - s.Attr |= sym.AttrReachable - s.Type = sym.SELFROSECT + ldr := ctxt.loader + s := ldr.CreateSymForUpdate(sectionName, 0) + s.SetReachable(true) + s.SetType(sym.SELFROSECT) // namesz s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME))) // descsz @@ -1410,93 +1445,91 @@ func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) { // tag s.AddUint32(ctxt.Arch, tag) // name + padding - s.P = append(s.P, ELF_NOTE_GO_NAME...) - for len(s.P)%4 != 0 { - s.P = append(s.P, 0) + s.AddBytes(ELF_NOTE_GO_NAME) + for len(s.Data())%4 != 0 { + s.AddUint8(0) } // desc + padding - s.P = append(s.P, desc...) - for len(s.P)%4 != 0 { - s.P = append(s.P, 0) + s.AddBytes(desc) + for len(s.Data())%4 != 0 { + s.AddUint8(0) } - s.Size = int64(len(s.P)) - s.Align = 4 + s.SetSize(int64(len(s.Data()))) + s.SetAlign(4) } func (ctxt *Link) doelf() { - if !ctxt.IsELF { - return - } + ldr := ctxt.loader /* predefine strings we need for section headers */ - shstrtab := ctxt.Syms.Lookup(".shstrtab", 0) + shstrtab := ldr.CreateSymForUpdate(".shstrtab", 0) - shstrtab.Type = sym.SELFROSECT - shstrtab.Attr |= sym.AttrReachable + shstrtab.SetType(sym.SELFROSECT) + shstrtab.SetReachable(true) - Addstring(shstrtab, "") - Addstring(shstrtab, ".text") - Addstring(shstrtab, ".noptrdata") - Addstring(shstrtab, ".data") - Addstring(shstrtab, ".bss") - Addstring(shstrtab, ".noptrbss") - Addstring(shstrtab, "__libfuzzer_extra_counters") - Addstring(shstrtab, ".go.buildinfo") + shstrtab.Addstring("") + shstrtab.Addstring(".text") + shstrtab.Addstring(".noptrdata") + shstrtab.Addstring(".data") + shstrtab.Addstring(".bss") + shstrtab.Addstring(".noptrbss") + shstrtab.Addstring("__libfuzzer_extra_counters") + shstrtab.Addstring(".go.buildinfo") // generate .tbss section for dynamic internal linker or external // linking, so that various binutils could correctly calculate // PT_TLS size. See https://golang.org/issue/5200. - if !*FlagD || ctxt.LinkMode == LinkExternal { - Addstring(shstrtab, ".tbss") + if !*FlagD || ctxt.IsExternal() { + shstrtab.Addstring(".tbss") } - if ctxt.HeadType == objabi.Hnetbsd { - Addstring(shstrtab, ".note.netbsd.ident") + if ctxt.IsNetbsd() { + shstrtab.Addstring(".note.netbsd.ident") } - if ctxt.HeadType == objabi.Hopenbsd { - Addstring(shstrtab, ".note.openbsd.ident") + if ctxt.IsOpenbsd() { + shstrtab.Addstring(".note.openbsd.ident") } if len(buildinfo) > 0 { - Addstring(shstrtab, ".note.gnu.build-id") + shstrtab.Addstring(".note.gnu.build-id") } if *flagBuildid != "" { - Addstring(shstrtab, ".note.go.buildid") + shstrtab.Addstring(".note.go.buildid") } - Addstring(shstrtab, ".elfdata") - Addstring(shstrtab, ".rodata") + shstrtab.Addstring(".elfdata") + shstrtab.Addstring(".rodata") // See the comment about data.rel.ro.FOO section names in data.go. relro_prefix := "" if ctxt.UseRelro() { - Addstring(shstrtab, ".data.rel.ro") + shstrtab.Addstring(".data.rel.ro") relro_prefix = ".data.rel.ro" } - Addstring(shstrtab, relro_prefix+".typelink") - Addstring(shstrtab, relro_prefix+".itablink") - Addstring(shstrtab, relro_prefix+".gosymtab") - Addstring(shstrtab, relro_prefix+".gopclntab") + shstrtab.Addstring(relro_prefix + ".typelink") + shstrtab.Addstring(relro_prefix + ".itablink") + shstrtab.Addstring(relro_prefix + ".gosymtab") + shstrtab.Addstring(relro_prefix + ".gopclntab") - if ctxt.LinkMode == LinkExternal { + if ctxt.IsExternal() { *FlagD = true - Addstring(shstrtab, elfRelType+".text") - Addstring(shstrtab, elfRelType+".rodata") - Addstring(shstrtab, elfRelType+relro_prefix+".typelink") - Addstring(shstrtab, elfRelType+relro_prefix+".itablink") - Addstring(shstrtab, elfRelType+relro_prefix+".gosymtab") - Addstring(shstrtab, elfRelType+relro_prefix+".gopclntab") - Addstring(shstrtab, elfRelType+".noptrdata") - Addstring(shstrtab, elfRelType+".data") + shstrtab.Addstring(elfRelType + ".text") + shstrtab.Addstring(elfRelType + ".rodata") + shstrtab.Addstring(elfRelType + relro_prefix + ".typelink") + shstrtab.Addstring(elfRelType + relro_prefix + ".itablink") + shstrtab.Addstring(elfRelType + relro_prefix + ".gosymtab") + shstrtab.Addstring(elfRelType + relro_prefix + ".gopclntab") + shstrtab.Addstring(elfRelType + ".noptrdata") + shstrtab.Addstring(elfRelType + ".data") if ctxt.UseRelro() { - Addstring(shstrtab, elfRelType+".data.rel.ro") + shstrtab.Addstring(elfRelType + ".data.rel.ro") } - Addstring(shstrtab, elfRelType+".go.buildinfo") + shstrtab.Addstring(elfRelType + ".go.buildinfo") // add a .note.GNU-stack section to mark the stack as non-executable - Addstring(shstrtab, ".note.GNU-stack") + shstrtab.Addstring(".note.GNU-stack") - if ctxt.BuildMode == BuildModeShared { - Addstring(shstrtab, ".note.go.abihash") - Addstring(shstrtab, ".note.go.pkg-list") - Addstring(shstrtab, ".note.go.deps") + if ctxt.IsShared() { + shstrtab.Addstring(".note.go.abihash") + shstrtab.Addstring(".note.go.pkg-list") + shstrtab.Addstring(".note.go.deps") } } @@ -1509,171 +1542,169 @@ func (ctxt *Link) doelf() { } if hasinitarr { - Addstring(shstrtab, ".init_array") - Addstring(shstrtab, elfRelType+".init_array") + shstrtab.Addstring(".init_array") + shstrtab.Addstring(elfRelType + ".init_array") } if !*FlagS { - Addstring(shstrtab, ".symtab") - Addstring(shstrtab, ".strtab") + shstrtab.Addstring(".symtab") + shstrtab.Addstring(".strtab") dwarfaddshstrings(ctxt, shstrtab) } - Addstring(shstrtab, ".shstrtab") + shstrtab.Addstring(".shstrtab") if !*FlagD { /* -d suppresses dynamic loader format */ - Addstring(shstrtab, ".interp") - Addstring(shstrtab, ".hash") - Addstring(shstrtab, ".got") - if ctxt.Arch.Family == sys.PPC64 { - Addstring(shstrtab, ".glink") + shstrtab.Addstring(".interp") + shstrtab.Addstring(".hash") + shstrtab.Addstring(".got") + if ctxt.IsPPC64() { + shstrtab.Addstring(".glink") } - Addstring(shstrtab, ".got.plt") - Addstring(shstrtab, ".dynamic") - Addstring(shstrtab, ".dynsym") - Addstring(shstrtab, ".dynstr") - Addstring(shstrtab, elfRelType) - Addstring(shstrtab, elfRelType+".plt") + shstrtab.Addstring(".got.plt") + shstrtab.Addstring(".dynamic") + shstrtab.Addstring(".dynsym") + shstrtab.Addstring(".dynstr") + shstrtab.Addstring(elfRelType) + shstrtab.Addstring(elfRelType + ".plt") - Addstring(shstrtab, ".plt") - Addstring(shstrtab, ".gnu.version") - Addstring(shstrtab, ".gnu.version_r") + shstrtab.Addstring(".plt") + shstrtab.Addstring(".gnu.version") + shstrtab.Addstring(".gnu.version_r") /* dynamic symbol table - first entry all zeros */ - s := ctxt.Syms.Lookup(".dynsym", 0) + dynsym := ldr.CreateSymForUpdate(".dynsym", 0) - s.Type = sym.SELFROSECT - s.Attr |= sym.AttrReachable + dynsym.SetType(sym.SELFROSECT) + dynsym.SetReachable(true) if elf64 { - s.Size += ELF64SYMSIZE + dynsym.SetSize(dynsym.Size() + ELF64SYMSIZE) } else { - s.Size += ELF32SYMSIZE + dynsym.SetSize(dynsym.Size() + ELF32SYMSIZE) } /* dynamic string table */ - s = ctxt.Syms.Lookup(".dynstr", 0) + dynstr := ldr.CreateSymForUpdate(".dynstr", 0) - s.Type = sym.SELFROSECT - s.Attr |= sym.AttrReachable - if s.Size == 0 { - Addstring(s, "") + dynstr.SetType(sym.SELFROSECT) + dynstr.SetReachable(true) + if dynstr.Size() == 0 { + dynstr.Addstring("") } - dynstr := s /* relocation table */ - s = ctxt.Syms.Lookup(elfRelType, 0) - s.Attr |= sym.AttrReachable - s.Type = sym.SELFROSECT + s := ldr.CreateSymForUpdate(elfRelType, 0) + s.SetReachable(true) + s.SetType(sym.SELFROSECT) /* global offset table */ - s = ctxt.Syms.Lookup(".got", 0) - - s.Attr |= sym.AttrReachable - s.Type = sym.SELFGOT // writable + got := ldr.CreateSymForUpdate(".got", 0) + got.SetReachable(true) + got.SetType(sym.SELFGOT) // writable /* ppc64 glink resolver */ - if ctxt.Arch.Family == sys.PPC64 { - s := ctxt.Syms.Lookup(".glink", 0) - s.Attr |= sym.AttrReachable - s.Type = sym.SELFRXSECT + if ctxt.IsPPC64() { + s := ldr.CreateSymForUpdate(".glink", 0) + s.SetReachable(true) + s.SetType(sym.SELFRXSECT) } /* hash */ - s = ctxt.Syms.Lookup(".hash", 0) + hash := ldr.CreateSymForUpdate(".hash", 0) + hash.SetReachable(true) + hash.SetType(sym.SELFROSECT) - s.Attr |= sym.AttrReachable - s.Type = sym.SELFROSECT + gotplt := ldr.CreateSymForUpdate(".got.plt", 0) + gotplt.SetReachable(true) + gotplt.SetType(sym.SELFSECT) // writable - s = ctxt.Syms.Lookup(".got.plt", 0) - s.Attr |= sym.AttrReachable - s.Type = sym.SELFSECT // writable - - s = ctxt.Syms.Lookup(".plt", 0) - - s.Attr |= sym.AttrReachable - if ctxt.Arch.Family == sys.PPC64 { + plt := ldr.CreateSymForUpdate(".plt", 0) + plt.SetReachable(true) + if ctxt.IsPPC64() { // In the ppc64 ABI, .plt is a data section // written by the dynamic linker. - s.Type = sym.SELFSECT + plt.SetType(sym.SELFSECT) } else { - s.Type = sym.SELFRXSECT + plt.SetType(sym.SELFRXSECT) } - thearch.Elfsetupplt(ctxt, &ctxt.Target, &ctxt.ArchSyms) + s = ldr.CreateSymForUpdate(elfRelType+".plt", 0) + s.SetReachable(true) + s.SetType(sym.SELFROSECT) - s = ctxt.Syms.Lookup(elfRelType+".plt", 0) - s.Attr |= sym.AttrReachable - s.Type = sym.SELFROSECT + s = ldr.CreateSymForUpdate(".gnu.version", 0) + s.SetReachable(true) + s.SetType(sym.SELFROSECT) - s = ctxt.Syms.Lookup(".gnu.version", 0) - s.Attr |= sym.AttrReachable - s.Type = sym.SELFROSECT - - s = ctxt.Syms.Lookup(".gnu.version_r", 0) - s.Attr |= sym.AttrReachable - s.Type = sym.SELFROSECT + s = ldr.CreateSymForUpdate(".gnu.version_r", 0) + s.SetReachable(true) + s.SetType(sym.SELFROSECT) /* define dynamic elf table */ - s = ctxt.Syms.Lookup(".dynamic", 0) + dynamic := ldr.CreateSymForUpdate(".dynamic", 0) + dynamic.SetReachable(true) + dynamic.SetType(sym.SELFSECT) // writable - s.Attr |= sym.AttrReachable - s.Type = sym.SELFSECT // writable + thearch.Elfsetupplt(ctxt, plt, gotplt, dynamic.Sym()) /* * .dynamic table */ - elfWriteDynEntSym(ctxt.Arch, s, DT_HASH, ctxt.Syms.Lookup(".hash", 0)) + elfwritedynentsym2(ctxt, dynamic, DT_HASH, hash.Sym()) - elfWriteDynEntSym(ctxt.Arch, s, DT_SYMTAB, ctxt.Syms.Lookup(".dynsym", 0)) + elfwritedynentsym2(ctxt, dynamic, DT_SYMTAB, dynsym.Sym()) if elf64 { - elfWriteDynEnt(ctxt.Arch, s, DT_SYMENT, ELF64SYMSIZE) + Elfwritedynent2(ctxt, dynamic, DT_SYMENT, ELF64SYMSIZE) } else { - elfWriteDynEnt(ctxt.Arch, s, DT_SYMENT, ELF32SYMSIZE) + Elfwritedynent2(ctxt, dynamic, DT_SYMENT, ELF32SYMSIZE) } - elfWriteDynEntSym(ctxt.Arch, s, DT_STRTAB, ctxt.Syms.Lookup(".dynstr", 0)) - elfWriteDynEntSymSize(ctxt.Arch, s, DT_STRSZ, ctxt.Syms.Lookup(".dynstr", 0)) + elfwritedynentsym2(ctxt, dynamic, DT_STRTAB, dynstr.Sym()) + elfwritedynentsymsize2(ctxt, dynamic, DT_STRSZ, dynstr.Sym()) if elfRelType == ".rela" { - elfWriteDynEntSym(ctxt.Arch, s, DT_RELA, ctxt.Syms.Lookup(".rela", 0)) - elfWriteDynEntSymSize(ctxt.Arch, s, DT_RELASZ, ctxt.Syms.Lookup(".rela", 0)) - elfWriteDynEnt(ctxt.Arch, s, DT_RELAENT, ELF64RELASIZE) + rela := ldr.LookupOrCreateSym(".rela", 0) + elfwritedynentsym2(ctxt, dynamic, DT_RELA, rela) + elfwritedynentsymsize2(ctxt, dynamic, DT_RELASZ, rela) + Elfwritedynent2(ctxt, dynamic, DT_RELAENT, ELF64RELASIZE) } else { - elfWriteDynEntSym(ctxt.Arch, s, DT_REL, ctxt.Syms.Lookup(".rel", 0)) - elfWriteDynEntSymSize(ctxt.Arch, s, DT_RELSZ, ctxt.Syms.Lookup(".rel", 0)) - elfWriteDynEnt(ctxt.Arch, s, DT_RELENT, ELF32RELSIZE) + rel := ldr.LookupOrCreateSym(".rel", 0) + elfwritedynentsym2(ctxt, dynamic, DT_REL, rel) + elfwritedynentsymsize2(ctxt, dynamic, DT_RELSZ, rel) + Elfwritedynent2(ctxt, dynamic, DT_RELENT, ELF32RELSIZE) } if rpath.val != "" { - elfWriteDynEnt(ctxt.Arch, s, DT_RUNPATH, uint64(Addstring(dynstr, rpath.val))) + Elfwritedynent2(ctxt, dynamic, DT_RUNPATH, uint64(dynstr.Addstring(rpath.val))) } - if ctxt.Arch.Family == sys.PPC64 { - elfWriteDynEntSym(ctxt.Arch, s, DT_PLTGOT, ctxt.Syms.Lookup(".plt", 0)) - } else if ctxt.Arch.Family == sys.S390X { - elfWriteDynEntSym(ctxt.Arch, s, DT_PLTGOT, ctxt.Syms.Lookup(".got", 0)) + if ctxt.IsPPC64() { + elfwritedynentsym2(ctxt, dynamic, DT_PLTGOT, plt.Sym()) + } else if ctxt.IsS390X() { + elfwritedynentsym2(ctxt, dynamic, DT_PLTGOT, got.Sym()) } else { - elfWriteDynEntSym(ctxt.Arch, s, DT_PLTGOT, ctxt.Syms.Lookup(".got.plt", 0)) + elfwritedynentsym2(ctxt, dynamic, DT_PLTGOT, gotplt.Sym()) } - if ctxt.Arch.Family == sys.PPC64 { - elfWriteDynEnt(ctxt.Arch, s, DT_PPC64_OPT, 0) + if ctxt.IsPPC64() { + Elfwritedynent2(ctxt, dynamic, DT_PPC64_OPT, 0) } // Solaris dynamic linker can't handle an empty .rela.plt if // DT_JMPREL is emitted so we have to defer generation of DT_PLTREL, // DT_PLTRELSZ, and DT_JMPREL dynamic entries until after we know the // size of .rel(a).plt section. - elfWriteDynEnt(ctxt.Arch, s, DT_DEBUG, 0) + Elfwritedynent2(ctxt, dynamic, DT_DEBUG, 0) } - if ctxt.BuildMode == BuildModeShared { + if ctxt.IsShared() { // The go.link.abihashbytes symbol will be pointed at the appropriate // part of the .note.go.abihash section in data.go:func address(). - s := ctxt.Syms.Lookup("go.link.abihashbytes", 0) - s.Attr |= sym.AttrLocal - s.Type = sym.SRODATA - s.Attr |= sym.AttrSpecial - s.Attr |= sym.AttrReachable - s.Size = int64(sha1.Size) + s := ldr.LookupOrCreateSym("go.link.abihashbytes", 0) + sb := ldr.MakeSymbolUpdater(s) + ldr.SetAttrLocal(s, true) + sb.SetType(sym.SRODATA) + ldr.SetAttrSpecial(s, true) + sb.SetReachable(true) + sb.SetSize(sha1.Size) sort.Sort(byPkg(ctxt.Library)) h := sha1.New() diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index bf8f240b00..6f222ce10c 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -174,7 +174,7 @@ type Arch struct { Asmb2 func(*Link) Elfreloc1 func(*Link, *sym.Reloc, int64) bool - Elfsetupplt func(*Link, *Target, *ArchSyms) + Elfsetupplt func(ctxt *Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) Gentext func(*Link) Machoreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool PEreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 8e7b9b8113..e2c795ac69 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -250,7 +250,7 @@ func Main(arch *sys.Arch, theArch Arch) { bench.Start("dostkcheck") ctxt.dostkcheck() - if !ctxt.IsDarwin() { + if !ctxt.IsELF && !ctxt.IsDarwin() { bench.Start("loadlibfull") ctxt.loadlibfull() // XXX do it here for now } @@ -258,6 +258,8 @@ func Main(arch *sys.Arch, theArch Arch) { if ctxt.IsELF { bench.Start("doelf") ctxt.doelf() + bench.Start("loadlibfull") + ctxt.loadlibfull() // XXX do it here for now } if ctxt.IsDarwin() { bench.Start("domacho") diff --git a/src/cmd/link/internal/ld/target.go b/src/cmd/link/internal/ld/target.go index 0caf2976df..69c15e56ee 100644 --- a/src/cmd/link/internal/ld/target.go +++ b/src/cmd/link/internal/ld/target.go @@ -112,6 +112,14 @@ func (t *Target) IsSolaris() bool { return t.HeadType == objabi.Hsolaris } +func (t *Target) IsNetbsd() bool { + return t.HeadType == objabi.Hnetbsd +} + +func (t *Target) IsOpenbsd() bool { + return t.HeadType == objabi.Hopenbsd +} + // // MISC // diff --git a/src/cmd/link/internal/loader/symbolbuilder.go b/src/cmd/link/internal/loader/symbolbuilder.go index 2560198aa6..aeaec8b7b0 100644 --- a/src/cmd/link/internal/loader/symbolbuilder.go +++ b/src/cmd/link/internal/loader/symbolbuilder.go @@ -60,6 +60,13 @@ func (l *Loader) MakeSymbolUpdater(symIdx Sym) *SymbolBuilder { return sb } +// CreateSymForUpdate creates a symbol with given name and version, +// returns a CreateSymForUpdate for update. If the symbol already +// exists, it will update in-place. +func (l *Loader) CreateSymForUpdate(name string, version int) *SymbolBuilder { + return l.MakeSymbolUpdater(l.LookupOrCreateSym(name, version)) +} + // Getters for properties of the symbol we're working on. func (sb *SymbolBuilder) Sym() Sym { return sb.symIdx } @@ -271,7 +278,7 @@ func (sb *SymbolBuilder) addRel() *Reloc { return &sb.relocs[len(sb.relocs)-1] } -func (sb *SymbolBuilder) addAddrPlus(tgt Sym, add int64, typ objabi.RelocType, rsize int) int64 { +func (sb *SymbolBuilder) addSymRef(tgt Sym, add int64, typ objabi.RelocType, rsize int) int64 { if sb.kind == 0 { sb.kind = sym.SDATA } @@ -290,17 +297,34 @@ func (sb *SymbolBuilder) addAddrPlus(tgt Sym, add int64, typ objabi.RelocType, r return i + int64(r.Size) } +// Add a symbol reference (relocation) with given type, addend, and size +// (the most generic form). +func (sb *SymbolBuilder) AddSymRef(arch *sys.Arch, tgt Sym, add int64, typ objabi.RelocType, rsize int) int64 { + sb.setReachable() + return sb.addSymRef(tgt, add, typ, rsize) +} + func (sb *SymbolBuilder) AddAddrPlus(arch *sys.Arch, tgt Sym, add int64) int64 { sb.setReachable() - return sb.addAddrPlus(tgt, add, objabi.R_ADDR, arch.PtrSize) + return sb.addSymRef(tgt, add, objabi.R_ADDR, arch.PtrSize) } func (sb *SymbolBuilder) AddAddrPlus4(arch *sys.Arch, tgt Sym, add int64) int64 { sb.setReachable() - return sb.addAddrPlus(tgt, add, objabi.R_ADDR, 4) + return sb.addSymRef(tgt, add, objabi.R_ADDR, 4) +} + +func (sb *SymbolBuilder) AddPCRelPlus(arch *sys.Arch, tgt Sym, add int64) int64 { + sb.setReachable() + return sb.addSymRef(tgt, add, objabi.R_PCREL, 4) } func (sb *SymbolBuilder) AddCURelativeAddrPlus(arch *sys.Arch, tgt Sym, add int64) int64 { sb.setReachable() - return sb.addAddrPlus(tgt, add, objabi.R_ADDRCUOFF, arch.PtrSize) + return sb.addSymRef(tgt, add, objabi.R_ADDRCUOFF, arch.PtrSize) +} + +func (sb *SymbolBuilder) AddSize(arch *sys.Arch, tgt Sym) int64 { + sb.setReachable() + return sb.addSymRef(tgt, 0, objabi.R_SIZE, arch.PtrSize) } diff --git a/src/cmd/link/internal/mips/asm.go b/src/cmd/link/internal/mips/asm.go index aceed34301..c2cabc8291 100644 --- a/src/cmd/link/internal/mips/asm.go +++ b/src/cmd/link/internal/mips/asm.go @@ -34,6 +34,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "debug/elf" "fmt" @@ -74,7 +75,7 @@ func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool { return true } -func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { +func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) { return } diff --git a/src/cmd/link/internal/mips64/asm.go b/src/cmd/link/internal/mips64/asm.go index d62ff8ec36..a6abec15f6 100644 --- a/src/cmd/link/internal/mips64/asm.go +++ b/src/cmd/link/internal/mips64/asm.go @@ -34,6 +34,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "debug/elf" "fmt" @@ -91,7 +92,7 @@ func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool { return true } -func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { +func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) { return } diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 21c9ad3e48..d0993e3267 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -34,6 +34,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "debug/elf" "encoding/binary" @@ -498,14 +499,13 @@ func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool { return true } -func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { - plt := ctxt.Syms.Lookup(".plt", 0) - if plt.Size == 0 { +func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) { + if plt.Size() == 0 { // The dynamic linker stores the address of the // dynamic resolver and the DSO identifier in the two // doublewords at the beginning of the .plt section // before the PLT array. Reserve space for these. - plt.Size = 16 + plt.SetSize(16) } } @@ -949,7 +949,7 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) { plt := ctxt.Syms.Lookup(".plt", 0) rela := ctxt.Syms.Lookup(".rela.plt", 0) if plt.Size == 0 { - elfsetupplt(ctxt, &ctxt.Target, &ctxt.ArchSyms) + panic("plt is not set up") } // Create the glink resolver if necessary diff --git a/src/cmd/link/internal/riscv64/asm.go b/src/cmd/link/internal/riscv64/asm.go index 704435ffd0..bd8380bfe2 100644 --- a/src/cmd/link/internal/riscv64/asm.go +++ b/src/cmd/link/internal/riscv64/asm.go @@ -9,6 +9,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "fmt" "log" @@ -31,7 +32,7 @@ func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool { return false } -func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { +func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) { log.Fatalf("elfsetuplt") } diff --git a/src/cmd/link/internal/s390x/asm.go b/src/cmd/link/internal/s390x/asm.go index 9bf3c5bde6..c5060fa02c 100644 --- a/src/cmd/link/internal/s390x/asm.go +++ b/src/cmd/link/internal/s390x/asm.go @@ -34,6 +34,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "debug/elf" "fmt" @@ -333,10 +334,8 @@ func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool { return true } -func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { - plt := ctxt.Syms.Lookup(".plt", 0) - got := ctxt.Syms.Lookup(".got", 0) - if plt.Size == 0 { +func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) { + if plt.Size() == 0 { // stg %r1,56(%r15) plt.AddUint8(0xe3) plt.AddUint8(0x10) @@ -347,7 +346,7 @@ func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { // larl %r1,_GLOBAL_OFFSET_TABLE_ plt.AddUint8(0xc0) plt.AddUint8(0x10) - plt.AddPCRelPlus(ctxt.Arch, got, 6) + plt.AddPCRelPlus(ctxt.Arch, got.Sym(), 6) // mvc 48(8,%r15),8(%r1) plt.AddUint8(0xd2) plt.AddUint8(0x07) @@ -376,7 +375,7 @@ func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { plt.AddUint8(0x00) // assume got->size == 0 too - got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0) + got.AddAddrPlus(ctxt.Arch, dynamic, 0) got.AddUint64(ctxt.Arch, 0) got.AddUint64(ctxt.Arch, 0) @@ -431,7 +430,7 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) { got := ctxt.Syms.Lookup(".got", 0) rela := ctxt.Syms.Lookup(".rela.plt", 0) if plt.Size == 0 { - elfsetupplt(ctxt, &ctxt.Target, &ctxt.ArchSyms) + panic("plt is not set up") } // larl %r1,_GLOBAL_OFFSET_TABLE_+index diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go index 267e048b40..1e407d05c0 100644 --- a/src/cmd/link/internal/x86/asm.go +++ b/src/cmd/link/internal/x86/asm.go @@ -34,6 +34,7 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "debug/elf" "log" @@ -511,27 +512,25 @@ func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym return t } -func elfsetupplt(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms) { - plt := ctxt.Syms.Lookup(".plt", 0) - got := ctxt.Syms.Lookup(".got.plt", 0) - if plt.Size == 0 { +func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) { + if plt.Size() == 0 { // pushl got+4 plt.AddUint8(0xff) plt.AddUint8(0x35) - plt.AddAddrPlus(ctxt.Arch, got, 4) + plt.AddAddrPlus(ctxt.Arch, got.Sym(), 4) // jmp *got+8 plt.AddUint8(0xff) plt.AddUint8(0x25) - plt.AddAddrPlus(ctxt.Arch, got, 8) + plt.AddAddrPlus(ctxt.Arch, got.Sym(), 8) // zero pad plt.AddUint32(ctxt.Arch, 0) // assume got->size == 0 too - got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0) + got.AddAddrPlus(ctxt.Arch, dynamic, 0) got.AddUint32(ctxt.Arch, 0) got.AddUint32(ctxt.Arch, 0) @@ -550,7 +549,7 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) { got := ctxt.Syms.Lookup(".got.plt", 0) rel := ctxt.Syms.Lookup(".rel.plt", 0) if plt.Size == 0 { - elfsetupplt(ctxt, &ctxt.Target, &ctxt.ArchSyms) + panic("plt is not set up") } // jmpq *got+size