mirror of https://github.com/golang/go.git
[dev.link] cmd/link: eliminate usage of *Link in arch funcs
Change-Id: I10e6b266ff3a1238d1b86a9b39debb13f5a04e55 Reviewed-on: https://go-review.googlesource.com/c/go/+/222159 Run-TryBot: Jeremy Faller <jeremy@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
63ffa1595c
commit
bf5dc7af0f
|
|
@ -107,13 +107,13 @@ func makeWritable(s *sym.Symbol) {
|
|||
}
|
||||
}
|
||||
|
||||
func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
func adddynrel(_ *ld.Link, target *ld.Target, 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(ctxt.Arch, r.Type))
|
||||
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(target.Arch, r.Type))
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -146,8 +146,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
r.Type = objabi.R_PCREL
|
||||
r.Add += 4
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
}
|
||||
|
||||
|
|
@ -171,10 +171,10 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
|
||||
// fall back to using GOT and hope for the best (CMOV*)
|
||||
// TODO: just needs relocation, no need to put in .dynsym
|
||||
addgotsym(ctxt, targ)
|
||||
addgotsym(target, syms, targ)
|
||||
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += 4
|
||||
r.Add += int64(targ.Got())
|
||||
return true
|
||||
|
|
@ -184,7 +184,7 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
ld.Errorf(s, "unexpected R_X86_64_64 relocation for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
r.Type = objabi.R_ADDR
|
||||
if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
|
||||
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.
|
||||
|
|
@ -206,8 +206,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
|
||||
case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1:
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(targ.Plt())
|
||||
r.Type = objabi.R_PCREL
|
||||
return true
|
||||
|
|
@ -246,9 +246,9 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
if targ.Type != sym.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
|
||||
}
|
||||
addgotsym(ctxt, targ)
|
||||
addgotsym(target, syms, targ)
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got())
|
||||
return true
|
||||
}
|
||||
|
|
@ -260,37 +260,37 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
// nothing to do, the relocation will be laid out in reloc
|
||||
return true
|
||||
}
|
||||
if ctxt.LinkMode == ld.LinkExternal {
|
||||
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(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(targ.Plt())
|
||||
return true
|
||||
|
||||
case objabi.R_ADDR:
|
||||
if s.Type == sym.STEXT && ctxt.IsELF {
|
||||
if ctxt.HeadType == objabi.Hsolaris {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
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(ctxt, targ)
|
||||
addgotsym(target, syms, targ)
|
||||
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got())
|
||||
return true
|
||||
}
|
||||
|
||||
// Process dynamic relocations for the data sections.
|
||||
if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
|
||||
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
|
||||
|
|
@ -338,7 +338,7 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
}
|
||||
}
|
||||
|
||||
if ctxt.IsELF {
|
||||
if target.IsElf() {
|
||||
// Generate R_X86_64_RELATIVE relocations for best
|
||||
// efficiency in the dynamic linker.
|
||||
//
|
||||
|
|
@ -356,14 +356,14 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
// 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 := ctxt.Syms.Lookup(".rela", 0)
|
||||
rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
|
||||
rela := syms.Rela
|
||||
rela.AddAddrPlus(target.Arch, s, int64(r.Off))
|
||||
if r.Siz == 8 {
|
||||
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(0, uint32(elf.R_X86_64_RELATIVE)))
|
||||
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(ctxt.Arch, targ, int64(r.Add))
|
||||
rela.AddAddrPlus(target.Arch, targ, int64(r.Add))
|
||||
// Not mark r done here. So we still apply it statically,
|
||||
// so in the file content we'll also have the right offset
|
||||
// to the relocation target. So it can be examined statically
|
||||
|
|
@ -371,7 +371,7 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
return true
|
||||
}
|
||||
|
||||
if ctxt.HeadType == objabi.Hdarwin && s.Size == int64(ctxt.Arch.PtrSize) && r.Off == 0 {
|
||||
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.
|
||||
|
|
@ -382,17 +382,17 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
// 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(&ctxt.Target, &ctxt.ArchSyms, targ)
|
||||
ld.Adddynsym(target, syms, targ)
|
||||
|
||||
got := ctxt.Syms.Lookup(".got", 0)
|
||||
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(ctxt.Arch, 0)
|
||||
ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(targ.Dynid))
|
||||
got.AddUint64(target.Arch, 0)
|
||||
syms.LinkEditGOT.AddUint32(target.Arch, uint32(targ.Dynid))
|
||||
r.Type = objabi.ElfRelocOffset // ignore during relocsym
|
||||
return true
|
||||
}
|
||||
|
|
@ -598,17 +598,17 @@ func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.S
|
|||
}
|
||||
}
|
||||
|
||||
func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Plt() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
|
||||
if ctxt.IsELF {
|
||||
plt := ctxt.Syms.Lookup(".plt", 0)
|
||||
got := ctxt.Syms.Lookup(".got.plt", 0)
|
||||
rela := ctxt.Syms.Lookup(".rela.plt", 0)
|
||||
if target.IsElf() {
|
||||
plt := syms.PLT
|
||||
got := syms.GOTPLT
|
||||
rela := syms.RelaPLT
|
||||
if plt.Size == 0 {
|
||||
panic("plt is not set up")
|
||||
}
|
||||
|
|
@ -617,29 +617,29 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
|||
plt.AddUint8(0xff)
|
||||
|
||||
plt.AddUint8(0x25)
|
||||
plt.AddPCRelPlus(ctxt.Arch, got, got.Size)
|
||||
plt.AddPCRelPlus(target.Arch, got, got.Size)
|
||||
|
||||
// add to got: pointer to current pos in plt
|
||||
got.AddAddrPlus(ctxt.Arch, plt, plt.Size)
|
||||
got.AddAddrPlus(target.Arch, plt, plt.Size)
|
||||
|
||||
// pushq $x
|
||||
plt.AddUint8(0x68)
|
||||
|
||||
plt.AddUint32(ctxt.Arch, uint32((got.Size-24-8)/8))
|
||||
plt.AddUint32(target.Arch, uint32((got.Size-24-8)/8))
|
||||
|
||||
// jmpq .plt
|
||||
plt.AddUint8(0xe9)
|
||||
|
||||
plt.AddUint32(ctxt.Arch, uint32(-(plt.Size + 4)))
|
||||
plt.AddUint32(target.Arch, uint32(-(plt.Size + 4)))
|
||||
|
||||
// rela
|
||||
rela.AddAddrPlus(ctxt.Arch, got, got.Size-8)
|
||||
rela.AddAddrPlus(target.Arch, got, got.Size-8)
|
||||
|
||||
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_X86_64_JMP_SLOT)))
|
||||
rela.AddUint64(ctxt.Arch, 0)
|
||||
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 ctxt.HeadType == objabi.Hdarwin {
|
||||
} 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
|
||||
|
|
@ -650,39 +650,39 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
|||
// https://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html
|
||||
// has details about what we're avoiding.
|
||||
|
||||
addgotsym(ctxt, s)
|
||||
plt := ctxt.Syms.Lookup(".plt", 0)
|
||||
addgotsym(target, syms, s)
|
||||
plt := syms.PLT
|
||||
|
||||
ctxt.Syms.Lookup(".linkedit.plt", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
|
||||
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(ctxt.Arch, ctxt.Syms.Lookup(".got", 0), int64(s.Got()))
|
||||
plt.AddPCRelPlus(target.Arch, syms.GOT, int64(s.Got()))
|
||||
} else {
|
||||
ld.Errorf(s, "addpltsym: unsupported binary format")
|
||||
}
|
||||
}
|
||||
|
||||
func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Got() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
got := ctxt.Syms.Lookup(".got", 0)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
got := syms.GOT
|
||||
s.SetGot(int32(got.Size))
|
||||
got.AddUint64(ctxt.Arch, 0)
|
||||
got.AddUint64(target.Arch, 0)
|
||||
|
||||
if ctxt.IsELF {
|
||||
rela := ctxt.Syms.Lookup(".rela", 0)
|
||||
rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
|
||||
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_X86_64_GLOB_DAT)))
|
||||
rela.AddUint64(ctxt.Arch, 0)
|
||||
} else if ctxt.HeadType == objabi.Hdarwin {
|
||||
ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
|
||||
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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,13 +116,13 @@ func braddoff(a int32, b int32) int32 {
|
|||
return int32((uint32(a))&0xff000000 | 0x00ffffff&uint32(a+b))
|
||||
}
|
||||
|
||||
func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
func adddynrel(_ *ld.Link, target *ld.Target, 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(ctxt.Arch, r.Type))
|
||||
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(target.Arch, r.Type))
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -131,8 +131,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
r.Type = objabi.R_CALLARM
|
||||
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
|
||||
}
|
||||
|
||||
|
|
@ -144,9 +144,9 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT32): // R_ARM_GOT_BREL
|
||||
if targ.Type != sym.SDYNIMPORT {
|
||||
addgotsyminternal(ctxt, targ)
|
||||
addgotsyminternal(target, syms, targ)
|
||||
} else {
|
||||
addgotsym(ctxt, targ)
|
||||
addgotsym(target, syms, targ)
|
||||
}
|
||||
|
||||
r.Type = objabi.R_CONST // write r->add during relocsym
|
||||
|
|
@ -156,13 +156,13 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT_PREL): // GOT(nil) + A - nil
|
||||
if targ.Type != sym.SDYNIMPORT {
|
||||
addgotsyminternal(ctxt, targ)
|
||||
addgotsyminternal(target, syms, targ)
|
||||
} else {
|
||||
addgotsym(ctxt, targ)
|
||||
addgotsym(target, syms, targ)
|
||||
}
|
||||
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got()) + 4
|
||||
return true
|
||||
|
||||
|
|
@ -174,15 +174,15 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOTPC): // R_ARM_BASE_PREL
|
||||
r.Type = objabi.R_PCREL
|
||||
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
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(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
|
||||
}
|
||||
|
||||
|
|
@ -215,8 +215,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_JUMP24):
|
||||
r.Type = objabi.R_CALLARM
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
|
||||
}
|
||||
|
||||
|
|
@ -230,12 +230,12 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
|
||||
switch r.Type {
|
||||
case objabi.R_CALLARM:
|
||||
if ctxt.LinkMode == ld.LinkExternal {
|
||||
if target.IsExternal() {
|
||||
// External linker will do this relocation.
|
||||
return true
|
||||
}
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(targ.Plt())
|
||||
return true
|
||||
|
||||
|
|
@ -243,12 +243,12 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
if s.Type != sym.SDATA {
|
||||
break
|
||||
}
|
||||
if ctxt.IsELF {
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, targ)
|
||||
rel := ctxt.Syms.Lookup(".rel", 0)
|
||||
rel.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
|
||||
rel.AddUint32(ctxt.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
|
||||
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
|
||||
}
|
||||
|
|
@ -671,7 +671,7 @@ func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym
|
|||
return t
|
||||
}
|
||||
|
||||
func addpltreloc(ctxt *ld.Link, plt *sym.Symbol, got *sym.Symbol, s *sym.Symbol, typ objabi.RelocType) {
|
||||
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)
|
||||
|
|
@ -684,17 +684,17 @@ func addpltreloc(ctxt *ld.Link, plt *sym.Symbol, got *sym.Symbol, s *sym.Symbol,
|
|||
plt.Grow(plt.Size)
|
||||
}
|
||||
|
||||
func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Plt() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
|
||||
if ctxt.IsELF {
|
||||
plt := ctxt.Syms.Lookup(".plt", 0)
|
||||
got := ctxt.Syms.Lookup(".got.plt", 0)
|
||||
rel := ctxt.Syms.Lookup(".rel.plt", 0)
|
||||
if target.IsElf() {
|
||||
plt := syms.PLT
|
||||
got := syms.GOTPLT
|
||||
rel := syms.RelPLT
|
||||
if plt.Size == 0 {
|
||||
panic("plt is not set up")
|
||||
}
|
||||
|
|
@ -705,54 +705,54 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
|||
// 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(ctxt.Arch, plt, 0)
|
||||
got.AddAddrPlus(target.Arch, plt, 0)
|
||||
|
||||
// .plt entry, this depends on the .got entry
|
||||
s.SetPlt(int32(plt.Size))
|
||||
|
||||
addpltreloc(ctxt, plt, got, s, objabi.R_PLT0) // add lr, pc, #0xXX00000
|
||||
addpltreloc(ctxt, plt, got, s, objabi.R_PLT1) // add lr, lr, #0xYY000
|
||||
addpltreloc(ctxt, plt, got, s, objabi.R_PLT2) // ldr pc, [lr, #0xZZZ]!
|
||||
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(ctxt.Arch, got, int64(s.Got()))
|
||||
rel.AddAddrPlus(target.Arch, got, int64(s.Got()))
|
||||
|
||||
rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_JUMP_SLOT)))
|
||||
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 addgotsyminternal(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addgotsyminternal(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Got() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
got := ctxt.Syms.Lookup(".got", 0)
|
||||
got := syms.GOT
|
||||
s.SetGot(int32(got.Size))
|
||||
|
||||
got.AddAddrPlus(ctxt.Arch, s, 0)
|
||||
got.AddAddrPlus(target.Arch, s, 0)
|
||||
|
||||
if ctxt.IsELF {
|
||||
if target.IsElf() {
|
||||
} else {
|
||||
ld.Errorf(s, "addgotsyminternal: unsupported binary format")
|
||||
}
|
||||
}
|
||||
|
||||
func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Got() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
got := ctxt.Syms.Lookup(".got", 0)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
got := syms.GOT
|
||||
s.SetGot(int32(got.Size))
|
||||
got.AddUint32(ctxt.Arch, 0)
|
||||
got.AddUint32(target.Arch, 0)
|
||||
|
||||
if ctxt.IsELF {
|
||||
rel := ctxt.Syms.Lookup(".rel", 0)
|
||||
rel.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
|
||||
rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_GLOB_DAT)))
|
||||
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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,13 +92,13 @@ func gentext(ctxt *ld.Link) {
|
|||
initarray_entry.AddAddr(ctxt.Arch, initfunc)
|
||||
}
|
||||
|
||||
func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
func adddynrel(_ *ld.Link, target *ld.Target, 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(ctxt.Arch, r.Type))
|
||||
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(target.Arch, r.Type))
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -130,8 +130,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26):
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
}
|
||||
if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
|
||||
|
|
@ -149,10 +149,10 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
|
||||
// fall back to using GOT
|
||||
// TODO: just needs relocation, no need to put in .dynsym
|
||||
addgotsym(ctxt, targ)
|
||||
addgotsym(target, syms, targ)
|
||||
|
||||
r.Type = objabi.R_ARM64_GOT
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got())
|
||||
return true
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
ld.Errorf(s, "unexpected R_AARCH64_ABS64 relocation for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
r.Type = objabi.R_ADDR
|
||||
if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
|
||||
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.
|
||||
|
|
@ -217,25 +217,25 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
// nothing to do, the relocation will be laid out in reloc
|
||||
return true
|
||||
}
|
||||
if ctxt.LinkMode == ld.LinkExternal {
|
||||
if target.IsExternal() {
|
||||
// External linker will do this relocation.
|
||||
return true
|
||||
}
|
||||
|
||||
case objabi.R_ADDR:
|
||||
if s.Type == sym.STEXT && ctxt.IsELF {
|
||||
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(ctxt, targ)
|
||||
addgotsym(target, syms, targ)
|
||||
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got())
|
||||
return true
|
||||
}
|
||||
|
||||
// Process dynamic relocations for the data sections.
|
||||
if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
|
||||
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
|
||||
|
|
@ -283,7 +283,7 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
}
|
||||
}
|
||||
|
||||
if ctxt.IsELF {
|
||||
if target.IsElf() {
|
||||
// Generate R_AARCH64_RELATIVE relocations for best
|
||||
// efficiency in the dynamic linker.
|
||||
//
|
||||
|
|
@ -301,14 +301,14 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
// 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 := ctxt.Syms.Lookup(".rela", 0)
|
||||
rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
|
||||
rela := syms.Rela
|
||||
rela.AddAddrPlus(target.Arch, s, int64(r.Off))
|
||||
if r.Siz == 8 {
|
||||
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(0, uint32(elf.R_AARCH64_RELATIVE)))
|
||||
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(ctxt.Arch, targ, int64(r.Add))
|
||||
rela.AddAddrPlus(target.Arch, targ, int64(r.Add))
|
||||
// Not mark r done here. So we still apply it statically,
|
||||
// so in the file content we'll also have the right offset
|
||||
// to the relocation target. So it can be examined statically
|
||||
|
|
@ -751,47 +751,47 @@ func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loade
|
|||
}
|
||||
}
|
||||
|
||||
func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Plt() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
|
||||
if ctxt.IsELF {
|
||||
plt := ctxt.Syms.Lookup(".plt", 0)
|
||||
gotplt := ctxt.Syms.Lookup(".got.plt", 0)
|
||||
rela := ctxt.Syms.Lookup(".rela.plt", 0)
|
||||
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(ctxt.Arch, plt.Size-4, 0x90000010)
|
||||
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(ctxt.Arch, plt.Size-4, 0xf9400211)
|
||||
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(ctxt.Arch, plt.Size-4, 0x91000210)
|
||||
plt.SetUint32(target.Arch, plt.Size-4, 0x91000210)
|
||||
plt.R[len(plt.R)-1].Type = objabi.R_ARM64_PCREL
|
||||
|
||||
// br x17
|
||||
plt.AddUint32(ctxt.Arch, 0xd61f0220)
|
||||
plt.AddUint32(target.Arch, 0xd61f0220)
|
||||
|
||||
// add to got.plt: pointer to plt[0]
|
||||
gotplt.AddAddrPlus(ctxt.Arch, plt, 0)
|
||||
gotplt.AddAddrPlus(target.Arch, plt, 0)
|
||||
|
||||
// rela
|
||||
rela.AddAddrPlus(ctxt.Arch, gotplt, gotplt.Size-8)
|
||||
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_JUMP_SLOT)))
|
||||
rela.AddUint64(ctxt.Arch, 0)
|
||||
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 {
|
||||
|
|
@ -799,21 +799,21 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
|||
}
|
||||
}
|
||||
|
||||
func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Got() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
got := ctxt.Syms.Lookup(".got", 0)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
got := syms.GOT
|
||||
s.SetGot(int32(got.Size))
|
||||
got.AddUint64(ctxt.Arch, 0)
|
||||
got.AddUint64(target.Arch, 0)
|
||||
|
||||
if ctxt.IsELF {
|
||||
rela := ctxt.Syms.Lookup(".rela", 0)
|
||||
rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
|
||||
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_GLOB_DAT)))
|
||||
rela.AddUint64(ctxt.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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,16 @@ type ArchSyms struct {
|
|||
Dynamic *sym.Symbol
|
||||
DynSym *sym.Symbol
|
||||
DynStr *sym.Symbol
|
||||
|
||||
// Elf specific
|
||||
Rel *sym.Symbol
|
||||
Rela *sym.Symbol
|
||||
RelPLT *sym.Symbol
|
||||
RelaPLT *sym.Symbol
|
||||
|
||||
// Darwin symbols
|
||||
LinkEditGOT *sym.Symbol
|
||||
LinkEditPLT *sym.Symbol
|
||||
}
|
||||
|
||||
// setArchSyms sets up the ArchSyms structure, and must be called before
|
||||
|
|
@ -136,6 +146,16 @@ func (ctxt *Link) setArchSyms() {
|
|||
ctxt.DotTOC[i] = ctxt.Syms.Lookup(".TOC.", i)
|
||||
}
|
||||
}
|
||||
if ctxt.IsElf() {
|
||||
ctxt.Rel = ctxt.Syms.Lookup(".rel", 0)
|
||||
ctxt.Rela = ctxt.Syms.Lookup(".rela", 0)
|
||||
ctxt.RelPLT = ctxt.Syms.Lookup(".rel.plt", 0)
|
||||
ctxt.RelaPLT = ctxt.Syms.Lookup(".rela.plt", 0)
|
||||
}
|
||||
if ctxt.IsDarwin() {
|
||||
ctxt.LinkEditGOT = ctxt.Syms.Lookup(".linkedit.got", 0)
|
||||
ctxt.LinkEditPLT = ctxt.Syms.Lookup(".linkedit.plt", 0)
|
||||
}
|
||||
}
|
||||
|
||||
type Arch struct {
|
||||
|
|
@ -2699,6 +2719,9 @@ func (ctxt *Link) loadlibfull() {
|
|||
ctxt.cgodata = nil
|
||||
|
||||
addToTextp(ctxt)
|
||||
|
||||
// Set special global symbols.
|
||||
ctxt.setArchSyms()
|
||||
}
|
||||
|
||||
func (ctxt *Link) dumpsyms() {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ func gentext(ctxt *ld.Link) {
|
|||
return
|
||||
}
|
||||
|
||||
func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
func adddynrel(_ *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
log.Fatalf("adddynrel not implemented")
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import (
|
|||
|
||||
func gentext(ctxt *ld.Link) {}
|
||||
|
||||
func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
func adddynrel(_ *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
log.Fatalf("adddynrel not implemented")
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,22 +263,23 @@ func gencallstub(ctxt *ld.Link, abicase int, stub *sym.Symbol, targ *sym.Symbol)
|
|||
stub.AddUint32(ctxt.Arch, 0x4e800420) // bctr
|
||||
}
|
||||
|
||||
func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
if ctxt.IsELF {
|
||||
return addelfdynrel(ctxt, s, r)
|
||||
} else if ctxt.HeadType == objabi.Haix {
|
||||
return ld.Xcoffadddynrel(&ctxt.Target, s, r)
|
||||
func adddynrel(_ *ld.Link, target *ld.Target, 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, s, r)
|
||||
}
|
||||
return false
|
||||
}
|
||||
func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
|
||||
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(ctxt.Arch, r.Type))
|
||||
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(target.Arch, r.Type))
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -314,12 +315,12 @@ func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
|
|||
r.Type = objabi.R_ADDR
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
// These happen in .toc sections
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, targ)
|
||||
ld.Adddynsym(target, syms, targ)
|
||||
|
||||
rela := ctxt.Syms.Lookup(".rela", 0)
|
||||
rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
|
||||
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_PPC64_ADDR64)))
|
||||
rela.AddUint64(ctxt.Arch, uint64(r.Add))
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ import (
|
|||
func gentext(ctxt *ld.Link) {
|
||||
}
|
||||
|
||||
func adddynrela(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, rel *sym.Symbol, s *sym.Symbol, r *sym.Reloc) {
|
||||
func adddynrela(_ *ld.Link, target *ld.Target, syms *ld.ArchSyms, rel *sym.Symbol, s *sym.Symbol, r *sym.Reloc) {
|
||||
log.Fatalf("adddynrela not implemented")
|
||||
}
|
||||
|
||||
func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
func adddynrel(_ *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
log.Fatalf("adddynrel not implemented")
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ func gentext(ctxt *ld.Link) {
|
|||
initarray_entry.AddAddr(ctxt.Arch, initfunc)
|
||||
}
|
||||
|
||||
func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
func adddynrel(_ *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
targ := r.Sym
|
||||
r.InitExt()
|
||||
|
||||
|
|
@ -159,8 +159,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
r.Variant = sym.RV_390_DBL
|
||||
r.Add += int64(r.Siz)
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
}
|
||||
return true
|
||||
|
|
@ -170,8 +170,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
r.Type = objabi.R_PCREL
|
||||
r.Add += int64(r.Siz)
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
}
|
||||
return true
|
||||
|
|
@ -201,7 +201,7 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPC):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(r.Siz)
|
||||
return true
|
||||
|
||||
|
|
@ -218,16 +218,16 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPCDBL):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Variant = sym.RV_390_DBL
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(r.Siz)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTENT):
|
||||
addgotsym(ctxt, targ)
|
||||
addgotsym(target, syms, targ)
|
||||
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Variant = sym.RV_390_DBL
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got())
|
||||
r.Add += int64(r.Siz)
|
||||
return true
|
||||
|
|
@ -418,17 +418,17 @@ func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym
|
|||
}
|
||||
}
|
||||
|
||||
func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Plt() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
|
||||
if ctxt.IsELF {
|
||||
plt := ctxt.Syms.Lookup(".plt", 0)
|
||||
got := ctxt.Syms.Lookup(".got", 0)
|
||||
rela := ctxt.Syms.Lookup(".rela.plt", 0)
|
||||
if target.IsElf() {
|
||||
plt := syms.PLT
|
||||
got := syms.GOT
|
||||
rela := syms.RelaPLT
|
||||
if plt.Size == 0 {
|
||||
panic("plt is not set up")
|
||||
}
|
||||
|
|
@ -436,10 +436,10 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
|||
|
||||
plt.AddUint8(0xc0)
|
||||
plt.AddUint8(0x10)
|
||||
plt.AddPCRelPlus(ctxt.Arch, got, got.Size+6) // need variant?
|
||||
plt.AddPCRelPlus(target.Arch, got, got.Size+6) // need variant?
|
||||
|
||||
// add to got: pointer to current pos in plt
|
||||
got.AddAddrPlus(ctxt.Arch, plt, plt.Size+8) // weird but correct
|
||||
got.AddAddrPlus(target.Arch, plt, plt.Size+8) // weird but correct
|
||||
// lg %r1,0(%r1)
|
||||
plt.AddUint8(0xe3)
|
||||
plt.AddUint8(0x10)
|
||||
|
|
@ -464,15 +464,15 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
|||
plt.AddUint8(0xc0)
|
||||
plt.AddUint8(0xf4)
|
||||
|
||||
plt.AddUint32(ctxt.Arch, uint32(-((plt.Size - 2) >> 1))) // roll-your-own relocation
|
||||
plt.AddUint32(target.Arch, uint32(-((plt.Size - 2) >> 1))) // roll-your-own relocation
|
||||
//.plt index
|
||||
plt.AddUint32(ctxt.Arch, uint32(rela.Size)) // rela size before current entry
|
||||
plt.AddUint32(target.Arch, uint32(rela.Size)) // rela size before current entry
|
||||
|
||||
// rela
|
||||
rela.AddAddrPlus(ctxt.Arch, got, got.Size-8)
|
||||
rela.AddAddrPlus(target.Arch, got, got.Size-8)
|
||||
|
||||
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_390_JMP_SLOT)))
|
||||
rela.AddUint64(ctxt.Arch, 0)
|
||||
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))
|
||||
|
||||
|
|
@ -481,21 +481,21 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
|||
}
|
||||
}
|
||||
|
||||
func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Got() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
got := ctxt.Syms.Lookup(".got", 0)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
got := syms.GOT
|
||||
s.SetGot(int32(got.Size))
|
||||
got.AddUint64(ctxt.Arch, 0)
|
||||
got.AddUint64(target.Arch, 0)
|
||||
|
||||
if ctxt.IsELF {
|
||||
rela := ctxt.Syms.Lookup(".rela", 0)
|
||||
rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
|
||||
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_390_GLOB_DAT)))
|
||||
rela.AddUint64(ctxt.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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,13 +168,13 @@ func gentext(ctxt *ld.Link) {
|
|||
initarray_entry.AddAddr(ctxt.Arch, initfunc)
|
||||
}
|
||||
|
||||
func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
|
||||
func adddynrel(_ *ld.Link, target *ld.Target, 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(ctxt.Arch, r.Type))
|
||||
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(target.Arch, r.Type))
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -196,8 +196,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
r.Type = objabi.R_PCREL
|
||||
r.Add += 4
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add += int64(targ.Plt())
|
||||
}
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
return false
|
||||
}
|
||||
|
||||
addgotsym(ctxt, targ)
|
||||
addgotsym(target, syms, targ)
|
||||
r.Type = objabi.R_CONST // write r->add during relocsym
|
||||
r.Sym = nil
|
||||
r.Add += int64(targ.Got())
|
||||
|
|
@ -241,7 +241,7 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOTPC):
|
||||
r.Type = objabi.R_PCREL
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += 4
|
||||
return true
|
||||
|
||||
|
|
@ -261,8 +261,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
|
||||
case objabi.MachoRelocOffset + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1:
|
||||
if targ.Type == sym.SDYNIMPORT {
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(targ.Plt())
|
||||
r.Type = objabi.R_PCREL
|
||||
return true
|
||||
|
|
@ -285,8 +285,8 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
return true
|
||||
}
|
||||
|
||||
addgotsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
||||
addgotsym(target, syms, targ)
|
||||
r.Sym = syms.GOT
|
||||
r.Add += int64(targ.Got())
|
||||
r.Type = objabi.R_PCREL
|
||||
return true
|
||||
|
|
@ -299,12 +299,12 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
switch r.Type {
|
||||
case objabi.R_CALL,
|
||||
objabi.R_PCREL:
|
||||
if ctxt.LinkMode == ld.LinkExternal {
|
||||
if target.IsExternal() {
|
||||
// External linker will do this relocation.
|
||||
return true
|
||||
}
|
||||
addpltsym(ctxt, targ)
|
||||
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
||||
addpltsym(target, syms, targ)
|
||||
r.Sym = syms.PLT
|
||||
r.Add = int64(targ.Plt())
|
||||
return true
|
||||
|
||||
|
|
@ -312,17 +312,17 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
if s.Type != sym.SDATA {
|
||||
break
|
||||
}
|
||||
if ctxt.IsELF {
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, targ)
|
||||
rel := ctxt.Syms.Lookup(".rel", 0)
|
||||
rel.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
|
||||
rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(targ.Dynid), uint32(elf.R_386_32)))
|
||||
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 ctxt.HeadType == objabi.Hdarwin && s.Size == int64(ctxt.Arch.PtrSize) && r.Off == 0 {
|
||||
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.
|
||||
|
|
@ -333,17 +333,17 @@ func adddynrel(ctxt *ld.Link, target *ld.Target, syms *ld.ArchSyms, s *sym.Symbo
|
|||
// 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(&ctxt.Target, &ctxt.ArchSyms, targ)
|
||||
ld.Adddynsym(target, syms, targ)
|
||||
|
||||
got := ctxt.Syms.Lookup(".got", 0)
|
||||
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(ctxt.Arch, 0)
|
||||
ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(targ.Dynid))
|
||||
got.AddUint32(target.Arch, 0)
|
||||
syms.LinkEditGOT.AddUint32(target.Arch, uint32(targ.Dynid))
|
||||
r.Type = objabi.ElfRelocOffset // ignore during relocsym
|
||||
return true
|
||||
}
|
||||
|
|
@ -537,17 +537,17 @@ func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.S
|
|||
}
|
||||
}
|
||||
|
||||
func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Plt() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
|
||||
if ctxt.IsELF {
|
||||
plt := ctxt.Syms.Lookup(".plt", 0)
|
||||
got := ctxt.Syms.Lookup(".got.plt", 0)
|
||||
rel := ctxt.Syms.Lookup(".rel.plt", 0)
|
||||
if target.IsElf() {
|
||||
plt := syms.PLT
|
||||
got := syms.GOTPLT
|
||||
rel := syms.RelPLT
|
||||
if plt.Size == 0 {
|
||||
panic("plt is not set up")
|
||||
}
|
||||
|
|
@ -556,63 +556,63 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
|||
plt.AddUint8(0xff)
|
||||
|
||||
plt.AddUint8(0x25)
|
||||
plt.AddAddrPlus(ctxt.Arch, got, got.Size)
|
||||
plt.AddAddrPlus(target.Arch, got, got.Size)
|
||||
|
||||
// add to got: pointer to current pos in plt
|
||||
got.AddAddrPlus(ctxt.Arch, plt, plt.Size)
|
||||
got.AddAddrPlus(target.Arch, plt, plt.Size)
|
||||
|
||||
// pushl $x
|
||||
plt.AddUint8(0x68)
|
||||
|
||||
plt.AddUint32(ctxt.Arch, uint32(rel.Size))
|
||||
plt.AddUint32(target.Arch, uint32(rel.Size))
|
||||
|
||||
// jmp .plt
|
||||
plt.AddUint8(0xe9)
|
||||
|
||||
plt.AddUint32(ctxt.Arch, uint32(-(plt.Size + 4)))
|
||||
plt.AddUint32(target.Arch, uint32(-(plt.Size + 4)))
|
||||
|
||||
// rel
|
||||
rel.AddAddrPlus(ctxt.Arch, got, got.Size-4)
|
||||
rel.AddAddrPlus(target.Arch, got, got.Size-4)
|
||||
|
||||
rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_386_JMP_SLOT)))
|
||||
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 ctxt.HeadType == objabi.Hdarwin {
|
||||
} else if target.IsDarwin() {
|
||||
// Same laziness as in 6l.
|
||||
|
||||
plt := ctxt.Syms.Lookup(".plt", 0)
|
||||
plt := syms.PLT
|
||||
|
||||
addgotsym(ctxt, s)
|
||||
addgotsym(target, syms, s)
|
||||
|
||||
ctxt.Syms.Lookup(".linkedit.plt", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
|
||||
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(ctxt.Arch, ctxt.Syms.Lookup(".got", 0), int64(s.Got()))
|
||||
plt.AddAddrPlus(target.Arch, syms.GOT, int64(s.Got()))
|
||||
} else {
|
||||
ld.Errorf(s, "addpltsym: unsupported binary format")
|
||||
}
|
||||
}
|
||||
|
||||
func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
|
||||
func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
|
||||
if s.Got() >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(&ctxt.Target, &ctxt.ArchSyms, s)
|
||||
got := ctxt.Syms.Lookup(".got", 0)
|
||||
ld.Adddynsym(target, syms, s)
|
||||
got := syms.GOT
|
||||
s.SetGot(int32(got.Size))
|
||||
got.AddUint32(ctxt.Arch, 0)
|
||||
got.AddUint32(target.Arch, 0)
|
||||
|
||||
if ctxt.IsELF {
|
||||
rel := ctxt.Syms.Lookup(".rel", 0)
|
||||
rel.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
|
||||
rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_386_GLOB_DAT)))
|
||||
} else if ctxt.HeadType == objabi.Hdarwin {
|
||||
ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
|
||||
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")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue