2015-02-27 22:57:28 -05:00
|
|
|
// Inferno utils/6l/asm.c
|
2016-08-28 17:04:46 -07:00
|
|
|
// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/asm.c
|
2015-02-27 22:57:28 -05:00
|
|
|
//
|
|
|
|
|
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
|
|
|
|
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
|
|
|
|
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
|
|
|
|
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
|
|
|
|
// Portions Copyright © 2004,2006 Bruce Ellis
|
|
|
|
|
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
|
|
|
|
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
2016-04-10 14:32:26 -07:00
|
|
|
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
2015-02-27 22:57:28 -05:00
|
|
|
//
|
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
|
//
|
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
|
//
|
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
// THE SOFTWARE.
|
|
|
|
|
|
2015-05-21 13:28:10 -04:00
|
|
|
package amd64
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
import (
|
2017-04-18 12:53:25 -07:00
|
|
|
"cmd/internal/objabi"
|
2017-09-30 21:10:49 +00:00
|
|
|
"cmd/internal/sys"
|
2015-05-21 13:28:10 -04:00
|
|
|
"cmd/link/internal/ld"
|
2017-10-04 17:54:04 -04:00
|
|
|
"cmd/link/internal/sym"
|
2015-05-05 16:10:12 +12:00
|
|
|
"debug/elf"
|
2015-02-27 22:57:28 -05:00
|
|
|
"log"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func PADDR(x uint32) uint32 {
|
|
|
|
|
return x &^ 0x80000000
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func Addcall(ctxt *ld.Link, s *sym.Symbol, t *sym.Symbol) int64 {
|
|
|
|
|
s.Attr |= sym.AttrReachable
|
2015-04-01 14:17:43 +13:00
|
|
|
i := s.Size
|
|
|
|
|
s.Size += 4
|
2017-09-30 15:06:44 +00:00
|
|
|
s.Grow(s.Size)
|
|
|
|
|
r := s.AddRel()
|
2015-04-01 14:17:43 +13:00
|
|
|
r.Sym = t
|
|
|
|
|
r.Off = int32(i)
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_CALL
|
2015-04-01 14:17:43 +13:00
|
|
|
r.Siz = 4
|
|
|
|
|
return i + int64(r.Siz)
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-21 13:52:23 -04:00
|
|
|
func gentext(ctxt *ld.Link) {
|
2016-08-25 21:06:10 -04:00
|
|
|
if !ctxt.DynlinkingGo() {
|
2015-04-01 14:17:43 +13:00
|
|
|
return
|
|
|
|
|
}
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
|
2017-10-05 10:20:17 -04:00
|
|
|
if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
|
2015-04-01 14:17:43 +13:00
|
|
|
// we're linking a module containing the runtime -> no need for
|
|
|
|
|
// an init function
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-10-04 17:54:04 -04:00
|
|
|
addmoduledata.Attr |= sym.AttrReachable
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
|
2017-10-04 17:54:04 -04:00
|
|
|
initfunc.Type = sym.STEXT
|
|
|
|
|
initfunc.Attr |= sym.AttrLocal
|
|
|
|
|
initfunc.Attr |= sym.AttrReachable
|
2015-04-01 14:17:43 +13:00
|
|
|
o := func(op ...uint8) {
|
|
|
|
|
for _, op1 := range op {
|
2017-09-30 15:06:44 +00:00
|
|
|
initfunc.AddUint8(op1)
|
2015-04-01 14:17:43 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 0000000000000000 <local.dso_init>:
|
|
|
|
|
// 0: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 7 <local.dso_init+0x7>
|
|
|
|
|
// 3: R_X86_64_PC32 runtime.firstmoduledata-0x4
|
|
|
|
|
o(0x48, 0x8d, 0x3d)
|
2017-09-30 15:06:44 +00:00
|
|
|
initfunc.AddPCRelPlus(ctxt.Arch, ctxt.Moduledata, 0)
|
2015-04-01 14:17:43 +13:00
|
|
|
// 7: e8 00 00 00 00 callq c <local.dso_init+0xc>
|
|
|
|
|
// 8: R_X86_64_PLT32 runtime.addmoduledata-0x4
|
|
|
|
|
o(0xe8)
|
2016-08-21 13:52:23 -04:00
|
|
|
Addcall(ctxt, initfunc, addmoduledata)
|
2015-04-01 14:17:43 +13:00
|
|
|
// c: c3 retq
|
|
|
|
|
o(0xc3)
|
2017-10-05 10:20:17 -04:00
|
|
|
if ctxt.BuildMode == ld.BuildModePlugin {
|
2016-08-25 21:58:45 -04:00
|
|
|
ctxt.Textp = append(ctxt.Textp, addmoduledata)
|
|
|
|
|
}
|
2016-09-14 14:47:12 -04:00
|
|
|
ctxt.Textp = append(ctxt.Textp, initfunc)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
|
2017-10-04 17:54:04 -04:00
|
|
|
initarray_entry.Attr |= sym.AttrReachable
|
|
|
|
|
initarray_entry.Attr |= sym.AttrLocal
|
|
|
|
|
initarray_entry.Type = sym.SINITARR
|
2017-09-30 15:06:44 +00:00
|
|
|
initarray_entry.AddAddr(ctxt.Arch, initfunc)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
|
2015-03-02 12:35:15 -05:00
|
|
|
targ := r.Sym
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
switch r.Type {
|
|
|
|
|
default:
|
|
|
|
|
if r.Type >= 256 {
|
2017-10-04 17:54:04 -04:00
|
|
|
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
|
2016-09-05 23:49:53 -04:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle relocations found in ELF object files.
|
2017-10-06 16:01:02 -04:00
|
|
|
case 256 + objabi.RelocType(elf.R_X86_64_PC32):
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type == sym.SDYNIMPORT {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ.Name)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-04-28 12:43:06 +12:00
|
|
|
// 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() {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_PCREL
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Add += 4
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-06 16:01:02 -04:00
|
|
|
case 256 + objabi.RelocType(elf.R_X86_64_PC64):
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type == sym.SDYNIMPORT {
|
2017-08-11 16:22:10 -04:00
|
|
|
ld.Errorf(s, "unexpected R_X86_64_PC64 relocation for dynamic symbol %s", targ.Name)
|
|
|
|
|
}
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type == 0 || targ.Type == sym.SXREF {
|
2017-08-11 16:22:10 -04:00
|
|
|
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
|
|
|
|
|
}
|
|
|
|
|
r.Type = objabi.R_PCREL
|
|
|
|
|
r.Add += 8
|
|
|
|
|
return true
|
|
|
|
|
|
2017-10-06 16:01:02 -04:00
|
|
|
case 256 + objabi.RelocType(elf.R_X86_64_PLT32):
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_PCREL
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Add += 4
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type == sym.SDYNIMPORT {
|
2016-08-21 13:52:23 -04:00
|
|
|
addpltsym(ctxt, targ)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Add += int64(targ.Plt)
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-06 16:01:02 -04:00
|
|
|
case 256 + objabi.RelocType(elf.R_X86_64_GOTPCREL), 256 + objabi.RelocType(elf.R_X86_64_GOTPCRELX), 256 + objabi.RelocType(elf.R_X86_64_REX_GOTPCRELX):
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type != sym.SDYNIMPORT {
|
2015-02-27 22:57:28 -05:00
|
|
|
// have symbol
|
|
|
|
|
if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
|
|
|
|
|
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
|
|
|
|
s.P[r.Off-2] = 0x8d
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_PCREL
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Add += 4
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fall back to using GOT and hope for the best (CMOV*)
|
|
|
|
|
// TODO: just needs relocation, no need to put in .dynsym
|
2016-08-21 13:52:23 -04:00
|
|
|
addgotsym(ctxt, targ)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_PCREL
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Add += 4
|
|
|
|
|
r.Add += int64(targ.Got)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-06 16:01:02 -04:00
|
|
|
case 256 + objabi.RelocType(elf.R_X86_64_64):
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type == sym.SDYNIMPORT {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "unexpected R_X86_64_64 relocation for dynamic symbol %s", targ.Name)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_ADDR
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Handle relocations found in Mach-O object files.
|
|
|
|
|
case 512 + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 0,
|
|
|
|
|
512 + ld.MACHO_X86_64_RELOC_SIGNED*2 + 0,
|
|
|
|
|
512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 0:
|
2015-03-05 13:57:36 -05:00
|
|
|
// TODO: What is the difference between all these?
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_ADDR
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type == sym.SDYNIMPORT {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
case 512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1:
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type == sym.SDYNIMPORT {
|
2016-08-21 13:52:23 -04:00
|
|
|
addpltsym(ctxt, targ)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Add = int64(targ.Plt)
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_PCREL
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
// fall through
|
|
|
|
|
case 512 + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 1,
|
|
|
|
|
512 + ld.MACHO_X86_64_RELOC_SIGNED*2 + 1,
|
|
|
|
|
512 + ld.MACHO_X86_64_RELOC_SIGNED_1*2 + 1,
|
|
|
|
|
512 + ld.MACHO_X86_64_RELOC_SIGNED_2*2 + 1,
|
|
|
|
|
512 + ld.MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_PCREL
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type == sym.SDYNIMPORT {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "unexpected pc-relative reloc for dynamic symbol %s", targ.Name)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
case 512 + ld.MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type != sym.SDYNIMPORT {
|
2015-02-27 22:57:28 -05:00
|
|
|
// have symbol
|
|
|
|
|
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
|
|
|
|
if r.Off < 2 || s.P[r.Off-2] != 0x8b {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ.Name)
|
2016-09-05 23:49:53 -04:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.P[r.Off-2] = 0x8d
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_PCREL
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
// fall through
|
|
|
|
|
case 512 + ld.MACHO_X86_64_RELOC_GOT*2 + 1:
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type != sym.SDYNIMPORT {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-08-21 13:52:23 -04:00
|
|
|
addgotsym(ctxt, targ)
|
2017-04-18 12:53:25 -07:00
|
|
|
r.Type = objabi.R_PCREL
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Add += int64(targ.Got)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch r.Type {
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_CALL,
|
|
|
|
|
objabi.R_PCREL:
|
2017-10-04 17:54:04 -04:00
|
|
|
if targ.Type != sym.SDYNIMPORT {
|
2016-09-05 23:49:53 -04:00
|
|
|
// nothing to do, the relocation will be laid out in reloc
|
|
|
|
|
return true
|
|
|
|
|
}
|
2018-04-23 07:30:32 -07:00
|
|
|
if ctxt.LinkMode == ld.LinkExternal {
|
|
|
|
|
// 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.
|
2017-09-10 09:01:30 +09:00
|
|
|
addpltsym(ctxt, targ)
|
|
|
|
|
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
|
|
|
|
r.Add = int64(targ.Plt)
|
|
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDR:
|
2017-10-07 13:43:38 -04:00
|
|
|
if s.Type == sym.STEXT && ctxt.IsELF {
|
2017-10-07 13:49:44 -04:00
|
|
|
if ctxt.HeadType == objabi.Hsolaris {
|
2016-08-21 13:52:23 -04:00
|
|
|
addpltsym(ctxt, targ)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
r.Sym = ctxt.Syms.Lookup(".plt", 0)
|
2015-03-30 13:46:28 +02:00
|
|
|
r.Add += int64(targ.Plt)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-03-30 13:46:28 +02:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
// The code is asking for the address of an external
|
2016-03-01 23:21:55 +00:00
|
|
|
// function. We provide it with the address of the
|
2015-02-27 22:57:28 -05:00
|
|
|
// correspondent GOT symbol.
|
2016-08-21 13:52:23 -04:00
|
|
|
addgotsym(ctxt, targ)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
r.Sym = ctxt.Syms.Lookup(".got", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Add += int64(targ.Got)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-13 08:24:07 -04:00
|
|
|
// Process dynamic relocations for the data sections.
|
2017-10-05 10:20:17 -04:00
|
|
|
if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
|
2016-09-13 08:24:07 -04:00
|
|
|
// 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.
|
cmd/link: skip R_ADDR relocs in .rela.plt for internal PIE
ld.addpltsym adds an R_X86_64_JMP_SLOT dynamic relocation to .rela.plt
and uses Addaddrplus to reference the GOT in Elf64_Rela.r_offset.
Addaddrplus results in an R_ADDR relocation, which here we transform
into an R_X86_64_64 dynamic relocation. This is wrong for several
reasons:
1. .rela.plt is not a writable, relro section. It is mapped read-only,
causing the dynamic linker to segfault when it tried to handle the
relocation. This was the immediate cause of internal PIE cgo
crashes.
2. Relocations targetting other reloc sections are, as far as I can
tell, undefined behavior in the ELF spec and are unlikely to be a
good idea.
3. Even if the relocation did work, it isn't what we want. The
relocation, if successfully handled, would have put an absolute
address as the JMP_SLOT offset, but it should be the offset from the
beginning of the binary, just like any other relocation. What we want
is a statically resolved R_ADDR relocation, just as is used below for
the R_X86_64_64 relocation.
Skipping the .rela.plt allows reloc() to handle these R_ADDR
relocations.
With this CL, internal PIE cgo binaries work.
Updates #18968
Change-Id: Ie74e6fe249e88150baa0e340b1cb128cf7f28673
Reviewed-on: https://go-review.googlesource.com/47837
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2017-07-08 16:47:16 -07:00
|
|
|
//
|
|
|
|
|
// 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.
|
2016-09-13 08:24:07 -04:00
|
|
|
switch s.Name {
|
cmd/link: skip R_ADDR relocs in .rela.plt for internal PIE
ld.addpltsym adds an R_X86_64_JMP_SLOT dynamic relocation to .rela.plt
and uses Addaddrplus to reference the GOT in Elf64_Rela.r_offset.
Addaddrplus results in an R_ADDR relocation, which here we transform
into an R_X86_64_64 dynamic relocation. This is wrong for several
reasons:
1. .rela.plt is not a writable, relro section. It is mapped read-only,
causing the dynamic linker to segfault when it tried to handle the
relocation. This was the immediate cause of internal PIE cgo
crashes.
2. Relocations targetting other reloc sections are, as far as I can
tell, undefined behavior in the ELF spec and are unlikely to be a
good idea.
3. Even if the relocation did work, it isn't what we want. The
relocation, if successfully handled, would have put an absolute
address as the JMP_SLOT offset, but it should be the offset from the
beginning of the binary, just like any other relocation. What we want
is a statically resolved R_ADDR relocation, just as is used below for
the R_X86_64_64 relocation.
Skipping the .rela.plt allows reloc() to handle these R_ADDR
relocations.
With this CL, internal PIE cgo binaries work.
Updates #18968
Change-Id: Ie74e6fe249e88150baa0e340b1cb128cf7f28673
Reviewed-on: https://go-review.googlesource.com/47837
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2017-07-08 16:47:16 -07:00
|
|
|
case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
|
2016-09-13 08:24:07 -04:00
|
|
|
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.
|
2017-10-04 17:54:04 -04:00
|
|
|
if s.Type != sym.SDATA && s.Type != sym.SRODATA {
|
2016-09-13 08:24:07 -04:00
|
|
|
break
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-09-13 08:24:07 -04:00
|
|
|
|
2017-10-07 13:43:38 -04:00
|
|
|
if ctxt.IsELF {
|
2016-09-13 08:24:07 -04:00
|
|
|
// TODO: We generate a R_X86_64_64 relocation for every R_ADDR, even
|
|
|
|
|
// though it would be more efficient (for the dynamic linker) if we
|
|
|
|
|
// generated R_X86_RELATIVE instead.
|
2016-08-21 13:52:23 -04:00
|
|
|
ld.Adddynsym(ctxt, targ)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
rela := ctxt.Syms.Lookup(".rela", 0)
|
2017-09-30 15:06:44 +00:00
|
|
|
rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
|
2015-02-27 22:57:28 -05:00
|
|
|
if r.Siz == 8 {
|
2017-10-06 16:01:02 -04:00
|
|
|
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_X86_64_64)))
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2016-09-13 08:24:07 -04:00
|
|
|
// TODO: never happens, remove.
|
2017-10-06 16:01:02 -04:00
|
|
|
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_X86_64_32)))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-09-30 15:06:44 +00:00
|
|
|
rela.AddUint64(ctxt.Arch, uint64(r.Add))
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Type = 256 // ignore during relocsym
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-07 13:49:44 -04:00
|
|
|
if ctxt.HeadType == objabi.Hdarwin && s.Size == int64(ctxt.Arch.PtrSize) && r.Off == 0 {
|
2015-02-27 22:57:28 -05:00
|
|
|
// 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
|
2016-03-01 23:21:55 +00:00
|
|
|
// for stderr. This is separate from the usual GOT entry,
|
2015-02-27 22:57:28 -05:00
|
|
|
// 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.
|
2016-08-21 13:52:23 -04:00
|
|
|
ld.Adddynsym(ctxt, targ)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
got := ctxt.Syms.Lookup(".got", 0)
|
2017-04-28 13:01:03 +12:00
|
|
|
s.Type = got.Type
|
|
|
|
|
s.Attr |= sym.AttrSubSymbol
|
2015-02-27 22:57:28 -05:00
|
|
|
s.Outer = got
|
|
|
|
|
s.Sub = got.Sub
|
|
|
|
|
got.Sub = s
|
|
|
|
|
s.Value = got.Size
|
2017-09-30 15:06:44 +00:00
|
|
|
got.AddUint64(ctxt.Arch, 0)
|
|
|
|
|
ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(targ.Dynid))
|
2015-02-27 22:57:28 -05:00
|
|
|
r.Type = 256 // ignore during relocsym
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-05 23:49:53 -04:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(sectoff))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2015-10-29 12:17:43 +13:00
|
|
|
elfsym := r.Xsym.ElfsymForReloc()
|
2015-02-27 22:57:28 -05:00
|
|
|
switch r.Type {
|
|
|
|
|
default:
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDR:
|
2015-02-27 22:57:28 -05:00
|
|
|
if r.Siz == 4 {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_32) | uint64(elfsym)<<32)
|
2015-02-27 22:57:28 -05:00
|
|
|
} else if r.Siz == 8 {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_64) | uint64(elfsym)<<32)
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_TLS_LE:
|
2015-02-27 22:57:28 -05:00
|
|
|
if r.Siz == 4 {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_TPOFF32) | uint64(elfsym)<<32)
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_TLS_IE:
|
2015-02-10 15:56:32 +13:00
|
|
|
if r.Siz == 4 {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_GOTTPOFF) | uint64(elfsym)<<32)
|
2015-02-10 15:56:32 +13:00
|
|
|
} else {
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-10 15:56:32 +13:00
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_CALL:
|
2015-02-27 22:57:28 -05:00
|
|
|
if r.Siz == 4 {
|
2017-10-04 17:54:04 -04:00
|
|
|
if r.Xsym.Type == sym.SDYNIMPORT {
|
2016-08-25 21:06:10 -04:00
|
|
|
if ctxt.DynlinkingGo() {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
|
2015-03-30 02:59:10 +00:00
|
|
|
} else {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32)
|
2015-03-30 02:59:10 +00:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
} else {
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_PCREL:
|
2015-02-27 22:57:28 -05:00
|
|
|
if r.Siz == 4 {
|
2017-10-04 17:54:04 -04:00
|
|
|
if r.Xsym.Type == sym.SDYNIMPORT && r.Xsym.ElfType == elf.STT_FUNC {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
|
2015-05-05 16:10:12 +12:00
|
|
|
} else {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
|
2015-05-05 16:10:12 +12:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_GOTPCREL:
|
2015-03-30 00:49:25 +00:00
|
|
|
if r.Siz == 4 {
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32)
|
2015-03-30 00:49:25 +00:00
|
|
|
} else {
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-03-30 00:49:25 +00:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(r.Xadd))
|
2017-08-27 22:00:00 +09:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
|
2015-02-27 22:57:28 -05:00
|
|
|
var v uint32
|
|
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
rs := r.Xsym
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2018-04-23 07:30:32 -07:00
|
|
|
if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_PCREL || r.Type == objabi.R_GOTPCREL || r.Type == objabi.R_CALL {
|
2015-02-27 22:57:28 -05:00
|
|
|
if rs.Dynid < 0 {
|
2017-10-04 17:54:04 -04:00
|
|
|
ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v = uint32(rs.Dynid)
|
|
|
|
|
v |= 1 << 27 // external relocation
|
|
|
|
|
} else {
|
2015-05-27 12:04:25 +12:00
|
|
|
v = uint32(rs.Sect.Extnum)
|
2015-02-27 22:57:28 -05:00
|
|
|
if v == 0 {
|
2017-10-04 17:54:04 -04:00
|
|
|
ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch r.Type {
|
|
|
|
|
default:
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDR:
|
2015-02-27 22:57:28 -05:00
|
|
|
v |= ld.MACHO_X86_64_RELOC_UNSIGNED << 28
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_CALL:
|
2015-02-27 22:57:28 -05:00
|
|
|
v |= 1 << 24 // pc-relative bit
|
|
|
|
|
v |= ld.MACHO_X86_64_RELOC_BRANCH << 28
|
|
|
|
|
|
|
|
|
|
// NOTE: Only works with 'external' relocation. Forced above.
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_PCREL:
|
2015-02-27 22:57:28 -05:00
|
|
|
v |= 1 << 24 // pc-relative bit
|
|
|
|
|
v |= ld.MACHO_X86_64_RELOC_SIGNED << 28
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_GOTPCREL:
|
2016-09-19 14:11:20 -04:00
|
|
|
v |= 1 << 24 // pc-relative bit
|
|
|
|
|
v |= ld.MACHO_X86_64_RELOC_GOT_LOAD << 28
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch r.Siz {
|
|
|
|
|
default:
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
v |= 0 << 25
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
v |= 1 << 25
|
|
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
v |= 2 << 25
|
|
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
|
v |= 3 << 25
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
out.Write32(uint32(sectoff))
|
|
|
|
|
out.Write32(v)
|
2017-08-27 22:00:00 +09:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
|
2015-03-13 22:10:48 -04:00
|
|
|
var v uint32
|
|
|
|
|
|
|
|
|
|
rs := r.Xsym
|
|
|
|
|
|
|
|
|
|
if rs.Dynid < 0 {
|
2017-10-04 17:54:04 -04:00
|
|
|
ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
|
2015-03-13 22:10:48 -04:00
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
out.Write32(uint32(sectoff))
|
|
|
|
|
out.Write32(uint32(rs.Dynid))
|
2015-03-13 22:10:48 -04:00
|
|
|
|
|
|
|
|
switch r.Type {
|
|
|
|
|
default:
|
|
|
|
|
return false
|
|
|
|
|
|
2017-10-24 16:08:46 -04:00
|
|
|
case objabi.R_DWARFSECREF:
|
2017-02-08 12:30:30 +11:00
|
|
|
v = ld.IMAGE_REL_AMD64_SECREL
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDR:
|
2015-03-13 22:10:48 -04:00
|
|
|
if r.Siz == 8 {
|
|
|
|
|
v = ld.IMAGE_REL_AMD64_ADDR64
|
|
|
|
|
} else {
|
|
|
|
|
v = ld.IMAGE_REL_AMD64_ADDR32
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_CALL,
|
|
|
|
|
objabi.R_PCREL:
|
2015-03-13 22:10:48 -04:00
|
|
|
v = ld.IMAGE_REL_AMD64_REL32
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
out.Write16(uint16(v))
|
2015-03-13 22:10:48 -04:00
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
cmd/link: fewer allocs in ld.Arch.Archreloc
Archreloc had this signature:
func(*Link, *sym.Reloc, *sym.Symbol, *int64) bool
The last *int64 argument is used as out parameter.
Passed valus could be allocated on stack, but escape analysis
fails here, leading to high number of unwanted allocs.
If instead 4th arg is passed by value, and modified values is returned,
no problems with allocations arise:
func(*Link, *sym.Reloc, *sym.Symbol, int64) (int64, bool)
There are 2 benefits:
1. code becomes more readable.
2. less allocations.
For linking "hello world" example from net/http:
name old time/op new time/op delta
Linker-4 530ms ± 2% 520ms ± 2% -1.83% (p=0.001 n=17+16)
It's top 1 in alloc_objects from memprofile:
flat flat% sum% cum cum%
229379 33.05% 33.05% 229379 33.05% cmd/link/internal/ld.relocsym
...
list relocsym:
229379 229379 (flat, cum) 33.05% of Total
229379 229379 183: var o int64
After the patch, ~230k of int64 allocs (~ 1.75mb) removed.
Passes toolshash-check (toolstash cmp).
Change-Id: I25504fe27967bcff70c4b7338790f3921d15473d
Reviewed-on: https://go-review.googlesource.com/113637
Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2018-05-17 19:50:29 +03:00
|
|
|
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
|
|
|
|
return val, false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
2015-02-27 22:57:28 -05:00
|
|
|
log.Fatalf("unexpected relocation variant")
|
|
|
|
|
return t
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-21 13:52:23 -04:00
|
|
|
func elfsetupplt(ctxt *ld.Link) {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
plt := ctxt.Syms.Lookup(".plt", 0)
|
|
|
|
|
got := ctxt.Syms.Lookup(".got.plt", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
if plt.Size == 0 {
|
|
|
|
|
// pushq got+8(IP)
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint8(0xff)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint8(0x35)
|
|
|
|
|
plt.AddPCRelPlus(ctxt.Arch, got, 8)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// jmpq got+16(IP)
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint8(0xff)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint8(0x25)
|
|
|
|
|
plt.AddPCRelPlus(ctxt.Arch, got, 16)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// nopl 0(AX)
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint32(ctxt.Arch, 0x00401f0f)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// assume got->size == 0 too
|
2017-09-30 15:06:44 +00:00
|
|
|
got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-09-30 15:06:44 +00:00
|
|
|
got.AddUint64(ctxt.Arch, 0)
|
|
|
|
|
got.AddUint64(ctxt.Arch, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
|
2015-02-27 22:57:28 -05:00
|
|
|
if s.Plt >= 0 {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-21 13:52:23 -04:00
|
|
|
ld.Adddynsym(ctxt, s)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-07 13:43:38 -04:00
|
|
|
if ctxt.IsELF {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
plt := ctxt.Syms.Lookup(".plt", 0)
|
|
|
|
|
got := ctxt.Syms.Lookup(".got.plt", 0)
|
|
|
|
|
rela := ctxt.Syms.Lookup(".rela.plt", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
if plt.Size == 0 {
|
2016-08-21 13:52:23 -04:00
|
|
|
elfsetupplt(ctxt)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// jmpq *got+size(IP)
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint8(0xff)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint8(0x25)
|
|
|
|
|
plt.AddPCRelPlus(ctxt.Arch, got, got.Size)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// add to got: pointer to current pos in plt
|
2017-09-30 15:06:44 +00:00
|
|
|
got.AddAddrPlus(ctxt.Arch, plt, plt.Size)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// pushq $x
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint8(0x68)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint32(ctxt.Arch, uint32((got.Size-24-8)/8))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// jmpq .plt
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint8(0xe9)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint32(ctxt.Arch, uint32(-(plt.Size + 4)))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// rela
|
2017-09-30 15:06:44 +00:00
|
|
|
rela.AddAddrPlus(ctxt.Arch, got, got.Size-8)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-06 16:01:02 -04:00
|
|
|
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_X86_64_JMP_SLOT)))
|
2017-09-30 15:06:44 +00:00
|
|
|
rela.AddUint64(ctxt.Arch, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
s.Plt = int32(plt.Size - 16)
|
2017-10-07 13:49:44 -04:00
|
|
|
} else if ctxt.HeadType == objabi.Hdarwin {
|
2015-02-27 22:57:28 -05:00
|
|
|
// 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
|
2016-03-01 23:21:55 +00:00
|
|
|
// section just so. I'm too lazy (ha!) to do that
|
2015-02-27 22:57:28 -05:00
|
|
|
// so for now we'll just use non-lazy pointers,
|
|
|
|
|
// which don't need to be told which library to use.
|
|
|
|
|
//
|
2018-06-01 17:29:59 -03:00
|
|
|
// https://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html
|
2015-02-27 22:57:28 -05:00
|
|
|
// has details about what we're avoiding.
|
|
|
|
|
|
2016-08-21 13:52:23 -04:00
|
|
|
addgotsym(ctxt, s)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
plt := ctxt.Syms.Lookup(".plt", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-09-30 15:06:44 +00:00
|
|
|
ctxt.Syms.Lookup(".linkedit.plt", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// jmpq *got+size(IP)
|
|
|
|
|
s.Plt = int32(plt.Size)
|
|
|
|
|
|
2017-09-30 15:06:44 +00:00
|
|
|
plt.AddUint8(0xff)
|
|
|
|
|
plt.AddUint8(0x25)
|
|
|
|
|
plt.AddPCRelPlus(ctxt.Arch, ctxt.Syms.Lookup(".got", 0), int64(s.Got))
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "addpltsym: unsupported binary format")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
|
2015-02-27 22:57:28 -05:00
|
|
|
if s.Got >= 0 {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-21 13:52:23 -04:00
|
|
|
ld.Adddynsym(ctxt, s)
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
got := ctxt.Syms.Lookup(".got", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
s.Got = int32(got.Size)
|
2017-09-30 15:06:44 +00:00
|
|
|
got.AddUint64(ctxt.Arch, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-07 13:43:38 -04:00
|
|
|
if ctxt.IsELF {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
rela := ctxt.Syms.Lookup(".rela", 0)
|
2017-09-30 15:06:44 +00:00
|
|
|
rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got))
|
2017-10-06 16:01:02 -04:00
|
|
|
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_X86_64_GLOB_DAT)))
|
2017-09-30 15:06:44 +00:00
|
|
|
rela.AddUint64(ctxt.Arch, 0)
|
2017-10-07 13:49:44 -04:00
|
|
|
} else if ctxt.HeadType == objabi.Hdarwin {
|
2017-09-30 15:06:44 +00:00
|
|
|
ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "addgotsym: unsupported binary format")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func asmb(ctxt *ld.Link) {
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f asmb\n", ld.Cputime())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f codeblk\n", ld.Cputime())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-07 13:43:38 -04:00
|
|
|
if ctxt.IsELF {
|
2016-09-20 15:57:53 +12:00
|
|
|
ld.Asmbelfsetup()
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 21:52:06 +12:00
|
|
|
sect := ld.Segtext.Sections[0]
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
|
2016-06-11 17:12:28 -07:00
|
|
|
// 0xCC is INT $3 - breakpoint instruction
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC})
|
2017-04-18 21:52:06 +12:00
|
|
|
for _, sect = range ld.Segtext.Sections[1:] {
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ld.Segrodata.Filelen > 0 {
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-09-05 23:29:16 -04:00
|
|
|
if ld.Segrelrodata.Filelen > 0 {
|
|
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime())
|
2016-09-05 23:29:16 -04:00
|
|
|
}
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
|
2016-09-05 23:29:16 -04:00
|
|
|
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f datblk\n", ld.Cputime())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
machlink := int64(0)
|
2017-10-07 13:49:44 -04:00
|
|
|
if ctxt.HeadType == objabi.Hdarwin {
|
2016-08-19 22:40:38 -04:00
|
|
|
machlink = ld.Domacholink(ctxt)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-07 13:49:44 -04:00
|
|
|
switch ctxt.HeadType {
|
2015-02-27 22:57:28 -05:00
|
|
|
default:
|
2017-10-07 13:49:44 -04:00
|
|
|
ld.Errorf(nil, "unknown header type %v", ctxt.HeadType)
|
2015-02-27 22:57:28 -05:00
|
|
|
fallthrough
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hplan9:
|
2015-02-27 22:57:28 -05:00
|
|
|
break
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hdarwin:
|
2016-08-21 18:34:24 -04:00
|
|
|
ld.Flag8 = true /* 64-bit addresses */
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hlinux,
|
|
|
|
|
objabi.Hfreebsd,
|
|
|
|
|
objabi.Hnetbsd,
|
|
|
|
|
objabi.Hopenbsd,
|
|
|
|
|
objabi.Hdragonfly,
|
|
|
|
|
objabi.Hsolaris:
|
2016-08-21 18:34:24 -04:00
|
|
|
ld.Flag8 = true /* 64-bit addresses */
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hnacl,
|
|
|
|
|
objabi.Hwindows:
|
2015-02-27 22:57:28 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ld.Symsize = 0
|
|
|
|
|
ld.Spsize = 0
|
|
|
|
|
ld.Lcsize = 0
|
2015-03-02 12:35:15 -05:00
|
|
|
symo := int64(0)
|
2016-08-21 18:34:24 -04:00
|
|
|
if !*ld.FlagS {
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f sym\n", ld.Cputime())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-10-07 13:49:44 -04:00
|
|
|
switch ctxt.HeadType {
|
2015-02-27 22:57:28 -05:00
|
|
|
default:
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hplan9:
|
2016-08-21 18:34:24 -04:00
|
|
|
*ld.FlagS = true
|
2015-02-27 22:57:28 -05:00
|
|
|
symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hdarwin:
|
2016-08-21 18:34:24 -04:00
|
|
|
symo = int64(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hlinux,
|
|
|
|
|
objabi.Hfreebsd,
|
|
|
|
|
objabi.Hnetbsd,
|
|
|
|
|
objabi.Hopenbsd,
|
|
|
|
|
objabi.Hdragonfly,
|
|
|
|
|
objabi.Hsolaris,
|
|
|
|
|
objabi.Hnacl:
|
2016-03-14 09:23:04 -07:00
|
|
|
symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
|
2016-08-21 18:34:24 -04:00
|
|
|
symo = ld.Rnd(symo, int64(*ld.FlagRound))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hwindows:
|
2016-03-14 09:23:04 -07:00
|
|
|
symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
|
2015-02-27 22:57:28 -05:00
|
|
|
symo = ld.Rnd(symo, ld.PEFILEALIGN)
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(symo)
|
2017-10-07 13:49:44 -04:00
|
|
|
switch ctxt.HeadType {
|
2015-02-27 22:57:28 -05:00
|
|
|
default:
|
2017-10-07 13:43:38 -04:00
|
|
|
if ctxt.IsELF {
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(symo)
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Asmelfsym(ctxt)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Flush()
|
|
|
|
|
ctxt.Out.Write(ld.Elfstrdat)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f dwarf\n", ld.Cputime())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-05 10:20:17 -04:00
|
|
|
if ctxt.LinkMode == ld.LinkExternal {
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Elfemitreloc(ctxt)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hplan9:
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Asmplan9sym(ctxt)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Flush()
|
2015-02-27 22:57:28 -05:00
|
|
|
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
sym := ctxt.Syms.Lookup("pclntab", 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
if sym != nil {
|
|
|
|
|
ld.Lcsize = int32(len(sym.P))
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write(sym.P)
|
|
|
|
|
ctxt.Out.Flush()
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hwindows:
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f dwarf\n", ld.Cputime())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hdarwin:
|
2017-10-05 10:20:17 -04:00
|
|
|
if ctxt.LinkMode == ld.LinkExternal {
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Machoemitreloc(ctxt)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f headr\n", ld.Cputime())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(0)
|
2017-10-07 13:49:44 -04:00
|
|
|
switch ctxt.HeadType {
|
2015-02-27 22:57:28 -05:00
|
|
|
default:
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hplan9: /* plan9 */
|
2015-03-02 12:35:15 -05:00
|
|
|
magic := int32(4*26*26 + 7)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
magic |= 0x00008000 /* fat header */
|
|
|
|
|
ctxt.Out.Write32b(uint32(magic)) /* magic */
|
|
|
|
|
ctxt.Out.Write32b(uint32(ld.Segtext.Filelen)) /* sizes */
|
|
|
|
|
ctxt.Out.Write32b(uint32(ld.Segdata.Filelen))
|
|
|
|
|
ctxt.Out.Write32b(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
|
|
|
|
|
ctxt.Out.Write32b(uint32(ld.Symsize)) /* nsyms */
|
2016-08-19 22:40:38 -04:00
|
|
|
vl := ld.Entryvalue(ctxt)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write32b(PADDR(uint32(vl))) /* va of entry */
|
|
|
|
|
ctxt.Out.Write32b(uint32(ld.Spsize)) /* sp offsets */
|
|
|
|
|
ctxt.Out.Write32b(uint32(ld.Lcsize)) /* line offsets */
|
|
|
|
|
ctxt.Out.Write64b(uint64(vl)) /* va of entry */
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hdarwin:
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Asmbmacho(ctxt)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hlinux,
|
|
|
|
|
objabi.Hfreebsd,
|
|
|
|
|
objabi.Hnetbsd,
|
|
|
|
|
objabi.Hopenbsd,
|
|
|
|
|
objabi.Hdragonfly,
|
|
|
|
|
objabi.Hsolaris,
|
|
|
|
|
objabi.Hnacl:
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Asmbelf(ctxt, symo)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hwindows:
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Asmbpe(ctxt)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Flush()
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-09-06 07:46:59 -04:00
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func tlsIEtoLE(s *sym.Symbol, off, size int) {
|
2016-09-06 07:46:59 -04:00
|
|
|
// Transform the PC-relative instruction into a constant load.
|
|
|
|
|
// That is,
|
|
|
|
|
//
|
|
|
|
|
// MOVQ X(IP), REG -> MOVQ $Y, REG
|
|
|
|
|
//
|
|
|
|
|
// To determine the instruction and register, we study the op codes.
|
|
|
|
|
// Consult an AMD64 instruction encoding guide to decipher this.
|
2016-09-06 07:46:59 -04:00
|
|
|
if off < 3 {
|
|
|
|
|
log.Fatal("R_X86_64_GOTTPOFF reloc not preceded by MOVQ or ADDQ instruction")
|
|
|
|
|
}
|
2016-09-06 07:46:59 -04:00
|
|
|
op := s.P[off-3 : off]
|
|
|
|
|
reg := op[2] >> 3
|
|
|
|
|
|
|
|
|
|
if op[1] == 0x8b || reg == 4 {
|
|
|
|
|
// MOVQ
|
|
|
|
|
if op[0] == 0x4c {
|
|
|
|
|
op[0] = 0x49
|
|
|
|
|
} else if size == 4 && op[0] == 0x44 {
|
|
|
|
|
op[0] = 0x41
|
|
|
|
|
}
|
|
|
|
|
if op[1] == 0x8b {
|
|
|
|
|
op[1] = 0xc7
|
|
|
|
|
} else {
|
|
|
|
|
op[1] = 0x81 // special case for SP
|
|
|
|
|
}
|
|
|
|
|
op[2] = 0xc0 | reg
|
|
|
|
|
} else {
|
|
|
|
|
// An alternate op is ADDQ. This is handled by GNU gold,
|
|
|
|
|
// but right now is not generated by the Go compiler:
|
|
|
|
|
// ADDQ X(IP), REG -> ADDQ $Y, REG
|
|
|
|
|
// Consider adding support for it here.
|
|
|
|
|
log.Fatalf("expected TLS IE op to be MOVQ, got %v", op)
|
|
|
|
|
}
|
|
|
|
|
}
|