mirror of
https://github.com/golang/go
synced 2024-11-05 15:46:11 -07:00
[dev.link] cmd/link: delete old dodata
Change-Id: I569bbee235630baad3c35ca0c6598b8bd059307a Reviewed-on: https://go-review.googlesource.com/c/go/+/230311 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
82f633a8e9
commit
98e3fdab3e
@ -1,402 +0,0 @@
|
||||
// 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 amd64
|
||||
|
||||
import (
|
||||
"cmd/internal/objabi"
|
||||
"cmd/link/internal/ld"
|
||||
"cmd/link/internal/loader"
|
||||
"cmd/link/internal/sym"
|
||||
"debug/elf"
|
||||
)
|
||||
|
||||
// Temporary dumping around 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_X86_64_PC32):
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_X86_64_PC32 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_X86_64_PC64):
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_X86_64_PC64 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_X86_64_PLT32):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Add += 4
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_GOTPCREL),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_GOTPCRELX),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_REX_GOTPCRELX):
|
||||
if targ.Type != sym.SDYNIMPORT {
|
||||
// have symbol
|
||||
if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
|
||||
makeWritable(s)
|
||||
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
||||
s.P[r.Off-2] = 0x8d
|
||||
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Add += 4
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// fall back to using GOT and hope for the best (CMOV*)
|
||||
// TODO: just needs relocation, no need to put in .dynsym
|
||||
addgotsym(target, syms, targ)
|
||||
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Sym = syms.GOT
|
||||
r.Add += 4
|
||||
r.Add += int64(targ.Got())
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_64):
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_X86_64_64 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
|
||||
|
||||
// Handle relocations found in Mach-O object files.
|
||||
case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 0,
|
||||
objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED*2 + 0,
|
||||
objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 0:
|
||||
// TODO: What is the difference between all these?
|
||||
r.Type = objabi.R_ADDR
|
||||
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
return true
|
||||
|
||||
case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1:
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(targ.Plt())
|
||||
r.Type = objabi.R_PCREL
|
||||
return true
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 1,
|
||||
objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED*2 + 1,
|
||||
objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_1*2 + 1,
|
||||
objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_2*2 + 1,
|
||||
objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
|
||||
r.Type = objabi.R_PCREL
|
||||
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected pc-relative reloc for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
return true
|
||||
|
||||
case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
|
||||
if targ.Type != sym.SDYNIMPORT {
|
||||
// have symbol
|
||||
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
||||
if r.Off < 2 || s.P[r.Off-2] != 0x8b {
|
||||
ld.Errorf(s, "unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ.Name)
|
||||
return false
|
||||
}
|
||||
|
||||
makeWritable(s)
|
||||
s.P[r.Off-2] = 0x8d
|
||||
r.Type = objabi.R_PCREL
|
||||
return true
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_GOT*2 + 1:
|
||||
if targ.Type != sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
|
||||
}
|
||||
addgotsym(target, syms, targ)
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got())
|
||||
return true
|
||||
}
|
||||
|
||||
switch r.Type {
|
||||
case objabi.R_CALL,
|
||||
objabi.R_PCREL:
|
||||
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
|
||||
}
|
||||
// Internal linking, for both ELF and Mach-O.
|
||||
// Build a PLT entry and change the relocation target to that entry.
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(targ.Plt())
|
||||
return true
|
||||
|
||||
case objabi.R_ADDR:
|
||||
if s.Type == sym.STEXT && target.IsElf() {
|
||||
if target.IsSolaris() {
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
return true
|
||||
}
|
||||
// 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_X86_64_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_X86_64_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_X86_64_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
|
||||
}
|
||||
|
||||
if target.IsDarwin() && s.Size == int64(target.Arch.PtrSize) && r.Off == 0 {
|
||||
// Mach-O relocations are a royal pain to lay out.
|
||||
// They use a compact stateful bytecode representation
|
||||
// that is too much bother to deal with.
|
||||
// Instead, interpret the C declaration
|
||||
// void *_Cvar_stderr = &stderr;
|
||||
// as making _Cvar_stderr the name of a GOT entry
|
||||
// for stderr. This is separate from the usual GOT entry,
|
||||
// just in case the C code assigns to the variable,
|
||||
// and of course it only works for single pointers,
|
||||
// but we only need to support cgo and that's all it needs.
|
||||
ld.Adddynsym(target, syms, targ)
|
||||
|
||||
got := syms.GOT
|
||||
s.Type = got.Type
|
||||
s.Attr |= sym.AttrSubSymbol
|
||||
s.Outer = got
|
||||
s.Sub = got.Sub
|
||||
got.Sub = s
|
||||
s.Value = got.Size
|
||||
got.AddUint64(target.Arch, 0)
|
||||
syms.LinkEditGOT.AddUint32(target.Arch, uint32(targ.Dynid))
|
||||
r.Type = objabi.ElfRelocOffset // ignore during relocsym
|
||||
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
|
||||
rela := syms.RelaPLT
|
||||
if plt.Size == 0 {
|
||||
panic("plt is not set up")
|
||||
}
|
||||
|
||||
// jmpq *got+size(IP)
|
||||
plt.AddUint8(0xff)
|
||||
|
||||
plt.AddUint8(0x25)
|
||||
plt.AddPCRelPlus(target.Arch, got, got.Size)
|
||||
|
||||
// add to got: pointer to current pos in plt
|
||||
got.AddAddrPlus(target.Arch, plt, plt.Size)
|
||||
|
||||
// pushq $x
|
||||
plt.AddUint8(0x68)
|
||||
|
||||
plt.AddUint32(target.Arch, uint32((got.Size-24-8)/8))
|
||||
|
||||
// jmpq .plt
|
||||
plt.AddUint8(0xe9)
|
||||
|
||||
plt.AddUint32(target.Arch, uint32(-(plt.Size + 4)))
|
||||
|
||||
// rela
|
||||
rela.AddAddrPlus(target.Arch, got, got.Size-8)
|
||||
|
||||
rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_X86_64_JMP_SLOT)))
|
||||
rela.AddUint64(target.Arch, 0)
|
||||
|
||||
s.SetPlt(int32(plt.Size - 16))
|
||||
} else if target.IsDarwin() {
|
||||
// To do lazy symbol lookup right, we're supposed
|
||||
// to tell the dynamic loader which library each
|
||||
// symbol comes from and format the link info
|
||||
// section just so. I'm too lazy (ha!) to do that
|
||||
// so for now we'll just use non-lazy pointers,
|
||||
// which don't need to be told which library to use.
|
||||
//
|
||||
// https://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html
|
||||
// has details about what we're avoiding.
|
||||
|
||||
addgotsym(target, syms, s)
|
||||
plt := syms.PLT
|
||||
|
||||
syms.LinkEditPLT.AddUint32(target.Arch, uint32(s.Dynid))
|
||||
|
||||
// jmpq *got+size(IP)
|
||||
s.SetPlt(int32(plt.Size))
|
||||
|
||||
plt.AddUint8(0xff)
|
||||
plt.AddUint8(0x25)
|
||||
plt.AddPCRelPlus(target.Arch, syms.GOT, int64(s.Got()))
|
||||
} 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_X86_64_GLOB_DAT)))
|
||||
rela.AddUint64(target.Arch, 0)
|
||||
} else if target.IsDarwin() {
|
||||
syms.LinkEditGOT.AddUint32(target.Arch, uint32(s.Dynid))
|
||||
} else {
|
||||
ld.Errorf(s, "addgotsym: unsupported binary format")
|
||||
}
|
||||
}
|
@ -46,7 +46,6 @@ func Init() (*sys.Arch, ld.Arch) {
|
||||
Dwarfregsp: dwarfRegSP,
|
||||
Dwarfreglr: dwarfRegLR,
|
||||
|
||||
Adddynrel: adddynrel,
|
||||
Adddynrel2: adddynrel2,
|
||||
Archinit: archinit,
|
||||
Archreloc: archreloc,
|
||||
|
@ -1,246 +0,0 @@
|
||||
// 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")
|
||||
}
|
||||
}
|
@ -46,7 +46,6 @@ func Init() (*sys.Arch, ld.Arch) {
|
||||
Dwarfregsp: dwarfRegSP,
|
||||
Dwarfreglr: dwarfRegLR,
|
||||
|
||||
Adddynrel: adddynrel,
|
||||
Adddynrel2: adddynrel2,
|
||||
Archinit: archinit,
|
||||
Archreloc: archreloc,
|
||||
|
@ -1,312 +0,0 @@
|
||||
// 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")
|
||||
}
|
||||
}
|
@ -46,7 +46,6 @@ func Init() (*sys.Arch, ld.Arch) {
|
||||
Dwarfregsp: dwarfRegSP,
|
||||
Dwarfreglr: dwarfRegLR,
|
||||
|
||||
Adddynrel: adddynrel,
|
||||
Adddynrel2: adddynrel2,
|
||||
Archinit: archinit,
|
||||
Archreloc: archreloc,
|
||||
|
@ -5,16 +5,8 @@
|
||||
package ld
|
||||
|
||||
import (
|
||||
"cmd/internal/gcprog"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/link/internal/loader"
|
||||
"cmd/link/internal/sym"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Temporary dumping around for sym.Symbol version of helper
|
||||
@ -22,206 +14,6 @@ import (
|
||||
// FIXME: get rid of this file when dodata() is completely
|
||||
// converted.
|
||||
|
||||
func (ctxt *Link) dodata() {
|
||||
// Give zeros sized symbols space if necessary.
|
||||
fixZeroSizedSymbols(ctxt)
|
||||
|
||||
// Collect data symbols by type into data.
|
||||
state := dodataState{ctxt: ctxt}
|
||||
for _, s := range ctxt.loader.Syms {
|
||||
if s == nil {
|
||||
continue
|
||||
}
|
||||
if !s.Attr.Reachable() || s.Attr.Special() || s.Attr.SubSymbol() {
|
||||
continue
|
||||
}
|
||||
if s.Type <= sym.STEXT || s.Type >= sym.SXREF {
|
||||
continue
|
||||
}
|
||||
state.data[s.Type] = append(state.data[s.Type], s)
|
||||
}
|
||||
|
||||
// Now that we have the data symbols, but before we start
|
||||
// to assign addresses, record all the necessary
|
||||
// dynamic relocations. These will grow the relocation
|
||||
// symbol, which is itself data.
|
||||
//
|
||||
// On darwin, we need the symbol table numbers for dynreloc.
|
||||
if ctxt.HeadType == objabi.Hdarwin {
|
||||
panic("not supported")
|
||||
//machosymorder(ctxt)
|
||||
}
|
||||
state.dynreloc(ctxt)
|
||||
|
||||
// Move any RO data with relocations to a separate section.
|
||||
state.makeRelroForSharedLib(ctxt)
|
||||
|
||||
// Temporary for debugging.
|
||||
symToIdx := make(map[*sym.Symbol]loader.Sym)
|
||||
for s := loader.Sym(1); s < loader.Sym(ctxt.loader.NSym()); s++ {
|
||||
sp := ctxt.loader.Syms[s]
|
||||
if sp != nil {
|
||||
symToIdx[sp] = s
|
||||
}
|
||||
}
|
||||
|
||||
// Sort symbols.
|
||||
var wg sync.WaitGroup
|
||||
for symn := range state.data {
|
||||
symn := sym.SymKind(symn)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
state.data[symn], state.dataMaxAlign[symn] = dodataSect(ctxt, symn, state.data[symn], symToIdx)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
|
||||
// These symbols must have the same alignment as their section.
|
||||
// Otherwize, ld might change the layout of Go sections.
|
||||
ctxt.Syms.ROLookup("runtime.data", 0).Align = state.dataMaxAlign[sym.SDATA]
|
||||
ctxt.Syms.ROLookup("runtime.bss", 0).Align = state.dataMaxAlign[sym.SBSS]
|
||||
}
|
||||
|
||||
// Create *sym.Section objects and assign symbols to sections for
|
||||
// data/rodata (and related) symbols.
|
||||
state.allocateDataSections(ctxt)
|
||||
|
||||
// Create *sym.Section objects and assign symbols to sections for
|
||||
// DWARF symbols.
|
||||
state.allocateDwarfSections(ctxt)
|
||||
|
||||
/* number the sections */
|
||||
n := int16(1)
|
||||
|
||||
for _, sect := range Segtext.Sections {
|
||||
sect.Extnum = n
|
||||
n++
|
||||
}
|
||||
for _, sect := range Segrodata.Sections {
|
||||
sect.Extnum = n
|
||||
n++
|
||||
}
|
||||
for _, sect := range Segrelrodata.Sections {
|
||||
sect.Extnum = n
|
||||
n++
|
||||
}
|
||||
for _, sect := range Segdata.Sections {
|
||||
sect.Extnum = n
|
||||
n++
|
||||
}
|
||||
for _, sect := range Segdwarf.Sections {
|
||||
sect.Extnum = n
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
// makeRelroForSharedLib creates a section of readonly data if necessary.
|
||||
func (state *dodataState) makeRelroForSharedLib(target *Link) {
|
||||
if !target.UseRelro() {
|
||||
return
|
||||
}
|
||||
|
||||
// "read only" data with relocations needs to go in its own section
|
||||
// when building a shared library. We do this by boosting objects of
|
||||
// type SXXX with relocations to type SXXXRELRO.
|
||||
for _, symnro := range sym.ReadOnly {
|
||||
symnrelro := sym.RelROMap[symnro]
|
||||
|
||||
ro := []*sym.Symbol{}
|
||||
relro := state.data[symnrelro]
|
||||
|
||||
for _, s := range state.data[symnro] {
|
||||
isRelro := len(s.R) > 0
|
||||
switch s.Type {
|
||||
case sym.STYPE, sym.STYPERELRO, sym.SGOFUNCRELRO:
|
||||
// Symbols are not sorted yet, so it is possible
|
||||
// that an Outer symbol has been changed to a
|
||||
// relro Type before it reaches here.
|
||||
isRelro = true
|
||||
case sym.SFUNCTAB:
|
||||
if target.IsAIX() && s.Name == "runtime.etypes" {
|
||||
// runtime.etypes must be at the end of
|
||||
// the relro datas.
|
||||
isRelro = true
|
||||
}
|
||||
}
|
||||
if isRelro {
|
||||
s.Type = symnrelro
|
||||
if s.Outer != nil {
|
||||
s.Outer.Type = s.Type
|
||||
}
|
||||
relro = append(relro, s)
|
||||
} else {
|
||||
ro = append(ro, s)
|
||||
}
|
||||
}
|
||||
|
||||
// Check that we haven't made two symbols with the same .Outer into
|
||||
// different types (because references two symbols with non-nil Outer
|
||||
// become references to the outer symbol + offset it's vital that the
|
||||
// symbol and the outer end up in the same section).
|
||||
for _, s := range relro {
|
||||
if s.Outer != nil && s.Outer.Type != s.Type {
|
||||
Errorf(s, "inconsistent types for symbol and its Outer %s (%v != %v)",
|
||||
s.Outer.Name, s.Type, s.Outer.Type)
|
||||
}
|
||||
}
|
||||
|
||||
state.data[symnro] = ro
|
||||
state.data[symnrelro] = relro
|
||||
}
|
||||
}
|
||||
|
||||
func dynrelocsym(ctxt *Link, s *sym.Symbol) {
|
||||
target := &ctxt.Target
|
||||
ldr := ctxt.loader
|
||||
syms := &ctxt.ArchSyms
|
||||
for ri := range s.R {
|
||||
r := &s.R[ri]
|
||||
if ctxt.BuildMode == BuildModePIE && ctxt.LinkMode == LinkInternal {
|
||||
// It's expected that some relocations will be done
|
||||
// later by relocsym (R_TLS_LE, R_ADDROFF), so
|
||||
// don't worry if Adddynrel returns false.
|
||||
thearch.Adddynrel(target, ldr, syms, s, r)
|
||||
continue
|
||||
}
|
||||
|
||||
if r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT || r.Type >= objabi.ElfRelocOffset {
|
||||
if r.Sym != nil && !r.Sym.Attr.Reachable() {
|
||||
Errorf(s, "dynamic relocation to unreachable symbol %s", r.Sym.Name)
|
||||
}
|
||||
if !thearch.Adddynrel(target, ldr, syms, s, r) {
|
||||
Errorf(s, "unsupported dynamic relocation for symbol %s (type=%d (%s) stype=%d (%s))", r.Sym.Name, r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Sym.Type, r.Sym.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (state *dodataState) dynreloc(ctxt *Link) {
|
||||
if ctxt.HeadType == objabi.Hwindows {
|
||||
return
|
||||
}
|
||||
// -d suppresses dynamic loader format, so we may as well not
|
||||
// compute these sections or mark their symbols as reachable.
|
||||
if *FlagD {
|
||||
return
|
||||
}
|
||||
|
||||
for _, s := range ctxt.Textp {
|
||||
dynrelocsym(ctxt, s)
|
||||
}
|
||||
for _, syms := range state.data {
|
||||
for _, s := range syms {
|
||||
dynrelocsym(ctxt, s)
|
||||
}
|
||||
}
|
||||
if ctxt.IsELF {
|
||||
elfdynhash(ctxt)
|
||||
}
|
||||
}
|
||||
|
||||
func Addstring(s *sym.Symbol, str string) int64 {
|
||||
if s.Type == 0 {
|
||||
s.Type = sym.SNOPTRDATA
|
||||
@ -257,686 +49,3 @@ func symalign(s *sym.Symbol) int32 {
|
||||
s.Align = align
|
||||
return align
|
||||
}
|
||||
|
||||
func aligndatsize(datsize int64, s *sym.Symbol) int64 {
|
||||
return Rnd(datsize, int64(symalign(s)))
|
||||
}
|
||||
|
||||
type GCProg struct {
|
||||
ctxt *Link
|
||||
sym *sym.Symbol
|
||||
w gcprog.Writer
|
||||
}
|
||||
|
||||
func (p *GCProg) Init(ctxt *Link, name string) {
|
||||
p.ctxt = ctxt
|
||||
p.sym = ctxt.Syms.Lookup(name, 0)
|
||||
p.w.Init(p.writeByte(ctxt))
|
||||
if debugGCProg {
|
||||
fmt.Fprintf(os.Stderr, "ld: start GCProg %s\n", name)
|
||||
p.w.Debug(os.Stderr)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *GCProg) writeByte(ctxt *Link) func(x byte) {
|
||||
return func(x byte) {
|
||||
p.sym.AddUint8(x)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *GCProg) End(size int64) {
|
||||
p.w.ZeroUntil(size / int64(p.ctxt.Arch.PtrSize))
|
||||
p.w.End()
|
||||
if debugGCProg {
|
||||
fmt.Fprintf(os.Stderr, "ld: end GCProg\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *GCProg) AddSym(s *sym.Symbol) {
|
||||
typ := s.Gotype
|
||||
// Things without pointers should be in sym.SNOPTRDATA or sym.SNOPTRBSS;
|
||||
// everything we see should have pointers and should therefore have a type.
|
||||
if typ == nil {
|
||||
switch s.Name {
|
||||
case "runtime.data", "runtime.edata", "runtime.bss", "runtime.ebss":
|
||||
// Ignore special symbols that are sometimes laid out
|
||||
// as real symbols. See comment about dyld on darwin in
|
||||
// the address function.
|
||||
return
|
||||
}
|
||||
Errorf(s, "missing Go type information for global symbol: size %d", s.Size)
|
||||
return
|
||||
}
|
||||
|
||||
ptrsize := int64(p.ctxt.Arch.PtrSize)
|
||||
nptr := decodetypePtrdata(p.ctxt.Arch, typ.P) / ptrsize
|
||||
|
||||
if debugGCProg {
|
||||
fmt.Fprintf(os.Stderr, "gcprog sym: %s at %d (ptr=%d+%d)\n", s.Name, s.Value, s.Value/ptrsize, nptr)
|
||||
}
|
||||
|
||||
if decodetypeUsegcprog(p.ctxt.Arch, typ.P) == 0 {
|
||||
// Copy pointers from mask into program.
|
||||
mask := decodetypeGcmask(p.ctxt, typ)
|
||||
for i := int64(0); i < nptr; i++ {
|
||||
if (mask[i/8]>>uint(i%8))&1 != 0 {
|
||||
p.w.Ptr(s.Value/ptrsize + i)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Copy program.
|
||||
prog := decodetypeGcprog(p.ctxt, typ)
|
||||
p.w.ZeroUntil(s.Value / ptrsize)
|
||||
p.w.Append(prog[4:], nptr)
|
||||
}
|
||||
|
||||
// dataSortKey is used to sort a slice of data symbol *sym.Symbol pointers.
|
||||
// The sort keys are kept inline to improve cache behavior while sorting.
|
||||
type dataSortKey struct {
|
||||
size int64
|
||||
name string
|
||||
sym *sym.Symbol
|
||||
symIdx loader.Sym
|
||||
}
|
||||
|
||||
type bySizeAndName []dataSortKey
|
||||
|
||||
func (d bySizeAndName) Len() int { return len(d) }
|
||||
func (d bySizeAndName) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
||||
func (d bySizeAndName) Less(i, j int) bool {
|
||||
s1, s2 := d[i], d[j]
|
||||
if s1.size != s2.size {
|
||||
return s1.size < s2.size
|
||||
}
|
||||
if s1.name != s2.name {
|
||||
return s1.name < s2.name
|
||||
}
|
||||
return s1.symIdx < s2.symIdx
|
||||
}
|
||||
|
||||
// fixZeroSizedSymbols gives a few special symbols with zero size some space.
|
||||
func fixZeroSizedSymbols(ctxt *Link) {
|
||||
// The values in moduledata are filled out by relocations
|
||||
// pointing to the addresses of these special symbols.
|
||||
// Typically these symbols have no size and are not laid
|
||||
// out with their matching section.
|
||||
//
|
||||
// However on darwin, dyld will find the special symbol
|
||||
// in the first loaded module, even though it is local.
|
||||
//
|
||||
// (An hypothesis, formed without looking in the dyld sources:
|
||||
// these special symbols have no size, so their address
|
||||
// matches a real symbol. The dynamic linker assumes we
|
||||
// want the normal symbol with the same address and finds
|
||||
// it in the other module.)
|
||||
//
|
||||
// To work around this we lay out the symbls whose
|
||||
// addresses are vital for multi-module programs to work
|
||||
// as normal symbols, and give them a little size.
|
||||
//
|
||||
// On AIX, as all DATA sections are merged together, ld might not put
|
||||
// these symbols at the beginning of their respective section if there
|
||||
// aren't real symbols, their alignment might not match the
|
||||
// first symbol alignment. Therefore, there are explicitly put at the
|
||||
// beginning of their section with the same alignment.
|
||||
if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) && !(ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
|
||||
return
|
||||
}
|
||||
|
||||
bss := ctxt.Syms.Lookup("runtime.bss", 0)
|
||||
bss.Size = 8
|
||||
bss.Attr.Set(sym.AttrSpecial, false)
|
||||
|
||||
ctxt.Syms.Lookup("runtime.ebss", 0).Attr.Set(sym.AttrSpecial, false)
|
||||
|
||||
data := ctxt.Syms.Lookup("runtime.data", 0)
|
||||
data.Size = 8
|
||||
data.Attr.Set(sym.AttrSpecial, false)
|
||||
|
||||
edata := ctxt.Syms.Lookup("runtime.edata", 0)
|
||||
edata.Attr.Set(sym.AttrSpecial, false)
|
||||
if ctxt.HeadType == objabi.Haix {
|
||||
// XCOFFTOC symbols are part of .data section.
|
||||
edata.Type = sym.SXCOFFTOC
|
||||
}
|
||||
|
||||
types := ctxt.Syms.Lookup("runtime.types", 0)
|
||||
types.Type = sym.STYPE
|
||||
types.Size = 8
|
||||
types.Attr.Set(sym.AttrSpecial, false)
|
||||
|
||||
etypes := ctxt.Syms.Lookup("runtime.etypes", 0)
|
||||
etypes.Type = sym.SFUNCTAB
|
||||
etypes.Attr.Set(sym.AttrSpecial, false)
|
||||
|
||||
if ctxt.HeadType == objabi.Haix {
|
||||
rodata := ctxt.Syms.Lookup("runtime.rodata", 0)
|
||||
rodata.Type = sym.SSTRING
|
||||
rodata.Size = 8
|
||||
rodata.Attr.Set(sym.AttrSpecial, false)
|
||||
|
||||
ctxt.Syms.Lookup("runtime.erodata", 0).Attr.Set(sym.AttrSpecial, false)
|
||||
}
|
||||
}
|
||||
|
||||
// allocateDataSectionForSym creates a new sym.Section into which a a
|
||||
// single symbol will be placed. Here "seg" is the segment into which
|
||||
// the section will go, "s" is the symbol to be placed into the new
|
||||
// section, and "rwx" contains permissions for the section.
|
||||
func (state *dodataState) allocateDataSectionForSym(seg *sym.Segment, s *sym.Symbol, rwx int) *sym.Section {
|
||||
sect := addsection(state.ctxt.loader, state.ctxt.Arch, seg, s.Name, rwx)
|
||||
sect.Align = symalign(s)
|
||||
state.datsize = Rnd(state.datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(state.datsize)
|
||||
return sect
|
||||
}
|
||||
|
||||
// assignDsymsToSection assigns a collection of data symbols to a
|
||||
// newly created section. "sect" is the section into which to place
|
||||
// the symbols, "syms" holds the list of symbols to assign,
|
||||
// "forceType" (if non-zero) contains a new sym type to apply to each
|
||||
// sym during the assignment, and "aligner" is a hook to call to
|
||||
// handle alignment during the assignment process.
|
||||
func (state *dodataState) assignDsymsToSection(sect *sym.Section, syms []*sym.Symbol, forceType sym.SymKind, aligner func(datsize int64, s *sym.Symbol) int64) {
|
||||
for _, s := range syms {
|
||||
state.datsize = aligner(state.datsize, s)
|
||||
s.Sect = sect
|
||||
if forceType != sym.Sxxx {
|
||||
s.Type = forceType
|
||||
}
|
||||
s.Value = int64(uint64(state.datsize) - sect.Vaddr)
|
||||
state.datsize += s.Size
|
||||
}
|
||||
sect.Length = uint64(state.datsize) - sect.Vaddr
|
||||
}
|
||||
|
||||
func (state *dodataState) assignToSection(sect *sym.Section, symn sym.SymKind, forceType sym.SymKind) {
|
||||
state.assignDsymsToSection(sect, state.data[symn], forceType, aligndatsize)
|
||||
state.checkdatsize(symn)
|
||||
}
|
||||
|
||||
// allocateSingleSymSections walks through the bucketed data symbols
|
||||
// with type 'symn', creates a new section for each sym, and assigns
|
||||
// the sym to a newly created section. Section name is set from the
|
||||
// symbol name. "Seg" is the segment into which to place the new
|
||||
// section, "forceType" is the new sym.SymKind to assign to the symbol
|
||||
// within the section, and "rwx" holds section permissions.
|
||||
func (state *dodataState) allocateSingleSymSections(seg *sym.Segment, symn sym.SymKind, forceType sym.SymKind, rwx int) {
|
||||
for _, s := range state.data[symn] {
|
||||
sect := state.allocateDataSectionForSym(seg, s, rwx)
|
||||
s.Sect = sect
|
||||
s.Type = forceType
|
||||
s.Value = int64(uint64(state.datsize) - sect.Vaddr)
|
||||
state.datsize += s.Size
|
||||
sect.Length = uint64(state.datsize) - sect.Vaddr
|
||||
}
|
||||
state.checkdatsize(symn)
|
||||
}
|
||||
|
||||
// allocateNamedSectionAndAssignSyms creates a new section with the
|
||||
// specified name, then walks through the bucketed data symbols with
|
||||
// type 'symn' and assigns each of them to this new section. "Seg" is
|
||||
// the segment into which to place the new section, "secName" is the
|
||||
// name to give to the new section, "forceType" (if non-zero) contains
|
||||
// a new sym type to apply to each sym during the assignment, and
|
||||
// "rwx" holds section permissions.
|
||||
func (state *dodataState) allocateNamedSectionAndAssignSyms(seg *sym.Segment, secName string, symn sym.SymKind, forceType sym.SymKind, rwx int) *sym.Section {
|
||||
|
||||
sect := state.allocateNamedDataSection(seg, secName, []sym.SymKind{symn}, rwx)
|
||||
state.assignDsymsToSection(sect, state.data[symn], forceType, aligndatsize)
|
||||
return sect
|
||||
}
|
||||
|
||||
// allocateDataSections allocates sym.Section objects for data/rodata
|
||||
// (and related) symbols, and then assigns symbols to those sections.
|
||||
func (state *dodataState) allocateDataSections(ctxt *Link) {
|
||||
// Allocate sections.
|
||||
// Data is processed before segtext, because we need
|
||||
// to see all symbols in the .data and .bss sections in order
|
||||
// to generate garbage collection information.
|
||||
|
||||
// Writable data sections that do not need any specialized handling.
|
||||
writable := []sym.SymKind{
|
||||
sym.SBUILDINFO,
|
||||
sym.SELFSECT,
|
||||
sym.SMACHO,
|
||||
sym.SMACHOGOT,
|
||||
sym.SWINDOWS,
|
||||
}
|
||||
for _, symn := range writable {
|
||||
state.allocateSingleSymSections(&Segdata, symn, sym.SDATA, 06)
|
||||
}
|
||||
|
||||
// .got (and .toc on ppc64)
|
||||
if len(state.data[sym.SELFGOT]) > 0 {
|
||||
sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06)
|
||||
if ctxt.IsPPC64() {
|
||||
for _, s := range state.data[sym.SELFGOT] {
|
||||
// Resolve .TOC. symbol for this object file (ppc64)
|
||||
toc := ctxt.Syms.ROLookup(".TOC.", int(s.Version))
|
||||
if toc != nil {
|
||||
toc.Sect = sect
|
||||
toc.Outer = s
|
||||
toc.Sub = s.Sub
|
||||
s.Sub = toc
|
||||
|
||||
toc.Value = 0x8000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* pointer-free data */
|
||||
sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".noptrdata", sym.SNOPTRDATA, sym.SDATA, 06)
|
||||
ctxt.Syms.Lookup("runtime.noptrdata", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.enoptrdata", 0).Sect = sect
|
||||
|
||||
hasinitarr := ctxt.linkShared
|
||||
|
||||
/* shared library initializer */
|
||||
switch ctxt.BuildMode {
|
||||
case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin:
|
||||
hasinitarr = true
|
||||
}
|
||||
|
||||
if ctxt.HeadType == objabi.Haix {
|
||||
if len(state.data[sym.SINITARR]) > 0 {
|
||||
Errorf(nil, "XCOFF format doesn't allow .init_array section")
|
||||
}
|
||||
}
|
||||
|
||||
if hasinitarr && len(state.data[sym.SINITARR]) > 0 {
|
||||
state.allocateNamedSectionAndAssignSyms(&Segdata, ".init_array", sym.SINITARR, sym.Sxxx, 06)
|
||||
}
|
||||
|
||||
/* data */
|
||||
sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".data", sym.SDATA, sym.SDATA, 06)
|
||||
ctxt.Syms.Lookup("runtime.data", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.edata", 0).Sect = sect
|
||||
dataGcEnd := state.datsize - int64(sect.Vaddr)
|
||||
|
||||
// On AIX, TOC entries must be the last of .data
|
||||
// These aren't part of gc as they won't change during the runtime.
|
||||
state.assignToSection(sect, sym.SXCOFFTOC, sym.SDATA)
|
||||
state.checkdatsize(sym.SDATA)
|
||||
sect.Length = uint64(state.datsize) - sect.Vaddr
|
||||
|
||||
/* bss */
|
||||
sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".bss", sym.SBSS, sym.Sxxx, 06)
|
||||
ctxt.Syms.Lookup("runtime.bss", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.ebss", 0).Sect = sect
|
||||
bssGcEnd := state.datsize - int64(sect.Vaddr)
|
||||
|
||||
// Emit gcdata for bcc symbols now that symbol values have been assigned.
|
||||
gcsToEmit := []struct {
|
||||
symName string
|
||||
symKind sym.SymKind
|
||||
gcEnd int64
|
||||
}{
|
||||
{"runtime.gcdata", sym.SDATA, dataGcEnd},
|
||||
{"runtime.gcbss", sym.SBSS, bssGcEnd},
|
||||
}
|
||||
for _, g := range gcsToEmit {
|
||||
var gc GCProg
|
||||
gc.Init(ctxt, g.symName)
|
||||
for _, s := range state.data[g.symKind] {
|
||||
gc.AddSym(s)
|
||||
}
|
||||
gc.End(g.gcEnd)
|
||||
}
|
||||
|
||||
/* pointer-free bss */
|
||||
sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".noptrbss", sym.SNOPTRBSS, sym.Sxxx, 06)
|
||||
ctxt.Syms.Lookup("runtime.noptrbss", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.enoptrbss", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.end", 0).Sect = sect
|
||||
|
||||
// Coverage instrumentation counters for libfuzzer.
|
||||
if len(state.data[sym.SLIBFUZZER_EXTRA_COUNTER]) > 0 {
|
||||
state.allocateNamedSectionAndAssignSyms(&Segdata, "__libfuzzer_extra_counters", sym.SLIBFUZZER_EXTRA_COUNTER, sym.Sxxx, 06)
|
||||
}
|
||||
|
||||
if len(state.data[sym.STLSBSS]) > 0 {
|
||||
var sect *sym.Section
|
||||
// FIXME: not clear why it is sometimes necessary to suppress .tbss section creation.
|
||||
if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && (ctxt.LinkMode == LinkExternal || !*FlagD) {
|
||||
sect = addsection(ctxt.loader, ctxt.Arch, &Segdata, ".tbss", 06)
|
||||
sect.Align = int32(ctxt.Arch.PtrSize)
|
||||
// FIXME: why does this need to be set to zero?
|
||||
sect.Vaddr = 0
|
||||
}
|
||||
state.datsize = 0
|
||||
|
||||
for _, s := range state.data[sym.STLSBSS] {
|
||||
state.datsize = aligndatsize(state.datsize, s)
|
||||
s.Sect = sect
|
||||
s.Value = state.datsize
|
||||
state.datsize += s.Size
|
||||
}
|
||||
state.checkdatsize(sym.STLSBSS)
|
||||
|
||||
if sect != nil {
|
||||
sect.Length = uint64(state.datsize)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We finished data, begin read-only data.
|
||||
* Not all systems support a separate read-only non-executable data section.
|
||||
* ELF and Windows PE systems do.
|
||||
* OS X and Plan 9 do not.
|
||||
* And if we're using external linking mode, the point is moot,
|
||||
* since it's not our decision; that code expects the sections in
|
||||
* segtext.
|
||||
*/
|
||||
var segro *sym.Segment
|
||||
if ctxt.IsELF && ctxt.LinkMode == LinkInternal {
|
||||
segro = &Segrodata
|
||||
} else if ctxt.HeadType == objabi.Hwindows {
|
||||
segro = &Segrodata
|
||||
} else {
|
||||
segro = &Segtext
|
||||
}
|
||||
|
||||
state.datsize = 0
|
||||
|
||||
/* read-only executable ELF, Mach-O sections */
|
||||
if len(state.data[sym.STEXT]) != 0 {
|
||||
Errorf(nil, "dodata found an sym.STEXT symbol: %s", state.data[sym.STEXT][0].Name)
|
||||
}
|
||||
state.allocateSingleSymSections(&Segtext, sym.SELFRXSECT, sym.SRODATA, 04)
|
||||
|
||||
/* read-only data */
|
||||
sect = state.allocateNamedDataSection(segro, ".rodata", sym.ReadOnly, 04)
|
||||
ctxt.Syms.Lookup("runtime.rodata", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.erodata", 0).Sect = sect
|
||||
if !ctxt.UseRelro() {
|
||||
ctxt.Syms.Lookup("runtime.types", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.etypes", 0).Sect = sect
|
||||
}
|
||||
for _, symn := range sym.ReadOnly {
|
||||
symnStartValue := state.datsize
|
||||
state.assignToSection(sect, symn, sym.SRODATA)
|
||||
if ctxt.HeadType == objabi.Haix {
|
||||
// Read-only symbols might be wrapped inside their outer
|
||||
// symbol.
|
||||
// XCOFF symbol table needs to know the size of
|
||||
// these outer symbols.
|
||||
xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
|
||||
}
|
||||
}
|
||||
|
||||
/* read-only ELF, Mach-O sections */
|
||||
state.allocateSingleSymSections(segro, sym.SELFROSECT, sym.SRODATA, 04)
|
||||
state.allocateSingleSymSections(segro, sym.SMACHOPLT, sym.SRODATA, 04)
|
||||
|
||||
// There is some data that are conceptually read-only but are written to by
|
||||
// relocations. On GNU systems, we can arrange for the dynamic linker to
|
||||
// mprotect sections after relocations are applied by giving them write
|
||||
// permissions in the object file and calling them ".data.rel.ro.FOO". We
|
||||
// divide the .rodata section between actual .rodata and .data.rel.ro.rodata,
|
||||
// but for the other sections that this applies to, we just write a read-only
|
||||
// .FOO section or a read-write .data.rel.ro.FOO section depending on the
|
||||
// situation.
|
||||
// TODO(mwhudson): It would make sense to do this more widely, but it makes
|
||||
// the system linker segfault on darwin.
|
||||
const relroPerm = 06
|
||||
const fallbackPerm = 04
|
||||
relroSecPerm := fallbackPerm
|
||||
genrelrosecname := func(suffix string) string {
|
||||
return suffix
|
||||
}
|
||||
seg := segro
|
||||
|
||||
if ctxt.UseRelro() {
|
||||
segrelro := &Segrelrodata
|
||||
if ctxt.LinkMode == LinkExternal && ctxt.HeadType != objabi.Haix {
|
||||
// Using a separate segment with an external
|
||||
// linker results in some programs moving
|
||||
// their data sections unexpectedly, which
|
||||
// corrupts the moduledata. So we use the
|
||||
// rodata segment and let the external linker
|
||||
// sort out a rel.ro segment.
|
||||
segrelro = segro
|
||||
} else {
|
||||
// Reset datsize for new segment.
|
||||
state.datsize = 0
|
||||
}
|
||||
|
||||
genrelrosecname = func(suffix string) string {
|
||||
return ".data.rel.ro" + suffix
|
||||
}
|
||||
relroReadOnly := []sym.SymKind{}
|
||||
for _, symnro := range sym.ReadOnly {
|
||||
symn := sym.RelROMap[symnro]
|
||||
relroReadOnly = append(relroReadOnly, symn)
|
||||
}
|
||||
seg = segrelro
|
||||
relroSecPerm = relroPerm
|
||||
|
||||
/* data only written by relocations */
|
||||
sect = state.allocateNamedDataSection(segrelro, genrelrosecname(""), relroReadOnly, relroSecPerm)
|
||||
|
||||
ctxt.Syms.Lookup("runtime.types", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.etypes", 0).Sect = sect
|
||||
|
||||
for i, symnro := range sym.ReadOnly {
|
||||
if i == 0 && symnro == sym.STYPE && ctxt.HeadType != objabi.Haix {
|
||||
// Skip forward so that no type
|
||||
// reference uses a zero offset.
|
||||
// This is unlikely but possible in small
|
||||
// programs with no other read-only data.
|
||||
state.datsize++
|
||||
}
|
||||
|
||||
symn := sym.RelROMap[symnro]
|
||||
symnStartValue := state.datsize
|
||||
|
||||
for _, s := range state.data[symn] {
|
||||
if s.Outer != nil && s.Outer.Sect != nil && s.Outer.Sect != sect {
|
||||
Errorf(s, "s.Outer (%s) in different section from s, %s != %s", s.Outer.Name, s.Outer.Sect.Name, sect.Name)
|
||||
}
|
||||
}
|
||||
state.assignToSection(sect, symn, sym.SRODATA)
|
||||
if ctxt.HeadType == objabi.Haix {
|
||||
// Read-only symbols might be wrapped inside their outer
|
||||
// symbol.
|
||||
// XCOFF symbol table needs to know the size of
|
||||
// these outer symbols.
|
||||
xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
|
||||
}
|
||||
}
|
||||
|
||||
sect.Length = uint64(state.datsize) - sect.Vaddr
|
||||
}
|
||||
|
||||
/* typelink */
|
||||
sect = state.allocateNamedDataSection(seg, genrelrosecname(".typelink"), []sym.SymKind{sym.STYPELINK}, relroSecPerm)
|
||||
typelink := ctxt.Syms.Lookup("runtime.typelink", 0)
|
||||
typelink.Sect = sect
|
||||
typelink.Type = sym.SRODATA
|
||||
state.datsize += typelink.Size
|
||||
state.checkdatsize(sym.STYPELINK)
|
||||
sect.Length = uint64(state.datsize) - sect.Vaddr
|
||||
|
||||
/* itablink */
|
||||
sect = state.allocateNamedSectionAndAssignSyms(seg, genrelrosecname(".itablink"), sym.SITABLINK, sym.Sxxx, relroSecPerm)
|
||||
ctxt.Syms.Lookup("runtime.itablink", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.eitablink", 0).Sect = sect
|
||||
if ctxt.HeadType == objabi.Haix {
|
||||
// Store .itablink size because its symbols are wrapped
|
||||
// under an outer symbol: runtime.itablink.
|
||||
xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SITABLINK)
|
||||
}
|
||||
|
||||
/* gosymtab */
|
||||
sect = state.allocateNamedSectionAndAssignSyms(seg, genrelrosecname(".gosymtab"), sym.SSYMTAB, sym.SRODATA, relroSecPerm)
|
||||
ctxt.Syms.Lookup("runtime.symtab", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.esymtab", 0).Sect = sect
|
||||
|
||||
/* gopclntab */
|
||||
sect = state.allocateNamedSectionAndAssignSyms(seg, genrelrosecname(".gopclntab"), sym.SPCLNTAB, sym.SRODATA, relroSecPerm)
|
||||
ctxt.Syms.Lookup("runtime.pclntab", 0).Sect = sect
|
||||
ctxt.Syms.Lookup("runtime.epclntab", 0).Sect = sect
|
||||
|
||||
// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
|
||||
if state.datsize != int64(uint32(state.datsize)) {
|
||||
Errorf(nil, "read-only data segment too large: %d", state.datsize)
|
||||
}
|
||||
|
||||
for symn := sym.SELFRXSECT; symn < sym.SXREF; symn++ {
|
||||
ctxt.datap = append(ctxt.datap, state.data[symn]...)
|
||||
}
|
||||
}
|
||||
|
||||
// allocateDwarfSections allocates sym.Section objects for DWARF
|
||||
// symbols, and assigns symbols to sections.
|
||||
func (state *dodataState) allocateDwarfSections(ctxt *Link) {
|
||||
|
||||
alignOne := func(datsize int64, s *sym.Symbol) int64 { return datsize }
|
||||
|
||||
for i := 0; i < len(dwarfp); i++ {
|
||||
// First the section symbol.
|
||||
s := dwarfp[i].secSym()
|
||||
sect := state.allocateNamedDataSection(&Segdwarf, s.Name, []sym.SymKind{}, 04)
|
||||
sect.Sym = s
|
||||
s.Sect = sect
|
||||
curType := s.Type
|
||||
s.Type = sym.SRODATA
|
||||
s.Value = int64(uint64(state.datsize) - sect.Vaddr)
|
||||
state.datsize += s.Size
|
||||
|
||||
// Then any sub-symbols for the section symbol.
|
||||
subSyms := dwarfp[i].subSyms()
|
||||
state.assignDsymsToSection(sect, subSyms, sym.SRODATA, alignOne)
|
||||
|
||||
for j := 0; j < len(subSyms); j++ {
|
||||
s := subSyms[j]
|
||||
if ctxt.HeadType == objabi.Haix && curType == sym.SDWARFLOC {
|
||||
// Update the size of .debug_loc for this symbol's
|
||||
// package.
|
||||
addDwsectCUSize(".debug_loc", s.File, uint64(s.Size))
|
||||
}
|
||||
}
|
||||
sect.Length = uint64(state.datsize) - sect.Vaddr
|
||||
state.checkdatsize(curType)
|
||||
}
|
||||
}
|
||||
|
||||
func dodataSect(ctxt *Link, symn sym.SymKind, syms []*sym.Symbol, symToIdx map[*sym.Symbol]loader.Sym) (result []*sym.Symbol, maxAlign int32) {
|
||||
if ctxt.HeadType == objabi.Hdarwin {
|
||||
// Some symbols may no longer belong in syms
|
||||
// due to movement in machosymorder.
|
||||
newSyms := make([]*sym.Symbol, 0, len(syms))
|
||||
for _, s := range syms {
|
||||
if s.Type == symn {
|
||||
newSyms = append(newSyms, s)
|
||||
}
|
||||
}
|
||||
syms = newSyms
|
||||
}
|
||||
|
||||
var head, tail *sym.Symbol
|
||||
symsSort := make([]dataSortKey, 0, len(syms))
|
||||
for _, s := range syms {
|
||||
if s.Attr.OnList() {
|
||||
log.Fatalf("symbol %s listed multiple times", s.Name)
|
||||
}
|
||||
s.Attr |= sym.AttrOnList
|
||||
switch {
|
||||
case s.Size < int64(len(s.P)):
|
||||
Errorf(s, "initialize bounds (%d < %d)", s.Size, len(s.P))
|
||||
case s.Size < 0:
|
||||
Errorf(s, "negative size (%d bytes)", s.Size)
|
||||
case s.Size > cutoff:
|
||||
Errorf(s, "symbol too large (%d bytes)", s.Size)
|
||||
}
|
||||
|
||||
// If the usually-special section-marker symbols are being laid
|
||||
// out as regular symbols, put them either at the beginning or
|
||||
// end of their section.
|
||||
if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
|
||||
switch s.Name {
|
||||
case "runtime.text", "runtime.bss", "runtime.data", "runtime.types", "runtime.rodata":
|
||||
head = s
|
||||
continue
|
||||
case "runtime.etext", "runtime.ebss", "runtime.edata", "runtime.etypes", "runtime.erodata":
|
||||
tail = s
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
key := dataSortKey{
|
||||
size: s.Size,
|
||||
name: s.Name,
|
||||
sym: s,
|
||||
symIdx: symToIdx[s],
|
||||
}
|
||||
|
||||
switch s.Type {
|
||||
case sym.SELFGOT:
|
||||
// For ppc64, we want to interleave the .got and .toc sections
|
||||
// from input files. Both are type sym.SELFGOT, so in that case
|
||||
// we skip size comparison and fall through to the name
|
||||
// comparison (conveniently, .got sorts before .toc).
|
||||
key.size = 0
|
||||
}
|
||||
|
||||
symsSort = append(symsSort, key)
|
||||
}
|
||||
|
||||
sort.Sort(bySizeAndName(symsSort))
|
||||
|
||||
off := 0
|
||||
if head != nil {
|
||||
syms[0] = head
|
||||
off++
|
||||
}
|
||||
for i, symSort := range symsSort {
|
||||
syms[i+off] = symSort.sym
|
||||
align := symalign(symSort.sym)
|
||||
if maxAlign < align {
|
||||
maxAlign = align
|
||||
}
|
||||
}
|
||||
if tail != nil {
|
||||
syms[len(syms)-1] = tail
|
||||
}
|
||||
|
||||
if ctxt.IsELF && symn == sym.SELFROSECT {
|
||||
// Make .rela and .rela.plt contiguous, the ELF ABI requires this
|
||||
// and Solaris actually cares.
|
||||
reli, plti := -1, -1
|
||||
for i, s := range syms {
|
||||
switch s.Name {
|
||||
case ".rel.plt", ".rela.plt":
|
||||
plti = i
|
||||
case ".rel", ".rela":
|
||||
reli = i
|
||||
}
|
||||
}
|
||||
if reli >= 0 && plti >= 0 && plti != reli+1 {
|
||||
var first, second int
|
||||
if plti > reli {
|
||||
first, second = reli, plti
|
||||
} else {
|
||||
first, second = plti, reli
|
||||
}
|
||||
rel, plt := syms[reli], syms[plti]
|
||||
copy(syms[first+2:], syms[first+1:second])
|
||||
syms[first+0] = rel
|
||||
syms[first+1] = plt
|
||||
|
||||
// Make sure alignment doesn't introduce a gap.
|
||||
// Setting the alignment explicitly prevents
|
||||
// symalign from basing it on the size and
|
||||
// getting it wrong.
|
||||
rel.Align = int32(ctxt.Arch.RegSize)
|
||||
plt.Align = int32(ctxt.Arch.RegSize)
|
||||
}
|
||||
}
|
||||
|
||||
return syms, maxAlign
|
||||
}
|
||||
|
@ -5,12 +5,9 @@
|
||||
package ld
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/internal/sys"
|
||||
"cmd/link/internal/sym"
|
||||
"debug/elf"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Decoding the type.* symbols. This has to be in sync with
|
||||
@ -29,23 +26,6 @@ const (
|
||||
tflagExtraStar = 1 << 1
|
||||
)
|
||||
|
||||
func decodeReloc(s *sym.Symbol, off int32) *sym.Reloc {
|
||||
for i := range s.R {
|
||||
if s.R[i].Off == off {
|
||||
return &s.R[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeRelocSym(s *sym.Symbol, off int32) *sym.Symbol {
|
||||
r := decodeReloc(s, off)
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
return r.Sym
|
||||
}
|
||||
|
||||
func decodeInuxi(arch *sys.Arch, p []byte, sz int) uint64 {
|
||||
switch sz {
|
||||
case 2:
|
||||
@ -103,26 +83,6 @@ func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type.commonType.gc
|
||||
func decodetypeGcprog(ctxt *Link, s *sym.Symbol) []byte {
|
||||
if s.Type == sym.SDYNIMPORT {
|
||||
addr := decodetypeGcprogShlib(ctxt, s.P)
|
||||
sect := findShlibSection(ctxt, s.File, addr)
|
||||
if sect != nil {
|
||||
// A gcprog is a 4-byte uint32 indicating length, followed by
|
||||
// the actual program.
|
||||
progsize := make([]byte, 4)
|
||||
sect.ReadAt(progsize, int64(addr-sect.Addr))
|
||||
progbytes := make([]byte, ctxt.Arch.ByteOrder.Uint32(progsize))
|
||||
sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
|
||||
return append(progsize, progbytes...)
|
||||
}
|
||||
Exitf("cannot find gcprog for %s", s.Name)
|
||||
return nil
|
||||
}
|
||||
return decodeRelocSym(s, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize)).P
|
||||
}
|
||||
|
||||
func decodetypeGcprogShlib(ctxt *Link, data []byte) uint64 {
|
||||
if ctxt.Arch.Family == sys.ARM64 {
|
||||
return 0
|
||||
@ -130,51 +90,6 @@ func decodetypeGcprogShlib(ctxt *Link, data []byte) uint64 {
|
||||
return decodeInuxi(ctxt.Arch, data[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
|
||||
}
|
||||
|
||||
func decodetypeGcmask(ctxt *Link, s *sym.Symbol) []byte {
|
||||
if s.Type == sym.SDYNIMPORT {
|
||||
addr := decodetypeGcprogShlib(ctxt, s.P)
|
||||
ptrdata := decodetypePtrdata(ctxt.Arch, s.P)
|
||||
sect := findShlibSection(ctxt, s.File, addr)
|
||||
if sect != nil {
|
||||
r := make([]byte, ptrdata/int64(ctxt.Arch.PtrSize))
|
||||
sect.ReadAt(r, int64(addr-sect.Addr))
|
||||
return r
|
||||
}
|
||||
Exitf("cannot find gcmask for %s", s.Name)
|
||||
return nil
|
||||
}
|
||||
mask := decodeRelocSym(s, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
|
||||
return mask.P
|
||||
}
|
||||
|
||||
// Type.ArrayType.elem and Type.SliceType.Elem
|
||||
func decodetypeArrayElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
|
||||
return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
}
|
||||
|
||||
func decodetypeArrayLen(arch *sys.Arch, s *sym.Symbol) int64 {
|
||||
return int64(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
|
||||
}
|
||||
|
||||
// Type.PtrType.elem
|
||||
func decodetypePtrElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
|
||||
return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
}
|
||||
|
||||
// Type.MapType.key, elem
|
||||
func decodetypeMapKey(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
|
||||
return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
}
|
||||
|
||||
func decodetypeMapValue(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
|
||||
return decodeRelocSym(s, int32(commonsize(arch))+int32(arch.PtrSize)) // 0x20 / 0x38
|
||||
}
|
||||
|
||||
// Type.ChanType.elem
|
||||
func decodetypeChanElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
|
||||
return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
|
||||
}
|
||||
|
||||
// Type.FuncType.dotdotdot
|
||||
func decodetypeFuncDotdotdot(arch *sys.Arch, p []byte) bool {
|
||||
return uint16(decodeInuxi(arch, p[commonsize(arch)+2:], 2))&(1<<15) != 0
|
||||
@ -189,75 +104,6 @@ func decodetypeFuncOutCount(arch *sys.Arch, p []byte) int {
|
||||
return int(uint16(decodeInuxi(arch, p[commonsize(arch)+2:], 2)) & (1<<15 - 1))
|
||||
}
|
||||
|
||||
func decodetypeFuncInType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
|
||||
uadd := commonsize(arch) + 4
|
||||
if arch.PtrSize == 8 {
|
||||
uadd += 4
|
||||
}
|
||||
if decodetypeHasUncommon(arch, s.P) {
|
||||
uadd += uncommonSize()
|
||||
}
|
||||
return decodeRelocSym(s, int32(uadd+i*arch.PtrSize))
|
||||
}
|
||||
|
||||
func decodetypeFuncOutType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
|
||||
return decodetypeFuncInType(arch, s, i+decodetypeFuncInCount(arch, s.P))
|
||||
}
|
||||
|
||||
// Type.StructType.fields.Slice::length
|
||||
func decodetypeStructFieldCount(arch *sys.Arch, s *sym.Symbol) int {
|
||||
return int(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
|
||||
}
|
||||
|
||||
func decodetypeStructFieldArrayOff(arch *sys.Arch, s *sym.Symbol, i int) int {
|
||||
off := commonsize(arch) + 4*arch.PtrSize
|
||||
if decodetypeHasUncommon(arch, s.P) {
|
||||
off += uncommonSize()
|
||||
}
|
||||
off += i * structfieldSize(arch)
|
||||
return off
|
||||
}
|
||||
|
||||
// decodetypeStr returns the contents of an rtype's str field (a nameOff).
|
||||
func decodetypeStr(arch *sys.Arch, s *sym.Symbol) string {
|
||||
str := decodetypeName(s, 4*arch.PtrSize+8)
|
||||
if s.P[2*arch.PtrSize+4]&tflagExtraStar != 0 {
|
||||
return str[1:]
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// decodetypeName decodes the name from a reflect.name.
|
||||
func decodetypeName(s *sym.Symbol, off int) string {
|
||||
r := decodeReloc(s, int32(off))
|
||||
if r == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
data := r.Sym.P
|
||||
namelen := int(uint16(data[1])<<8 | uint16(data[2]))
|
||||
return string(data[3 : 3+namelen])
|
||||
}
|
||||
|
||||
func decodetypeStructFieldName(arch *sys.Arch, s *sym.Symbol, i int) string {
|
||||
off := decodetypeStructFieldArrayOff(arch, s, i)
|
||||
return decodetypeName(s, off)
|
||||
}
|
||||
|
||||
func decodetypeStructFieldType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
|
||||
off := decodetypeStructFieldArrayOff(arch, s, i)
|
||||
return decodeRelocSym(s, int32(off+arch.PtrSize))
|
||||
}
|
||||
|
||||
func decodetypeStructFieldOffs(arch *sys.Arch, s *sym.Symbol, i int) int64 {
|
||||
return decodetypeStructFieldOffsAnon(arch, s, i) >> 1
|
||||
}
|
||||
|
||||
func decodetypeStructFieldOffsAnon(arch *sys.Arch, s *sym.Symbol, i int) int64 {
|
||||
off := decodetypeStructFieldArrayOff(arch, s, i)
|
||||
return int64(decodeInuxi(arch, s.P[off+2*arch.PtrSize:], arch.PtrSize))
|
||||
}
|
||||
|
||||
// InterfaceType.methods.length
|
||||
func decodetypeIfaceMethodCount(arch *sys.Arch, p []byte) int64 {
|
||||
return int64(decodeInuxi(arch, p[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
|
||||
@ -279,91 +125,3 @@ const (
|
||||
kindStruct = 25
|
||||
kindMask = (1 << 5) - 1
|
||||
)
|
||||
|
||||
// decodeMethodSig decodes an array of method signature information.
|
||||
// Each element of the array is size bytes. The first 4 bytes is a
|
||||
// nameOff for the method name, and the next 4 bytes is a typeOff for
|
||||
// the function type.
|
||||
//
|
||||
// Conveniently this is the layout of both runtime.method and runtime.imethod.
|
||||
func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []methodsig {
|
||||
var buf bytes.Buffer
|
||||
var methods []methodsig
|
||||
for i := 0; i < count; i++ {
|
||||
buf.WriteString(decodetypeName(s, off))
|
||||
mtypSym := decodeRelocSym(s, int32(off+4))
|
||||
|
||||
buf.WriteRune('(')
|
||||
inCount := decodetypeFuncInCount(arch, mtypSym.P)
|
||||
for i := 0; i < inCount; i++ {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
buf.WriteString(decodetypeFuncInType(arch, mtypSym, i).Name)
|
||||
}
|
||||
buf.WriteString(") (")
|
||||
outCount := decodetypeFuncOutCount(arch, mtypSym.P)
|
||||
for i := 0; i < outCount; i++ {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
buf.WriteString(decodetypeFuncOutType(arch, mtypSym, i).Name)
|
||||
}
|
||||
buf.WriteRune(')')
|
||||
|
||||
off += size
|
||||
methods = append(methods, methodsig(buf.String()))
|
||||
buf.Reset()
|
||||
}
|
||||
return methods
|
||||
}
|
||||
|
||||
func decodeIfaceMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
|
||||
if decodetypeKind(arch, s.P)&kindMask != kindInterface {
|
||||
panic(fmt.Sprintf("symbol %q is not an interface", s.Name))
|
||||
}
|
||||
r := decodeReloc(s, int32(commonsize(arch)+arch.PtrSize))
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
if r.Sym != s {
|
||||
panic(fmt.Sprintf("imethod slice pointer in %q leads to a different symbol", s.Name))
|
||||
}
|
||||
off := int(r.Add) // array of reflect.imethod values
|
||||
numMethods := int(decodetypeIfaceMethodCount(arch, s.P))
|
||||
sizeofIMethod := 4 + 4
|
||||
return decodeMethodSig(arch, s, off, sizeofIMethod, numMethods)
|
||||
}
|
||||
|
||||
func decodetypeMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
|
||||
if !decodetypeHasUncommon(arch, s.P) {
|
||||
panic(fmt.Sprintf("no methods on %q", s.Name))
|
||||
}
|
||||
off := commonsize(arch) // reflect.rtype
|
||||
switch decodetypeKind(arch, s.P) & kindMask {
|
||||
case kindStruct: // reflect.structType
|
||||
off += 4 * arch.PtrSize
|
||||
case kindPtr: // reflect.ptrType
|
||||
off += arch.PtrSize
|
||||
case kindFunc: // reflect.funcType
|
||||
off += arch.PtrSize // 4 bytes, pointer aligned
|
||||
case kindSlice: // reflect.sliceType
|
||||
off += arch.PtrSize
|
||||
case kindArray: // reflect.arrayType
|
||||
off += 3 * arch.PtrSize
|
||||
case kindChan: // reflect.chanType
|
||||
off += 2 * arch.PtrSize
|
||||
case kindMap: // reflect.mapType
|
||||
off += 4*arch.PtrSize + 8
|
||||
case kindInterface: // reflect.interfaceType
|
||||
off += 3 * arch.PtrSize
|
||||
default:
|
||||
// just Sizeof(rtype)
|
||||
}
|
||||
|
||||
mcount := int(decodeInuxi(arch, s.P[off+4:], 2))
|
||||
moff := int(decodeInuxi(arch, s.P[off+4+2+2:], 4))
|
||||
off += moff // offset to array of reflect.method values
|
||||
const sizeofMethod = 4 * 4 // sizeof reflect.method in program
|
||||
return decodeMethodSig(arch, s, off, sizeofMethod, mcount)
|
||||
}
|
||||
|
@ -2343,93 +2343,6 @@ elfobj:
|
||||
}
|
||||
}
|
||||
|
||||
func elfadddynsym(target *Target, syms *ArchSyms, s *sym.Symbol) {
|
||||
if elf64 {
|
||||
s.Dynid = int32(Nelfsym)
|
||||
Nelfsym++
|
||||
|
||||
d := syms.DynSym
|
||||
|
||||
name := s.Extname()
|
||||
d.AddUint32(target.Arch, uint32(Addstring(syms.DynStr, name)))
|
||||
|
||||
/* type */
|
||||
t := STB_GLOBAL << 4
|
||||
|
||||
if s.Attr.CgoExport() && s.Type == sym.STEXT {
|
||||
t |= STT_FUNC
|
||||
} else {
|
||||
t |= STT_OBJECT
|
||||
}
|
||||
d.AddUint8(uint8(t))
|
||||
|
||||
/* reserved */
|
||||
d.AddUint8(0)
|
||||
|
||||
/* section where symbol is defined */
|
||||
if s.Type == sym.SDYNIMPORT {
|
||||
d.AddUint16(target.Arch, SHN_UNDEF)
|
||||
} else {
|
||||
d.AddUint16(target.Arch, 1)
|
||||
}
|
||||
|
||||
/* value */
|
||||
if s.Type == sym.SDYNIMPORT {
|
||||
d.AddUint64(target.Arch, 0)
|
||||
} else {
|
||||
d.AddAddr(target.Arch, s)
|
||||
}
|
||||
|
||||
/* size of object */
|
||||
d.AddUint64(target.Arch, uint64(s.Size))
|
||||
|
||||
if target.Arch.Family == sys.AMD64 && !s.Attr.CgoExportDynamic() && s.Dynimplib() != "" && !seenlib[s.Dynimplib()] {
|
||||
elfWriteDynEnt(target.Arch, syms.Dynamic, DT_NEEDED, uint64(Addstring(syms.DynStr, s.Dynimplib())))
|
||||
}
|
||||
} else {
|
||||
s.Dynid = int32(Nelfsym)
|
||||
Nelfsym++
|
||||
|
||||
d := syms.DynSym
|
||||
|
||||
/* name */
|
||||
name := s.Extname()
|
||||
|
||||
d.AddUint32(target.Arch, uint32(Addstring(syms.DynStr, name)))
|
||||
|
||||
/* value */
|
||||
if s.Type == sym.SDYNIMPORT {
|
||||
d.AddUint32(target.Arch, 0)
|
||||
} else {
|
||||
d.AddAddr(target.Arch, s)
|
||||
}
|
||||
|
||||
/* size of object */
|
||||
d.AddUint32(target.Arch, uint32(s.Size))
|
||||
|
||||
/* type */
|
||||
t := STB_GLOBAL << 4
|
||||
|
||||
// TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386.
|
||||
if target.Arch.Family == sys.I386 && s.Attr.CgoExport() && s.Type == sym.STEXT {
|
||||
t |= STT_FUNC
|
||||
} else if target.Arch.Family == sys.ARM && s.Attr.CgoExportDynamic() && s.Type == sym.STEXT {
|
||||
t |= STT_FUNC
|
||||
} else {
|
||||
t |= STT_OBJECT
|
||||
}
|
||||
d.AddUint8(uint8(t))
|
||||
d.AddUint8(0)
|
||||
|
||||
/* shndx */
|
||||
if s.Type == sym.SDYNIMPORT {
|
||||
d.AddUint16(target.Arch, SHN_UNDEF)
|
||||
} else {
|
||||
d.AddUint16(target.Arch, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func elfadddynsym2(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
|
||||
ldr.SetSymDynid(s, int32(Nelfsym))
|
||||
Nelfsym++
|
||||
|
@ -5,7 +5,6 @@
|
||||
package ld
|
||||
|
||||
import (
|
||||
"cmd/internal/sys"
|
||||
"cmd/link/internal/sym"
|
||||
)
|
||||
|
||||
@ -24,146 +23,3 @@ func elfsetstring(s *sym.Symbol, str string, off int) {
|
||||
elfstr[nelfstr].off = off
|
||||
nelfstr++
|
||||
}
|
||||
|
||||
func elfWriteDynEntSym(arch *sys.Arch, s *sym.Symbol, tag int, t *sym.Symbol) {
|
||||
Elfwritedynentsymplus(arch, s, tag, t, 0)
|
||||
}
|
||||
|
||||
func elfdynhash(ctxt *Link) {
|
||||
if !ctxt.IsELF {
|
||||
return
|
||||
}
|
||||
|
||||
nsym := Nelfsym
|
||||
s := ctxt.Syms.Lookup(".hash", 0)
|
||||
s.Type = sym.SELFROSECT
|
||||
s.Attr |= sym.AttrReachable
|
||||
|
||||
i := nsym
|
||||
nbucket := 1
|
||||
for i > 0 {
|
||||
nbucket++
|
||||
i >>= 1
|
||||
}
|
||||
|
||||
var needlib *Elflib
|
||||
need := make([]*Elfaux, nsym)
|
||||
chain := make([]uint32, nsym)
|
||||
buckets := make([]uint32, nbucket)
|
||||
|
||||
for _, sy := range ctxt.loader.Syms {
|
||||
if sy == nil {
|
||||
continue
|
||||
}
|
||||
if sy.Dynid <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if sy.Dynimpvers() != "" {
|
||||
need[sy.Dynid] = addelflib(&needlib, sy.Dynimplib(), sy.Dynimpvers())
|
||||
}
|
||||
|
||||
name := sy.Extname()
|
||||
hc := elfhash(name)
|
||||
|
||||
b := hc % uint32(nbucket)
|
||||
chain[sy.Dynid] = buckets[b]
|
||||
buckets[b] = uint32(sy.Dynid)
|
||||
}
|
||||
|
||||
// s390x (ELF64) hash table entries are 8 bytes
|
||||
if ctxt.Arch.Family == sys.S390X {
|
||||
s.AddUint64(ctxt.Arch, uint64(nbucket))
|
||||
s.AddUint64(ctxt.Arch, uint64(nsym))
|
||||
for i := 0; i < nbucket; i++ {
|
||||
s.AddUint64(ctxt.Arch, uint64(buckets[i]))
|
||||
}
|
||||
for i := 0; i < nsym; i++ {
|
||||
s.AddUint64(ctxt.Arch, uint64(chain[i]))
|
||||
}
|
||||
} else {
|
||||
s.AddUint32(ctxt.Arch, uint32(nbucket))
|
||||
s.AddUint32(ctxt.Arch, uint32(nsym))
|
||||
for i := 0; i < nbucket; i++ {
|
||||
s.AddUint32(ctxt.Arch, buckets[i])
|
||||
}
|
||||
for i := 0; i < nsym; i++ {
|
||||
s.AddUint32(ctxt.Arch, chain[i])
|
||||
}
|
||||
}
|
||||
|
||||
// version symbols
|
||||
dynstr := ctxt.Syms.Lookup(".dynstr", 0)
|
||||
|
||||
s = ctxt.Syms.Lookup(".gnu.version_r", 0)
|
||||
i = 2
|
||||
nfile := 0
|
||||
for l := needlib; l != nil; l = l.next {
|
||||
nfile++
|
||||
|
||||
// header
|
||||
s.AddUint16(ctxt.Arch, 1) // table version
|
||||
j := 0
|
||||
for x := l.aux; x != nil; x = x.next {
|
||||
j++
|
||||
}
|
||||
s.AddUint16(ctxt.Arch, uint16(j)) // aux count
|
||||
s.AddUint32(ctxt.Arch, uint32(Addstring(dynstr, l.file))) // file string offset
|
||||
s.AddUint32(ctxt.Arch, 16) // offset from header to first aux
|
||||
if l.next != nil {
|
||||
s.AddUint32(ctxt.Arch, 16+uint32(j)*16) // offset from this header to next
|
||||
} else {
|
||||
s.AddUint32(ctxt.Arch, 0)
|
||||
}
|
||||
|
||||
for x := l.aux; x != nil; x = x.next {
|
||||
x.num = i
|
||||
i++
|
||||
|
||||
// aux struct
|
||||
s.AddUint32(ctxt.Arch, elfhash(x.vers)) // hash
|
||||
s.AddUint16(ctxt.Arch, 0) // flags
|
||||
s.AddUint16(ctxt.Arch, uint16(x.num)) // other - index we refer to this by
|
||||
s.AddUint32(ctxt.Arch, uint32(Addstring(dynstr, x.vers))) // version string offset
|
||||
if x.next != nil {
|
||||
s.AddUint32(ctxt.Arch, 16) // offset from this aux to next
|
||||
} else {
|
||||
s.AddUint32(ctxt.Arch, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// version references
|
||||
s = ctxt.Syms.Lookup(".gnu.version", 0)
|
||||
|
||||
for i := 0; i < nsym; i++ {
|
||||
if i == 0 {
|
||||
s.AddUint16(ctxt.Arch, 0) // first entry - no symbol
|
||||
} else if need[i] == nil {
|
||||
s.AddUint16(ctxt.Arch, 1) // global
|
||||
} else {
|
||||
s.AddUint16(ctxt.Arch, uint16(need[i].num))
|
||||
}
|
||||
}
|
||||
|
||||
s = ctxt.Syms.Lookup(".dynamic", 0)
|
||||
elfverneed = nfile
|
||||
if elfverneed != 0 {
|
||||
elfWriteDynEntSym(ctxt.Arch, s, DT_VERNEED, ctxt.Syms.Lookup(".gnu.version_r", 0))
|
||||
elfWriteDynEnt(ctxt.Arch, s, DT_VERNEEDNUM, uint64(nfile))
|
||||
elfWriteDynEntSym(ctxt.Arch, s, DT_VERSYM, ctxt.Syms.Lookup(".gnu.version", 0))
|
||||
}
|
||||
|
||||
sy := ctxt.Syms.Lookup(elfRelType+".plt", 0)
|
||||
if sy.Size > 0 {
|
||||
if elfRelType == ".rela" {
|
||||
elfWriteDynEnt(ctxt.Arch, s, DT_PLTREL, DT_RELA)
|
||||
} else {
|
||||
elfWriteDynEnt(ctxt.Arch, s, DT_PLTREL, DT_REL)
|
||||
}
|
||||
elfWriteDynEntSymSize(ctxt.Arch, s, DT_PLTRELSZ, sy)
|
||||
elfWriteDynEntSym(ctxt.Arch, s, DT_JMPREL, sy)
|
||||
}
|
||||
|
||||
elfWriteDynEnt(ctxt.Arch, s, DT_NULL, 0)
|
||||
}
|
||||
|
@ -347,22 +347,6 @@ func Adddynsym2(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym
|
||||
}
|
||||
}
|
||||
|
||||
func Adddynsym(target *Target, syms *ArchSyms, s *sym.Symbol) {
|
||||
if s.Dynid >= 0 || target.LinkMode == LinkExternal {
|
||||
return
|
||||
}
|
||||
|
||||
if target.IsELF {
|
||||
elfadddynsym(target, syms, s)
|
||||
} else if target.HeadType == objabi.Hdarwin {
|
||||
Errorf(s, "adddynsym: missed symbol (Extname=%s)", s.Extname())
|
||||
} else if target.HeadType == objabi.Hwindows {
|
||||
// already taken care of
|
||||
} else {
|
||||
Errorf(s, "adddynsym: unsupported binary format")
|
||||
}
|
||||
}
|
||||
|
||||
func fieldtrack(arch *sys.Arch, l *loader.Loader) {
|
||||
var buf bytes.Buffer
|
||||
for i := loader.Sym(1); i < loader.Sym(l.NSym()); i++ {
|
||||
|
@ -96,7 +96,6 @@ var (
|
||||
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
|
||||
memprofile = flag.String("memprofile", "", "write memory profile to `file`")
|
||||
memprofilerate = flag.Int64("memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
|
||||
flagnewDoData = flag.Bool("newdodata", true, "New style dodata")
|
||||
|
||||
benchmarkFlag = flag.String("benchmark", "", "set to 'mem' or 'cpu' to enable phase benchmarking")
|
||||
benchmarkFileFlag = flag.String("benchmarkprofile", "", "emit phase profiles to `base`_phase.{cpu,mem}prof")
|
||||
@ -299,16 +298,10 @@ func Main(arch *sys.Arch, theArch Arch) {
|
||||
dwarfGenerateDebugSyms(ctxt)
|
||||
bench.Start("symtab")
|
||||
symGroupType := ctxt.symtab()
|
||||
if *flagnewDoData {
|
||||
bench.Start("dodata")
|
||||
ctxt.dodata2(symGroupType)
|
||||
}
|
||||
bench.Start("loadlibfull")
|
||||
ctxt.loadlibfull(symGroupType) // XXX do it here for now
|
||||
if !*flagnewDoData {
|
||||
bench.Start("dodata")
|
||||
ctxt.dodata()
|
||||
}
|
||||
bench.Start("address")
|
||||
order := ctxt.address()
|
||||
bench.Start("dwarfcompress")
|
||||
|
@ -1,140 +0,0 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ppc64
|
||||
|
||||
import (
|
||||
"cmd/internal/objabi"
|
||||
"cmd/link/internal/ld"
|
||||
"cmd/link/internal/loader"
|
||||
"cmd/link/internal/sym"
|
||||
"debug/elf"
|
||||
)
|
||||
|
||||
// Temporary dumping ground for sym.Symbol version of helper
|
||||
// functions in asm.go, still being used for some oses.
|
||||
// FIXME: get rid of this file when dodata() is completely
|
||||
// converted.
|
||||
|
||||
func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
if target.IsElf() {
|
||||
return addelfdynrel(target, syms, s, r)
|
||||
} else if target.IsAIX() {
|
||||
return ld.Xcoffadddynrel(target, ldr, s, r)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func addelfdynrel(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
targ := r.Sym
|
||||
r.InitExt()
|
||||
|
||||
switch r.Type {
|
||||
default:
|
||||
if r.Type >= objabi.ElfRelocOffset {
|
||||
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(target.Arch, r.Type))
|
||||
return false
|
||||
}
|
||||
|
||||
// Handle relocations found in ELF object files.
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
|
||||
r.Type = objabi.R_CALLPOWER
|
||||
|
||||
// This is a local call, so the caller isn't setting
|
||||
// up r12 and r2 is the same for the caller and
|
||||
// callee. Hence, we need to go to the local entry
|
||||
// point. (If we don't do this, the callee will try
|
||||
// to use r12 to compute r2.)
|
||||
r.Add += int64(r.Sym.Localentry()) * 4
|
||||
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
// Should have been handled in elfsetupplt
|
||||
ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Add += 4
|
||||
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64):
|
||||
r.Type = objabi.R_ADDR
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
// These happen in .toc sections
|
||||
ld.Adddynsym(target, syms, targ)
|
||||
|
||||
rela := syms.Rela
|
||||
rela.AddAddrPlus(target.Arch, s, int64(r.Off))
|
||||
rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_PPC64_ADDR64)))
|
||||
rela.AddUint64(target.Arch, uint64(r.Add))
|
||||
r.Type = objabi.ElfRelocOffset // ignore during relocsym
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
|
||||
r.Type = objabi.R_POWER_TOC
|
||||
r.Variant = sym.RV_POWER_LO | sym.RV_CHECK_OVERFLOW
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
|
||||
r.Type = objabi.R_POWER_TOC
|
||||
r.Variant = sym.RV_POWER_LO
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
|
||||
r.Type = objabi.R_POWER_TOC
|
||||
r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
|
||||
r.Type = objabi.R_POWER_TOC
|
||||
r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
|
||||
r.Type = objabi.R_POWER_TOC
|
||||
r.Variant = sym.RV_POWER_DS | sym.RV_CHECK_OVERFLOW
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
|
||||
r.Type = objabi.R_POWER_TOC
|
||||
r.Variant = sym.RV_POWER_DS
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Variant = sym.RV_POWER_LO
|
||||
r.Add += 2 // Compensate for relocation size of 2
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
|
||||
r.Add += 2
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
|
||||
r.Add += 2
|
||||
return true
|
||||
}
|
||||
|
||||
// Handle references to ELF symbols from our own object files.
|
||||
if targ.Type != sym.SDYNIMPORT {
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO(austin): Translate our relocations to ELF
|
||||
|
||||
return false
|
||||
}
|
@ -49,7 +49,6 @@ func Init() (*sys.Arch, ld.Arch) {
|
||||
Dwarfregsp: dwarfRegSP,
|
||||
Dwarfreglr: dwarfRegLR,
|
||||
|
||||
Adddynrel: adddynrel,
|
||||
Adddynrel2: adddynrel2,
|
||||
Archinit: archinit,
|
||||
Archreloc: archreloc,
|
||||
|
@ -1,231 +0,0 @@
|
||||
// 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 s390x
|
||||
|
||||
import (
|
||||
"cmd/internal/objabi"
|
||||
"cmd/link/internal/ld"
|
||||
"cmd/link/internal/loader"
|
||||
"cmd/link/internal/sym"
|
||||
"debug/elf"
|
||||
)
|
||||
|
||||
func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
targ := r.Sym
|
||||
r.InitExt()
|
||||
|
||||
switch r.Type {
|
||||
default:
|
||||
if r.Type >= objabi.ElfRelocOffset {
|
||||
ld.Errorf(s, "unexpected relocation type %d", r.Type)
|
||||
return false
|
||||
}
|
||||
|
||||
// Handle relocations found in ELF object files.
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_12),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT12):
|
||||
ld.Errorf(s, "s390x 12-bit relocations have not been implemented (relocation type %d)", r.Type-objabi.ElfRelocOffset)
|
||||
return false
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_8),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_16),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_32),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_64):
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_390_nn relocation for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
r.Type = objabi.R_ADDR
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC64):
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_390_PCnn 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 += int64(r.Siz)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT16),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT32),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT64):
|
||||
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT16DBL),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32DBL):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Variant = sym.RV_390_DBL
|
||||
r.Add += int64(r.Siz)
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
}
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT64):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Add += int64(r.Siz)
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
}
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_COPY):
|
||||
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
|
||||
return false
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GLOB_DAT):
|
||||
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
|
||||
return false
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_JMP_SLOT):
|
||||
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
|
||||
return false
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_RELATIVE):
|
||||
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
|
||||
return false
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTOFF):
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_390_GOTOFF relocation for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
r.Type = objabi.R_GOTOFF
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPC):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(r.Siz)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16DBL),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32DBL):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Variant = sym.RV_390_DBL
|
||||
r.Add += int64(r.Siz)
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_390_PCnnDBL relocation for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPCDBL):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Variant = sym.RV_390_DBL
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(r.Siz)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTENT):
|
||||
addgotsym(target, syms, targ)
|
||||
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Variant = sym.RV_390_DBL
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got())
|
||||
r.Add += int64(r.Siz)
|
||||
return true
|
||||
}
|
||||
// Handle references to ELF symbols from our own object files.
|
||||
if targ.Type != sym.SDYNIMPORT {
|
||||
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.GOT
|
||||
rela := syms.RelaPLT
|
||||
if plt.Size == 0 {
|
||||
panic("plt is not set up")
|
||||
}
|
||||
// larl %r1,_GLOBAL_OFFSET_TABLE_+index
|
||||
|
||||
plt.AddUint8(0xc0)
|
||||
plt.AddUint8(0x10)
|
||||
plt.AddPCRelPlus(target.Arch, got, got.Size+6) // need variant?
|
||||
|
||||
// add to got: pointer to current pos in plt
|
||||
got.AddAddrPlus(target.Arch, plt, plt.Size+8) // weird but correct
|
||||
// lg %r1,0(%r1)
|
||||
plt.AddUint8(0xe3)
|
||||
plt.AddUint8(0x10)
|
||||
plt.AddUint8(0x10)
|
||||
plt.AddUint8(0x00)
|
||||
plt.AddUint8(0x00)
|
||||
plt.AddUint8(0x04)
|
||||
// br %r1
|
||||
plt.AddUint8(0x07)
|
||||
plt.AddUint8(0xf1)
|
||||
// basr %r1,%r0
|
||||
plt.AddUint8(0x0d)
|
||||
plt.AddUint8(0x10)
|
||||
// lgf %r1,12(%r1)
|
||||
plt.AddUint8(0xe3)
|
||||
plt.AddUint8(0x10)
|
||||
plt.AddUint8(0x10)
|
||||
plt.AddUint8(0x0c)
|
||||
plt.AddUint8(0x00)
|
||||
plt.AddUint8(0x14)
|
||||
// jg .plt
|
||||
plt.AddUint8(0xc0)
|
||||
plt.AddUint8(0xf4)
|
||||
|
||||
plt.AddUint32(target.Arch, uint32(-((plt.Size - 2) >> 1))) // roll-your-own relocation
|
||||
//.plt index
|
||||
plt.AddUint32(target.Arch, uint32(rela.Size)) // rela size before current entry
|
||||
|
||||
// rela
|
||||
rela.AddAddrPlus(target.Arch, got, got.Size-8)
|
||||
|
||||
rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_390_JMP_SLOT)))
|
||||
rela.AddUint64(target.Arch, 0)
|
||||
|
||||
s.SetPlt(int32(plt.Size - 32))
|
||||
|
||||
} 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_390_GLOB_DAT)))
|
||||
rela.AddUint64(target.Arch, 0)
|
||||
} else {
|
||||
ld.Errorf(s, "addgotsym: unsupported binary format")
|
||||
}
|
||||
}
|
@ -46,7 +46,6 @@ func Init() (*sys.Arch, ld.Arch) {
|
||||
Dwarfregsp: dwarfRegSP,
|
||||
Dwarfreglr: dwarfRegLR,
|
||||
|
||||
Adddynrel: adddynrel,
|
||||
Adddynrel2: adddynrel2,
|
||||
Archinit: archinit,
|
||||
Archreloc: archreloc,
|
||||
|
@ -1,283 +0,0 @@
|
||||
// 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 x86
|
||||
|
||||
import (
|
||||
"cmd/internal/objabi"
|
||||
"cmd/link/internal/ld"
|
||||
"cmd/link/internal/loader"
|
||||
"cmd/link/internal/sym"
|
||||
"debug/elf"
|
||||
)
|
||||
|
||||
// Temporary dumping around 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_386_PC32):
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_386_PC32 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_386_PLT32):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Add += 4
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOT32),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOT32X):
|
||||
if targ.Type != sym.SDYNIMPORT {
|
||||
// have symbol
|
||||
if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
|
||||
// turn MOVL of GOT entry into LEAL of symbol address, relative to GOT.
|
||||
s.P[r.Off-2] = 0x8d
|
||||
|
||||
r.Type = objabi.R_GOTOFF
|
||||
return true
|
||||
}
|
||||
|
||||
if r.Off >= 2 && s.P[r.Off-2] == 0xff && s.P[r.Off-1] == 0xb3 {
|
||||
// turn PUSHL of GOT entry into PUSHL of symbol itself.
|
||||
// use unnecessary SS prefix to keep instruction same length.
|
||||
s.P[r.Off-2] = 0x36
|
||||
|
||||
s.P[r.Off-1] = 0x68
|
||||
r.Type = objabi.R_ADDR
|
||||
return true
|
||||
}
|
||||
|
||||
ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
|
||||
return false
|
||||
}
|
||||
|
||||
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_386_GOTOFF):
|
||||
r.Type = objabi.R_GOTOFF
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOTPC):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Sym = syms.GOT
|
||||
r.Add += 4
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_32):
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_386_32 relocation for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
r.Type = objabi.R_ADDR
|
||||
return true
|
||||
|
||||
case objabi.MachoRelocOffset + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 0:
|
||||
r.Type = objabi.R_ADDR
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
return true
|
||||
|
||||
case objabi.MachoRelocOffset + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1:
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(targ.Plt())
|
||||
r.Type = objabi.R_PCREL
|
||||
return true
|
||||
}
|
||||
|
||||
r.Type = objabi.R_PCREL
|
||||
return true
|
||||
|
||||
case objabi.MachoRelocOffset + ld.MACHO_FAKE_GOTPCREL:
|
||||
if targ.Type != sym.SDYNIMPORT {
|
||||
// have symbol
|
||||
// turn MOVL of GOT entry into LEAL of symbol itself
|
||||
if r.Off < 2 || s.P[r.Off-2] != 0x8b {
|
||||
ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
|
||||
return false
|
||||
}
|
||||
|
||||
s.P[r.Off-2] = 0x8d
|
||||
r.Type = objabi.R_PCREL
|
||||
return true
|
||||
}
|
||||
|
||||
addgotsym(target, syms, targ)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got())
|
||||
r.Type = objabi.R_PCREL
|
||||
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_CALL,
|
||||
objabi.R_PCREL:
|
||||
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_386_32)))
|
||||
r.Type = objabi.R_CONST // write r->add during relocsym
|
||||
r.Sym = nil
|
||||
return true
|
||||
}
|
||||
|
||||
if target.IsDarwin() && s.Size == int64(target.Arch.PtrSize) && r.Off == 0 {
|
||||
// Mach-O relocations are a royal pain to lay out.
|
||||
// They use a compact stateful bytecode representation
|
||||
// that is too much bother to deal with.
|
||||
// Instead, interpret the C declaration
|
||||
// void *_Cvar_stderr = &stderr;
|
||||
// as making _Cvar_stderr the name of a GOT entry
|
||||
// for stderr. This is separate from the usual GOT entry,
|
||||
// just in case the C code assigns to the variable,
|
||||
// and of course it only works for single pointers,
|
||||
// but we only need to support cgo and that's all it needs.
|
||||
ld.Adddynsym(target, syms, targ)
|
||||
|
||||
got := syms.GOT
|
||||
s.Type = got.Type
|
||||
s.Attr |= sym.AttrSubSymbol
|
||||
s.Outer = got
|
||||
s.Sub = got.Sub
|
||||
got.Sub = s
|
||||
s.Value = got.Size
|
||||
got.AddUint32(target.Arch, 0)
|
||||
syms.LinkEditGOT.AddUint32(target.Arch, uint32(targ.Dynid))
|
||||
r.Type = objabi.ElfRelocOffset // ignore during relocsym
|
||||
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")
|
||||
}
|
||||
|
||||
// jmpq *got+size
|
||||
plt.AddUint8(0xff)
|
||||
|
||||
plt.AddUint8(0x25)
|
||||
plt.AddAddrPlus(target.Arch, got, got.Size)
|
||||
|
||||
// add to got: pointer to current pos in plt
|
||||
got.AddAddrPlus(target.Arch, plt, plt.Size)
|
||||
|
||||
// pushl $x
|
||||
plt.AddUint8(0x68)
|
||||
|
||||
plt.AddUint32(target.Arch, uint32(rel.Size))
|
||||
|
||||
// jmp .plt
|
||||
plt.AddUint8(0xe9)
|
||||
|
||||
plt.AddUint32(target.Arch, uint32(-(plt.Size + 4)))
|
||||
|
||||
// rel
|
||||
rel.AddAddrPlus(target.Arch, got, got.Size-4)
|
||||
|
||||
rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_386_JMP_SLOT)))
|
||||
|
||||
s.SetPlt(int32(plt.Size - 16))
|
||||
} else if target.IsDarwin() {
|
||||
// Same laziness as in 6l.
|
||||
|
||||
plt := syms.PLT
|
||||
|
||||
addgotsym(target, syms, s)
|
||||
|
||||
syms.LinkEditPLT.AddUint32(target.Arch, uint32(s.Dynid))
|
||||
|
||||
// jmpq *got+size(IP)
|
||||
s.SetPlt(int32(plt.Size))
|
||||
|
||||
plt.AddUint8(0xff)
|
||||
plt.AddUint8(0x25)
|
||||
plt.AddAddrPlus(target.Arch, syms.GOT, int64(s.Got()))
|
||||
} 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.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_386_GLOB_DAT)))
|
||||
} else if target.IsDarwin() {
|
||||
syms.LinkEditGOT.AddUint32(target.Arch, uint32(s.Dynid))
|
||||
} else {
|
||||
ld.Errorf(s, "addgotsym: unsupported binary format")
|
||||
}
|
||||
}
|
@ -46,7 +46,6 @@ func Init() (*sys.Arch, ld.Arch) {
|
||||
Dwarfregsp: dwarfRegSP,
|
||||
Dwarfreglr: dwarfRegLR,
|
||||
|
||||
Adddynrel: adddynrel,
|
||||
Adddynrel2: adddynrel2,
|
||||
Archinit: archinit,
|
||||
Archreloc: archreloc,
|
||||
|
Loading…
Reference in New Issue
Block a user