1
0
mirror of https://github.com/golang/go synced 2024-09-29 23:24:29 -06:00

[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 <thanm@google.com>
This commit is contained in:
Cherry Zhang 2020-03-11 12:12:41 -04:00
parent a8e8e05ed1
commit a3e965ce8a
15 changed files with 278 additions and 217 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)
// <imm> is the offset value of &got[2] to &got[0], the same below
// ldr x17, [x16, <imm>]
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, <imm>
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]

View File

@ -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)
}
}
}

View File

@ -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()

View File

@ -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

View File

@ -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")

View File

@ -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
//

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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")
}

View File

@ -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

View File

@ -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