2015-02-27 22:57:28 -05:00
|
|
|
// Inferno utils/5l/asm.c
|
2016-08-28 17:04:46 -07:00
|
|
|
// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/5l/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 ppc64
|
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"
|
2020-03-11 12:12:41 -04:00
|
|
|
"cmd/link/internal/loader"
|
2017-10-04 17:54:04 -04:00
|
|
|
"cmd/link/internal/sym"
|
2017-10-06 16:01:02 -04:00
|
|
|
"debug/elf"
|
2015-03-01 22:02:13 -05:00
|
|
|
"encoding/binary"
|
2015-02-27 22:57:28 -05:00
|
|
|
"fmt"
|
|
|
|
|
"log"
|
2018-11-26 11:14:09 +01:00
|
|
|
"strings"
|
2020-03-20 12:24:35 -04:00
|
|
|
"sync"
|
2015-02-27 22:57:28 -05:00
|
|
|
)
|
|
|
|
|
|
2020-04-02 08:27:09 -04:00
|
|
|
func genplt2(ctxt *ld.Link, ldr *loader.Loader) {
|
2015-02-27 22:57:28 -05:00
|
|
|
// The ppc64 ABI PLT has similar concepts to other
|
2016-03-01 23:21:55 +00:00
|
|
|
// architectures, but is laid out quite differently. When we
|
2015-02-27 22:57:28 -05:00
|
|
|
// see an R_PPC64_REL24 relocation to a dynamic symbol
|
|
|
|
|
// (indicating that the call needs to go through the PLT), we
|
|
|
|
|
// generate up to three stubs and reserve a PLT slot.
|
|
|
|
|
//
|
|
|
|
|
// 1) The call site will be bl x; nop (where the relocation
|
|
|
|
|
// applies to the bl). We rewrite this to bl x_stub; ld
|
|
|
|
|
// r2,24(r1). The ld is necessary because x_stub will save
|
|
|
|
|
// r2 (the TOC pointer) at 24(r1) (the "TOC save slot").
|
|
|
|
|
//
|
|
|
|
|
// 2) We reserve space for a pointer in the .plt section (once
|
|
|
|
|
// per referenced dynamic function). .plt is a data
|
|
|
|
|
// section filled solely by the dynamic linker (more like
|
|
|
|
|
// .plt.got on other architectures). Initially, the
|
|
|
|
|
// dynamic linker will fill each slot with a pointer to the
|
|
|
|
|
// corresponding x@plt entry point.
|
|
|
|
|
//
|
|
|
|
|
// 3) We generate the "call stub" x_stub (once per dynamic
|
|
|
|
|
// function/object file pair). This saves the TOC in the
|
|
|
|
|
// TOC save slot, reads the function pointer from x's .plt
|
|
|
|
|
// slot and calls it like any other global entry point
|
|
|
|
|
// (including setting r12 to the function address).
|
|
|
|
|
//
|
|
|
|
|
// 4) We generate the "symbol resolver stub" x@plt (once per
|
|
|
|
|
// dynamic function). This is solely a branch to the glink
|
|
|
|
|
// resolver stub.
|
|
|
|
|
//
|
|
|
|
|
// 5) We generate the glink resolver stub (only once). This
|
|
|
|
|
// computes which symbol resolver stub we came through and
|
|
|
|
|
// invokes the dynamic resolver via a pointer provided by
|
2016-03-01 23:21:55 +00:00
|
|
|
// the dynamic linker. This will patch up the .plt slot to
|
2015-02-27 22:57:28 -05:00
|
|
|
// point directly at the function so future calls go
|
|
|
|
|
// straight from the call stub to the real function, and
|
|
|
|
|
// then call the function.
|
|
|
|
|
|
|
|
|
|
// NOTE: It's possible we could make ppc64 closer to other
|
|
|
|
|
// architectures: ppc64's .plt is like .plt.got on other
|
|
|
|
|
// platforms and ppc64's .glink is like .plt on other
|
|
|
|
|
// platforms.
|
|
|
|
|
|
|
|
|
|
// Find all R_PPC64_REL24 relocations that reference dynamic
|
2016-03-01 23:21:55 +00:00
|
|
|
// imports. Reserve PLT entries for these symbols and
|
|
|
|
|
// generate call stubs. The call stubs need to live in .text,
|
2015-02-27 22:57:28 -05:00
|
|
|
// which is why we need to do this pass this early.
|
|
|
|
|
//
|
|
|
|
|
// This assumes "case 1" from the ABI, where the caller needs
|
|
|
|
|
// us to save and restore the TOC pointer.
|
2020-04-02 08:27:09 -04:00
|
|
|
var stubs []loader.Sym
|
|
|
|
|
for _, s := range ctxt.Textp2 {
|
|
|
|
|
relocs := ldr.Relocs(s)
|
|
|
|
|
for i := 0; i < relocs.Count(); i++ {
|
|
|
|
|
r := relocs.At2(i)
|
|
|
|
|
if r.Type() != objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_REL24) || ldr.SymType(r.Sym()) != sym.SDYNIMPORT {
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reserve PLT entry and generate symbol
|
|
|
|
|
// resolver
|
2020-04-02 08:27:09 -04:00
|
|
|
addpltsym2(ctxt, ldr, r.Sym())
|
|
|
|
|
|
|
|
|
|
// Generate call stub. Important to note that we're looking
|
|
|
|
|
// up the stub using the same version as the parent symbol (s),
|
|
|
|
|
// needed so that symtoc() will select the right .TOC. symbol
|
|
|
|
|
// when processing the stub. In older versions of the linker
|
|
|
|
|
// this was done by setting stub.Outer to the parent, but
|
|
|
|
|
// if the stub has the right version initially this is not needed.
|
|
|
|
|
n := fmt.Sprintf("%s.%s", ldr.SymName(s), ldr.SymName(r.Sym()))
|
|
|
|
|
stub := ldr.CreateSymForUpdate(n, ldr.SymVersion(s))
|
|
|
|
|
if stub.Size() == 0 {
|
|
|
|
|
stubs = append(stubs, stub.Sym())
|
|
|
|
|
gencallstub2(ctxt, ldr, 1, stub, r.Sym())
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update the relocation to use the call stub
|
2020-04-02 08:27:09 -04:00
|
|
|
r.SetSym(stub.Sym())
|
|
|
|
|
|
|
|
|
|
// make sure the data is writeable
|
|
|
|
|
if ldr.AttrReadOnly(s) {
|
|
|
|
|
panic("can't write to read-only sym data")
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-03-01 23:21:55 +00:00
|
|
|
// Restore TOC after bl. The compiler put a
|
2015-02-27 22:57:28 -05:00
|
|
|
// nop here for us to overwrite.
|
2020-04-02 08:27:09 -04:00
|
|
|
sp := ldr.Data(s)
|
2016-04-20 14:40:18 -04:00
|
|
|
const o1 = 0xe8410018 // ld r2,24(r1)
|
2020-04-02 08:27:09 -04:00
|
|
|
ctxt.Arch.ByteOrder.PutUint32(sp[r.Off()+4:], o1)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
2017-03-13 08:24:46 -04:00
|
|
|
// Put call stubs at the beginning (instead of the end).
|
|
|
|
|
// So when resolving the relocations to calls to the stubs,
|
|
|
|
|
// the addresses are known and trampolines can be inserted
|
|
|
|
|
// when necessary.
|
2020-04-02 08:27:09 -04:00
|
|
|
ctxt.Textp2 = append(stubs, ctxt.Textp2...)
|
2015-10-16 21:22:20 +13:00
|
|
|
}
|
|
|
|
|
|
2020-04-02 08:27:09 -04:00
|
|
|
func genaddmoduledata2(ctxt *ld.Link, ldr *loader.Loader) {
|
|
|
|
|
initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
|
|
|
|
|
if initfunc == nil {
|
2015-10-16 21:22:20 +13:00
|
|
|
return
|
|
|
|
|
}
|
2020-04-02 08:27:09 -04:00
|
|
|
|
2015-10-16 21:22:20 +13:00
|
|
|
o := func(op uint32) {
|
2017-09-30 15:06:44 +00:00
|
|
|
initfunc.AddUint32(ctxt.Arch, op)
|
2015-10-16 21:22:20 +13:00
|
|
|
}
|
2020-04-02 08:27:09 -04:00
|
|
|
|
2015-10-16 21:22:20 +13:00
|
|
|
// addis r2, r12, .TOC.-func@ha
|
2020-04-02 08:27:09 -04:00
|
|
|
toc := ctxt.DotTOC2[0]
|
|
|
|
|
rel1 := loader.Reloc{
|
|
|
|
|
Off: 0,
|
|
|
|
|
Size: 8,
|
|
|
|
|
Type: objabi.R_ADDRPOWER_PCREL,
|
|
|
|
|
Sym: toc,
|
|
|
|
|
}
|
|
|
|
|
initfunc.AddReloc(rel1)
|
2015-10-16 21:22:20 +13:00
|
|
|
o(0x3c4c0000)
|
|
|
|
|
// addi r2, r2, .TOC.-func@l
|
|
|
|
|
o(0x38420000)
|
|
|
|
|
// mflr r31
|
|
|
|
|
o(0x7c0802a6)
|
|
|
|
|
// stdu r31, -32(r1)
|
|
|
|
|
o(0xf801ffe1)
|
|
|
|
|
// addis r3, r2, local.moduledata@got@ha
|
2020-04-02 08:27:09 -04:00
|
|
|
var tgt loader.Sym
|
|
|
|
|
if s := ldr.Lookup("local.moduledata", 0); s != 0 {
|
|
|
|
|
tgt = s
|
|
|
|
|
} else if s := ldr.Lookup("local.pluginmoduledata", 0); s != 0 {
|
|
|
|
|
tgt = s
|
2017-08-15 14:34:53 -04:00
|
|
|
} else {
|
2020-04-02 08:27:09 -04:00
|
|
|
tgt = ldr.LookupOrCreateSym("runtime.firstmoduledata", 0)
|
|
|
|
|
}
|
|
|
|
|
rel2 := loader.Reloc{
|
|
|
|
|
Off: int32(initfunc.Size()),
|
|
|
|
|
Size: 8,
|
|
|
|
|
Type: objabi.R_ADDRPOWER_GOT,
|
|
|
|
|
Sym: tgt,
|
2017-08-15 14:34:53 -04:00
|
|
|
}
|
2020-04-02 08:27:09 -04:00
|
|
|
initfunc.AddReloc(rel2)
|
2015-10-16 21:22:20 +13:00
|
|
|
o(0x3c620000)
|
|
|
|
|
// ld r3, local.moduledata@got@l(r3)
|
|
|
|
|
o(0xe8630000)
|
|
|
|
|
// bl runtime.addmoduledata
|
2020-04-02 08:27:09 -04:00
|
|
|
rel3 := loader.Reloc{
|
|
|
|
|
Off: int32(initfunc.Size()),
|
|
|
|
|
Size: 4,
|
|
|
|
|
Type: objabi.R_CALLPOWER,
|
|
|
|
|
Sym: addmoduledata,
|
|
|
|
|
}
|
|
|
|
|
initfunc.AddReloc(rel3)
|
2015-10-16 21:22:20 +13:00
|
|
|
o(0x48000001)
|
|
|
|
|
// nop
|
|
|
|
|
o(0x60000000)
|
|
|
|
|
// ld r31, 0(r1)
|
|
|
|
|
o(0xe8010000)
|
|
|
|
|
// mtlr r31
|
|
|
|
|
o(0x7c0803a6)
|
|
|
|
|
// addi r1,r1,32
|
|
|
|
|
o(0x38210020)
|
|
|
|
|
// blr
|
|
|
|
|
o(0x4e800020)
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-02 08:27:09 -04:00
|
|
|
func gentext2(ctxt *ld.Link, ldr *loader.Loader) {
|
2016-08-25 21:06:10 -04:00
|
|
|
if ctxt.DynlinkingGo() {
|
2020-04-02 08:27:09 -04:00
|
|
|
genaddmoduledata2(ctxt, ldr)
|
2015-10-16 21:22:20 +13:00
|
|
|
}
|
|
|
|
|
|
2017-10-05 10:20:17 -04:00
|
|
|
if ctxt.LinkMode == ld.LinkInternal {
|
2020-04-02 08:27:09 -04:00
|
|
|
genplt2(ctxt, ldr)
|
2015-10-16 21:22:20 +13:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Construct a call stub in stub that calls symbol targ via its PLT
|
|
|
|
|
// entry.
|
2020-04-02 08:27:09 -04:00
|
|
|
func gencallstub2(ctxt *ld.Link, ldr *loader.Loader, abicase int, stub *loader.SymbolBuilder, targ loader.Sym) {
|
2015-02-27 22:57:28 -05:00
|
|
|
if abicase != 1 {
|
|
|
|
|
// If we see R_PPC64_TOCSAVE or R_PPC64_REL24_NOTOC
|
|
|
|
|
// relocations, we'll need to implement cases 2 and 3.
|
|
|
|
|
log.Fatalf("gencallstub only implements case 1 calls")
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-02 08:27:09 -04:00
|
|
|
plt := ctxt.PLT2
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2020-04-02 08:27:09 -04:00
|
|
|
stub.SetType(sym.STEXT)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Save TOC pointer in TOC save slot
|
2017-09-30 15:06:44 +00:00
|
|
|
stub.AddUint32(ctxt.Arch, 0xf8410018) // std r2,24(r1)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Load the function pointer from the PLT.
|
2020-04-02 08:27:09 -04:00
|
|
|
rel := loader.Reloc{
|
|
|
|
|
Off: int32(stub.Size()),
|
|
|
|
|
Size: 2,
|
|
|
|
|
Add: int64(ldr.SymPlt(targ)),
|
|
|
|
|
Type: objabi.R_POWER_TOC,
|
|
|
|
|
Sym: plt,
|
|
|
|
|
}
|
2016-08-21 13:52:23 -04:00
|
|
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
2020-04-02 08:27:09 -04:00
|
|
|
rel.Off += int32(rel.Size)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2020-04-02 08:27:09 -04:00
|
|
|
ri1 := stub.AddReloc(rel)
|
|
|
|
|
ldr.SetRelocVariant(stub.Sym(), int(ri1), sym.RV_POWER_HA)
|
2017-09-30 15:06:44 +00:00
|
|
|
stub.AddUint32(ctxt.Arch, 0x3d820000) // addis r12,r2,targ@plt@toc@ha
|
2020-04-02 08:27:09 -04:00
|
|
|
|
|
|
|
|
rel2 := loader.Reloc{
|
|
|
|
|
Off: int32(stub.Size()),
|
|
|
|
|
Size: 2,
|
|
|
|
|
Add: int64(ldr.SymPlt(targ)),
|
|
|
|
|
Type: objabi.R_POWER_TOC,
|
|
|
|
|
Sym: plt,
|
|
|
|
|
}
|
2016-08-21 13:52:23 -04:00
|
|
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
2020-04-02 08:27:09 -04:00
|
|
|
rel2.Off += int32(rel.Size)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2020-04-02 08:27:09 -04:00
|
|
|
ri2 := stub.AddReloc(rel2)
|
|
|
|
|
ldr.SetRelocVariant(stub.Sym(), int(ri2), sym.RV_POWER_LO)
|
2017-09-30 15:06:44 +00:00
|
|
|
stub.AddUint32(ctxt.Arch, 0xe98c0000) // ld r12,targ@plt@toc@l(r12)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Jump to the loaded pointer
|
2017-09-30 15:06:44 +00:00
|
|
|
stub.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12
|
|
|
|
|
stub.AddUint32(ctxt.Arch, 0x4e800420) // bctr
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2020-04-30 01:32:48 -04:00
|
|
|
func adddynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
|
2020-03-04 17:25:01 -05:00
|
|
|
if target.IsElf() {
|
2020-04-24 15:32:46 -04:00
|
|
|
return addelfdynrel2(target, ldr, syms, s, r, rIdx)
|
2020-03-04 17:25:01 -05:00
|
|
|
} else if target.IsAIX() {
|
2020-04-24 15:32:46 -04:00
|
|
|
return ld.Xcoffadddynrel2(target, ldr, syms, s, r, rIdx)
|
2018-11-23 13:29:59 +01:00
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
2020-03-04 17:25:01 -05:00
|
|
|
|
2020-04-30 01:32:48 -04:00
|
|
|
func addelfdynrel2(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc2, rIdx int) bool {
|
2020-04-24 15:32:46 -04:00
|
|
|
targ := r.Sym()
|
|
|
|
|
var targType sym.SymKind
|
|
|
|
|
if targ != 0 {
|
|
|
|
|
targType = ldr.SymType(targ)
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2020-04-24 15:32:46 -04:00
|
|
|
switch r.Type() {
|
2015-02-27 22:57:28 -05:00
|
|
|
default:
|
2020-04-24 15:32:46 -04:00
|
|
|
if r.Type() >= objabi.ElfRelocOffset {
|
|
|
|
|
ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.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.
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_CALLPOWER)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// This is a local call, so the caller isn't setting
|
|
|
|
|
// up r12 and r2 is the same for the caller and
|
2016-03-01 23:21:55 +00:00
|
|
|
// callee. Hence, we need to go to the local entry
|
2015-02-27 22:57:28 -05:00
|
|
|
// point. (If we don't do this, the callee will try
|
|
|
|
|
// to use r12 to compute r2.)
|
2020-04-24 15:32:46 -04:00
|
|
|
su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymLocalentry(targ))*4)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2020-04-24 15:32:46 -04:00
|
|
|
if targType == sym.SDYNIMPORT {
|
2015-02-27 22:57:28 -05:00
|
|
|
// Should have been handled in elfsetupplt
|
2020-04-24 15:32:46 -04:00
|
|
|
ldr.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
|
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
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_PCREL)
|
|
|
|
|
su.SetRelocAdd(rIdx, r.Add()+4)
|
2015-11-23 12:55:37 -08:00
|
|
|
|
2020-04-24 15:32:46 -04:00
|
|
|
if targType == sym.SDYNIMPORT {
|
|
|
|
|
ldr.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
|
2015-11-23 12:55:37 -08:00
|
|
|
}
|
|
|
|
|
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-11-23 12:55:37 -08:00
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_ADDR)
|
|
|
|
|
if targType == sym.SDYNIMPORT {
|
2015-02-27 22:57:28 -05:00
|
|
|
// These happen in .toc sections
|
2020-04-24 15:32:46 -04:00
|
|
|
ld.Adddynsym2(ldr, target, syms, targ)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2020-04-24 15:32:46 -04:00
|
|
|
rela := ldr.MakeSymbolUpdater(syms.Rela2)
|
|
|
|
|
rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
|
|
|
|
|
rela.AddUint64(target.Arch, ld.ELF64_R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64)))
|
|
|
|
|
rela.AddUint64(target.Arch, uint64(r.Add()))
|
|
|
|
|
su.SetRelocType(rIdx, objabi.ElfRelocOffset) // ignore during relocsym
|
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
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
|
|
|
|
|
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO|sym.RV_CHECK_OVERFLOW)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
|
|
|
|
|
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
|
|
|
|
|
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
|
|
|
|
|
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
|
|
|
|
|
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS|sym.RV_CHECK_OVERFLOW)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_POWER_TOC)
|
|
|
|
|
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_PCREL)
|
|
|
|
|
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
|
|
|
|
|
su.SetRelocAdd(rIdx, r.Add()+2) // Compensate for relocation size of 2
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_PCREL)
|
|
|
|
|
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
|
|
|
|
|
su.SetRelocAdd(rIdx, r.Add()+2)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2019-04-16 02:49:09 +00:00
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
|
2020-04-24 15:32:46 -04:00
|
|
|
su := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
su.SetRelocType(rIdx, objabi.R_PCREL)
|
|
|
|
|
ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
|
|
|
|
|
su.SetRelocAdd(rIdx, r.Add()+2)
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle references to ELF symbols from our own object files.
|
2020-04-24 15:32:46 -04:00
|
|
|
if targType != sym.SDYNIMPORT {
|
2016-09-05 23:49:53 -04:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO(austin): Translate our relocations to ELF
|
|
|
|
|
|
2016-09-05 23:49:53 -04:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2019-02-20 16:16:38 +01:00
|
|
|
func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
|
|
|
|
|
rs := r.Xsym
|
|
|
|
|
|
|
|
|
|
emitReloc := func(v uint16, off uint64) {
|
|
|
|
|
out.Write64(uint64(sectoff) + off)
|
|
|
|
|
out.Write32(uint32(rs.Dynid))
|
|
|
|
|
out.Write16(v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var v uint16
|
|
|
|
|
switch r.Type {
|
|
|
|
|
default:
|
|
|
|
|
return false
|
|
|
|
|
case objabi.R_ADDR:
|
|
|
|
|
v = ld.XCOFF_R_POS
|
|
|
|
|
if r.Siz == 4 {
|
|
|
|
|
v |= 0x1F << 8
|
|
|
|
|
} else {
|
|
|
|
|
v |= 0x3F << 8
|
|
|
|
|
}
|
|
|
|
|
emitReloc(v, 0)
|
|
|
|
|
case objabi.R_ADDRPOWER_TOCREL:
|
|
|
|
|
case objabi.R_ADDRPOWER_TOCREL_DS:
|
|
|
|
|
emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2)
|
|
|
|
|
emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6)
|
|
|
|
|
case objabi.R_POWER_TLS_LE:
|
|
|
|
|
emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
|
|
|
|
|
case objabi.R_CALLPOWER:
|
|
|
|
|
if r.Siz != 4 {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
|
2019-02-20 16:20:56 +01:00
|
|
|
case objabi.R_XCOFFREF:
|
|
|
|
|
emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
|
|
|
|
|
|
2019-02-20 16:16:38 +01:00
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
|
2018-11-16 15:39:59 +00:00
|
|
|
// Beware that bit0~bit15 start from the third byte of a instruction in Big-Endian machines.
|
2018-11-28 13:38:02 +01:00
|
|
|
if r.Type == objabi.R_ADDR || r.Type == objabi.R_POWER_TLS || r.Type == objabi.R_CALLPOWER {
|
2018-11-16 15:39:59 +00:00
|
|
|
} else {
|
|
|
|
|
if ctxt.Arch.ByteOrder == binary.BigEndian {
|
|
|
|
|
sectoff += 2
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(sectoff))
|
2015-09-04 08:30:15 +12:00
|
|
|
|
2020-04-28 10:51:40 -04:00
|
|
|
elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
|
2015-09-04 08:30:15 +12:00
|
|
|
switch r.Type {
|
|
|
|
|
default:
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2020-04-29 22:00:28 -04:00
|
|
|
case objabi.R_ADDR, objabi.R_DWARFSECREF:
|
2015-09-04 08:30:15 +12:00
|
|
|
switch r.Siz {
|
|
|
|
|
case 4:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32)
|
2015-09-04 08:30:15 +12:00
|
|
|
case 8:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32)
|
2015-09-04 08:30:15 +12:00
|
|
|
default:
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-09-04 08:30:15 +12:00
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_POWER_TLS:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_POWER_TLS_LE:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_TPREL16) | uint64(elfsym)<<32)
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_POWER_TLS_IE:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(r.Xadd))
|
|
|
|
|
ctxt.Out.Write64(uint64(sectoff + 4))
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32)
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(r.Xadd))
|
|
|
|
|
ctxt.Out.Write64(uint64(sectoff + 4))
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32)
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER_DS:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(r.Xadd))
|
|
|
|
|
ctxt.Out.Write64(uint64(sectoff + 4))
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32)
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER_GOT:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(r.Xadd))
|
|
|
|
|
ctxt.Out.Write64(uint64(sectoff + 4))
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32)
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER_PCREL:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(r.Xadd))
|
|
|
|
|
ctxt.Out.Write64(uint64(sectoff + 4))
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32)
|
cmd/compile, cmd/link, runtime: on ppc64x, maintain the TOC pointer in R2 when compiling PIC
The PowerPC ISA does not have a PC-relative load instruction, which poses
obvious challenges when generating position-independent code. The way the ELFv2
ABI addresses this is to specify that r2 points to a per "module" (shared
library or executable) TOC pointer. Maintaining this pointer requires
cooperation between codegen and the system linker:
* Non-leaf functions leave space on the stack at r1+24 to save the TOC pointer.
* A call to a function that *might* have to go via a PLT stub must be followed
by a nop instruction that the system linker can replace with "ld r1, 24(r1)"
to restore the TOC pointer (only when dynamically linking Go code).
* When calling a function via a function pointer, the address of the function
must be in r12, and the first couple of instructions (the "global entry
point") of the called function use this to derive the address of the TOC
for the module it is in.
* When calling a function that is implemented in the same module, the system
linker adjusts the call to skip over the instructions mentioned above (the
"local entry point"), assuming that r2 is already correctly set.
So this changeset adds the global entry point instructions, sets the metadata so
the system linker knows where the local entry point is, inserts code to save the
TOC pointer at 24(r1), adds a nop after any call not known to be local and copes
with the odd non-local code transfer in the runtime (e.g. the stuff around
jmpdefer). It does not actually compile PIC yet.
Change-Id: I7522e22bdfd2f891745a900c60254fe9e372c854
Reviewed-on: https://go-review.googlesource.com/15967
Reviewed-by: Russ Cox <rsc@golang.org>
2015-10-16 15:42:09 +13:00
|
|
|
r.Xadd += 4
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER_TOCREL:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(r.Xadd))
|
|
|
|
|
ctxt.Out.Write64(uint64(sectoff + 4))
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32)
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER_TOCREL_DS:
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(r.Xadd))
|
|
|
|
|
ctxt.Out.Write64(uint64(sectoff + 4))
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32)
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_CALLPOWER:
|
2015-09-04 08:30:15 +12:00
|
|
|
if r.Siz != 4 {
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-09-04 08:30:15 +12:00
|
|
|
}
|
2017-10-06 16:01:02 -04:00
|
|
|
ctxt.Out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32)
|
2015-09-04 08:30:15 +12:00
|
|
|
|
|
|
|
|
}
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write64(uint64(r.Xadd))
|
2015-09-04 08:30:15 +12:00
|
|
|
|
2017-08-27 22:00:00 +09:00
|
|
|
return true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2020-03-11 12:12:41 -04:00
|
|
|
func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
|
|
|
|
if plt.Size() == 0 {
|
2015-02-27 22:57:28 -05:00
|
|
|
// The dynamic linker stores the address of the
|
|
|
|
|
// dynamic resolver and the DSO identifier in the two
|
|
|
|
|
// doublewords at the beginning of the .plt section
|
2016-03-01 23:21:55 +00:00
|
|
|
// before the PLT array. Reserve space for these.
|
2020-03-11 12:12:41 -04:00
|
|
|
plt.SetSize(16)
|
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 {
|
2017-08-27 22:00:00 +09:00
|
|
|
return false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2020-03-13 17:02:31 -04:00
|
|
|
// Return the value of .TOC. for symbol s
|
|
|
|
|
func symtoc(syms *ld.ArchSyms, s *sym.Symbol) int64 {
|
|
|
|
|
v := s.Version
|
|
|
|
|
if s.Outer != nil {
|
|
|
|
|
v = s.Outer.Version
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
toc := syms.DotTOC[v]
|
|
|
|
|
if toc == nil {
|
|
|
|
|
ld.Errorf(s, "TOC-relative relocation in object without .TOC.")
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return toc.Value
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-28 13:38:02 +01:00
|
|
|
// archreloctoc relocates a TOC relative symbol.
|
2018-11-26 11:14:09 +01:00
|
|
|
// If the symbol pointed by this TOC relative symbol is in .data or .bss, the
|
|
|
|
|
// default load instruction can be changed to an addi instruction and the
|
|
|
|
|
// symbol address can be used directly.
|
2018-11-28 13:38:02 +01:00
|
|
|
// This code is for AIX only.
|
2020-02-24 21:06:21 -05:00
|
|
|
func archreloctoc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
|
2020-02-24 21:04:50 -05:00
|
|
|
if target.IsLinux() {
|
2018-11-28 13:38:02 +01:00
|
|
|
ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
|
|
|
|
|
}
|
2018-11-23 14:20:19 +01:00
|
|
|
var o1, o2 uint32
|
|
|
|
|
|
|
|
|
|
o1 = uint32(val >> 32)
|
|
|
|
|
o2 = uint32(val)
|
|
|
|
|
|
2018-11-26 11:14:09 +01:00
|
|
|
var t int64
|
|
|
|
|
useAddi := false
|
|
|
|
|
const prefix = "TOC."
|
|
|
|
|
var tarSym *sym.Symbol
|
|
|
|
|
if strings.HasPrefix(r.Sym.Name, prefix) {
|
2019-10-11 21:51:01 -04:00
|
|
|
tarSym = r.Sym.R[0].Sym
|
2018-11-26 11:14:09 +01:00
|
|
|
} else {
|
|
|
|
|
ld.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-24 21:04:50 -05:00
|
|
|
if target.IsInternal() && tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) {
|
2020-02-24 21:06:21 -05:00
|
|
|
t = ld.Symaddr(tarSym) + r.Add - syms.TOC.Value
|
2018-11-26 11:14:09 +01:00
|
|
|
// change ld to addi in the second instruction
|
|
|
|
|
o2 = (o2 & 0x03FF0000) | 0xE<<26
|
|
|
|
|
useAddi = true
|
|
|
|
|
} else {
|
2020-02-24 21:06:21 -05:00
|
|
|
t = ld.Symaddr(r.Sym) + r.Add - syms.TOC.Value
|
2018-11-26 11:14:09 +01:00
|
|
|
}
|
|
|
|
|
|
2018-11-23 14:20:19 +01:00
|
|
|
if t != int64(int32(t)) {
|
|
|
|
|
ld.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", s.Name, r.Sym, t)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t&0x8000 != 0 {
|
|
|
|
|
t += 0x10000
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
o1 |= uint32((t >> 16) & 0xFFFF)
|
|
|
|
|
|
|
|
|
|
switch r.Type {
|
|
|
|
|
case objabi.R_ADDRPOWER_TOCREL_DS:
|
2018-11-26 11:14:09 +01:00
|
|
|
if useAddi {
|
|
|
|
|
o2 |= uint32(t) & 0xFFFF
|
|
|
|
|
} else {
|
|
|
|
|
if t&3 != 0 {
|
|
|
|
|
ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
|
|
|
|
|
}
|
|
|
|
|
o2 |= uint32(t) & 0xFFFC
|
2018-11-23 14:20:19 +01:00
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return int64(o1)<<32 | int64(o2)
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-28 13:38:02 +01:00
|
|
|
// archrelocaddr relocates a symbol address.
|
|
|
|
|
// This code is for AIX only.
|
2020-02-24 21:06:21 -05:00
|
|
|
func archrelocaddr(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
|
2020-02-24 21:04:50 -05:00
|
|
|
if target.IsAIX() {
|
2018-11-23 14:20:19 +01:00
|
|
|
ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
|
|
|
|
|
}
|
2015-09-08 15:21:58 +12:00
|
|
|
var o1, o2 uint32
|
2020-02-24 21:04:50 -05:00
|
|
|
if target.IsBigEndian() {
|
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
|
|
|
o1 = uint32(val >> 32)
|
|
|
|
|
o2 = uint32(val)
|
2015-09-08 15:21:58 +12:00
|
|
|
} else {
|
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
|
|
|
o1 = uint32(val)
|
|
|
|
|
o2 = uint32(val >> 32)
|
2015-09-08 15:21:58 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We are spreading a 31-bit address across two instructions, putting the
|
|
|
|
|
// high (adjusted) part in the low 16 bits of the first instruction and the
|
|
|
|
|
// low part in the low 16 bits of the second instruction, or, in the DS case,
|
|
|
|
|
// bits 15-2 (inclusive) of the address into bits 15-2 of the second
|
|
|
|
|
// instruction (it is an error in this case if the low 2 bits of the address
|
|
|
|
|
// are non-zero).
|
|
|
|
|
|
2016-09-17 09:39:33 -04:00
|
|
|
t := ld.Symaddr(r.Sym) + r.Add
|
2015-09-08 15:21:58 +12:00
|
|
|
if t < 0 || t >= 1<<31 {
|
2018-11-23 14:20:19 +01:00
|
|
|
ld.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", s.Name, ld.Symaddr(r.Sym))
|
2015-09-08 15:21:58 +12:00
|
|
|
}
|
|
|
|
|
if t&0x8000 != 0 {
|
|
|
|
|
t += 0x10000
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch r.Type {
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER:
|
2015-09-08 15:21:58 +12:00
|
|
|
o1 |= (uint32(t) >> 16) & 0xffff
|
|
|
|
|
o2 |= uint32(t) & 0xffff
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER_DS:
|
2015-09-08 15:21:58 +12:00
|
|
|
o1 |= (uint32(t) >> 16) & 0xffff
|
|
|
|
|
if t&3 != 0 {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
|
2015-09-08 15:21:58 +12:00
|
|
|
}
|
|
|
|
|
o2 |= uint32(t) & 0xfffc
|
|
|
|
|
default:
|
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
|
|
|
return -1
|
2015-09-08 15:21:58 +12:00
|
|
|
}
|
|
|
|
|
|
2020-02-24 21:04:50 -05:00
|
|
|
if target.IsBigEndian() {
|
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
|
|
|
return int64(o1)<<32 | int64(o2)
|
2015-09-08 15:21:58 +12:00
|
|
|
}
|
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
|
|
|
return int64(o2)<<32 | int64(o1)
|
2015-09-08 15:21:58 +12:00
|
|
|
}
|
|
|
|
|
|
2016-10-11 09:26:40 -05:00
|
|
|
// resolve direct jump relocation r in s, and add trampoline if necessary
|
2020-04-06 15:58:21 -04:00
|
|
|
func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
|
2017-12-01 00:59:45 +00:00
|
|
|
|
2017-06-08 08:26:19 -04:00
|
|
|
// Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it.
|
|
|
|
|
// For internal linking, trampolines are always created for long calls.
|
|
|
|
|
// For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in
|
|
|
|
|
// r2. For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created.
|
2020-04-06 15:58:21 -04:00
|
|
|
if ctxt.IsExternal() && (ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE) {
|
2017-06-08 08:26:19 -04:00
|
|
|
// No trampolines needed since r2 contains the TOC
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-06 15:58:21 -04:00
|
|
|
relocs := ldr.Relocs(s)
|
|
|
|
|
r := relocs.At2(ri)
|
|
|
|
|
t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
|
|
|
|
|
switch r.Type() {
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_CALLPOWER:
|
2016-10-11 09:26:40 -05:00
|
|
|
|
|
|
|
|
// If branch offset is too far then create a trampoline.
|
|
|
|
|
|
2020-04-06 15:58:21 -04:00
|
|
|
if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
|
|
|
|
|
var tramp loader.Sym
|
2016-10-11 09:26:40 -05:00
|
|
|
for i := 0; ; i++ {
|
2017-12-01 00:59:45 +00:00
|
|
|
|
2016-10-11 09:26:40 -05:00
|
|
|
// Using r.Add as part of the name is significant in functions like duffzero where the call
|
|
|
|
|
// target is at some offset within the function. Calls to duff+8 and duff+256 must appear as
|
|
|
|
|
// distinct trampolines.
|
|
|
|
|
|
2020-04-06 15:58:21 -04:00
|
|
|
name := ldr.SymName(rs)
|
|
|
|
|
if r.Add() == 0 {
|
2016-10-11 09:26:40 -05:00
|
|
|
name = name + fmt.Sprintf("-tramp%d", i)
|
|
|
|
|
} else {
|
2020-04-06 15:58:21 -04:00
|
|
|
name = name + fmt.Sprintf("%+x-tramp%d", r.Add(), i)
|
2016-10-11 09:26:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Look up the trampoline in case it already exists
|
|
|
|
|
|
2020-04-06 15:58:21 -04:00
|
|
|
tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
|
|
|
|
|
if ldr.SymValue(tramp) == 0 {
|
2016-10-11 09:26:40 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-06 15:58:21 -04:00
|
|
|
t = ldr.SymValue(tramp) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
|
2016-10-11 09:26:40 -05:00
|
|
|
|
2017-06-08 08:26:19 -04:00
|
|
|
// With internal linking, the trampoline can be used if it is not too far.
|
|
|
|
|
// With external linking, the trampoline must be in this section for it to be reused.
|
2020-04-06 15:58:21 -04:00
|
|
|
if (ctxt.IsInternal() && int64(int32(t<<6)>>6) == t) || (ctxt.IsExternal() && ldr.SymSect(s) == ldr.SymSect(tramp)) {
|
2016-10-11 09:26:40 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-06 15:58:21 -04:00
|
|
|
if ldr.SymType(tramp) == 0 {
|
2017-10-05 10:20:17 -04:00
|
|
|
if ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE {
|
2017-06-08 08:26:19 -04:00
|
|
|
// Should have returned for above cases
|
2020-04-06 15:58:21 -04:00
|
|
|
ctxt.Errorf(s, "unexpected trampoline for shared or dynamic linking")
|
2017-06-08 08:26:19 -04:00
|
|
|
} else {
|
2020-04-06 15:58:21 -04:00
|
|
|
trampb := ldr.MakeSymbolUpdater(tramp)
|
|
|
|
|
ctxt.AddTramp(trampb)
|
|
|
|
|
gentramp(ctxt, ldr, trampb, rs, r.Add())
|
2017-06-08 08:26:19 -04:00
|
|
|
}
|
2016-10-11 09:26:40 -05:00
|
|
|
}
|
2020-04-06 15:58:21 -04:00
|
|
|
sb := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
relocs := sb.Relocs()
|
|
|
|
|
r := relocs.At2(ri)
|
|
|
|
|
r.SetSym(tramp)
|
|
|
|
|
r.SetAdd(0) // This was folded into the trampoline target address
|
2016-10-11 09:26:40 -05:00
|
|
|
}
|
|
|
|
|
default:
|
2020-04-06 15:58:21 -04:00
|
|
|
ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
|
2016-10-11 09:26:40 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-06 15:58:21 -04:00
|
|
|
func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
|
|
|
|
|
tramp.SetSize(16) // 4 instructions
|
|
|
|
|
P := make([]byte, tramp.Size())
|
|
|
|
|
t := ldr.SymValue(target) + offset
|
2019-02-20 16:48:43 +01:00
|
|
|
var o1, o2 uint32
|
|
|
|
|
|
2020-04-06 15:58:21 -04:00
|
|
|
if ctxt.IsAIX() {
|
2019-02-20 16:48:43 +01:00
|
|
|
// On AIX, the address is retrieved with a TOC symbol.
|
|
|
|
|
// For internal linking, the "Linux" way might still be used.
|
|
|
|
|
// However, all text symbols are accessed with a TOC symbol as
|
|
|
|
|
// text relocations aren't supposed to be possible.
|
|
|
|
|
// So, keep using the external linking way to be more AIX friendly.
|
|
|
|
|
o1 = uint32(0x3fe20000) // lis r2, toctargetaddr hi
|
|
|
|
|
o2 = uint32(0xebff0000) // ld r31, toctargetaddr lo
|
|
|
|
|
|
2020-04-06 15:58:21 -04:00
|
|
|
toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0)
|
|
|
|
|
toctramp.SetType(sym.SXCOFFTOC)
|
|
|
|
|
toctramp.SetReachable(true)
|
2020-04-15 23:11:52 -04:00
|
|
|
toctramp.AddAddrPlus(ctxt.Arch, target, offset)
|
2019-02-20 16:48:43 +01:00
|
|
|
|
2020-04-06 15:58:21 -04:00
|
|
|
r := loader.Reloc{
|
2020-04-08 11:45:00 -04:00
|
|
|
Off: 0,
|
2020-04-06 15:58:21 -04:00
|
|
|
Type: objabi.R_ADDRPOWER_TOCREL_DS,
|
|
|
|
|
Size: 8, // generates 2 relocations: HA + LO
|
2020-04-08 11:45:00 -04:00
|
|
|
Sym: toctramp.Sym(),
|
2020-04-06 15:58:21 -04:00
|
|
|
}
|
|
|
|
|
tramp.AddReloc(r)
|
2017-06-08 08:26:19 -04:00
|
|
|
} else {
|
2019-02-20 16:48:43 +01:00
|
|
|
// Used for default build mode for an executable
|
|
|
|
|
// Address of the call target is generated using
|
|
|
|
|
// relocation and doesn't depend on r2 (TOC).
|
|
|
|
|
o1 = uint32(0x3fe00000) // lis r31,targetaddr hi
|
|
|
|
|
o2 = uint32(0x3bff0000) // addi r31,targetaddr lo
|
|
|
|
|
|
|
|
|
|
// With external linking, the target address must be
|
|
|
|
|
// relocated using LO and HA
|
2020-04-06 15:58:21 -04:00
|
|
|
if ctxt.IsExternal() {
|
|
|
|
|
r := loader.Reloc{
|
2020-04-08 11:45:00 -04:00
|
|
|
Off: 0,
|
2020-04-06 15:58:21 -04:00
|
|
|
Type: objabi.R_ADDRPOWER,
|
|
|
|
|
Size: 8, // generates 2 relocations: HA + LO
|
2020-04-08 11:45:00 -04:00
|
|
|
Sym: target,
|
|
|
|
|
Add: offset,
|
2020-04-06 15:58:21 -04:00
|
|
|
}
|
|
|
|
|
tramp.AddReloc(r)
|
2019-02-20 16:48:43 +01:00
|
|
|
} else {
|
|
|
|
|
// adjustment needed if lo has sign bit set
|
|
|
|
|
// when using addi to compute address
|
|
|
|
|
val := uint32((t & 0xffff0000) >> 16)
|
|
|
|
|
if t&0x8000 != 0 {
|
|
|
|
|
val += 1
|
|
|
|
|
}
|
|
|
|
|
o1 |= val // hi part of addr
|
|
|
|
|
o2 |= uint32(t & 0xffff) // lo part of addr
|
2017-06-08 08:26:19 -04:00
|
|
|
}
|
|
|
|
|
}
|
2019-02-20 16:48:43 +01:00
|
|
|
|
2017-06-08 08:26:19 -04:00
|
|
|
o3 := uint32(0x7fe903a6) // mtctr r31
|
|
|
|
|
o4 := uint32(0x4e800420) // bctr
|
2020-04-06 15:58:21 -04:00
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P, o1)
|
|
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
|
|
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
|
|
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P[12:], o4)
|
|
|
|
|
tramp.SetData(P)
|
2017-06-08 08:26:19 -04:00
|
|
|
}
|
|
|
|
|
|
2020-02-24 21:06:21 -05:00
|
|
|
func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
|
|
|
|
|
if target.IsExternal() {
|
2019-02-20 16:16:38 +01:00
|
|
|
// On AIX, relocations (except TLS ones) must be also done to the
|
|
|
|
|
// value with the current addresses.
|
2015-09-04 08:30:15 +12:00
|
|
|
switch r.Type {
|
|
|
|
|
default:
|
2020-02-24 21:06:21 -05:00
|
|
|
if target.IsAIX() {
|
2019-02-20 16:16:38 +01:00
|
|
|
return val, false
|
|
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
|
2017-08-27 22:00:00 +09:00
|
|
|
r.Done = false
|
2015-09-04 08:30:15 +12:00
|
|
|
// check Outer is nil, Type is TLSBSS?
|
|
|
|
|
r.Xadd = r.Add
|
|
|
|
|
r.Xsym = r.Sym
|
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
|
|
|
return val, true
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER,
|
|
|
|
|
objabi.R_ADDRPOWER_DS,
|
|
|
|
|
objabi.R_ADDRPOWER_TOCREL,
|
|
|
|
|
objabi.R_ADDRPOWER_TOCREL_DS,
|
|
|
|
|
objabi.R_ADDRPOWER_GOT,
|
|
|
|
|
objabi.R_ADDRPOWER_PCREL:
|
2017-08-27 22:00:00 +09:00
|
|
|
r.Done = false
|
2015-09-04 08:30:15 +12:00
|
|
|
|
|
|
|
|
// set up addend for eventual relocation via outer symbol.
|
|
|
|
|
rs := r.Sym
|
|
|
|
|
r.Xadd = r.Add
|
|
|
|
|
for rs.Outer != nil {
|
2016-09-17 09:39:33 -04:00
|
|
|
r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
|
2015-09-04 08:30:15 +12:00
|
|
|
rs = rs.Outer
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-29 16:59:56 -07:00
|
|
|
if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "missing section for %s", rs.Name)
|
2015-09-04 08:30:15 +12:00
|
|
|
}
|
|
|
|
|
r.Xsym = rs
|
|
|
|
|
|
2020-02-24 21:06:21 -05:00
|
|
|
if !target.IsAIX() {
|
2019-02-20 16:16:38 +01:00
|
|
|
return val, true
|
|
|
|
|
}
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_CALLPOWER:
|
2017-08-27 22:00:00 +09:00
|
|
|
r.Done = false
|
2015-09-04 08:30:15 +12:00
|
|
|
r.Xsym = r.Sym
|
|
|
|
|
r.Xadd = r.Add
|
2020-02-24 21:06:21 -05:00
|
|
|
if !target.IsAIX() {
|
2019-02-20 16:16:38 +01:00
|
|
|
return val, true
|
|
|
|
|
}
|
2015-09-04 08:30:15 +12:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch r.Type {
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_CONST:
|
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
|
|
|
return r.Add, true
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_GOTOFF:
|
2020-02-24 21:06:21 -05:00
|
|
|
return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
|
2018-11-23 14:20:19 +01:00
|
|
|
case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
|
2020-02-24 21:06:21 -05:00
|
|
|
return archreloctoc(target, syms, r, s, val), true
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
|
2020-02-24 21:06:21 -05:00
|
|
|
return archrelocaddr(target, syms, r, s, val), true
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_CALLPOWER:
|
2015-03-01 13:32:49 -05:00
|
|
|
// Bits 6 through 29 = (S + A - P) >> 2
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2016-09-17 09:39:33 -04:00
|
|
|
t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
|
2016-10-11 09:26:40 -05:00
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
if t&3 != 0 {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-10-11 09:26:40 -05:00
|
|
|
// If branch offset is too far then create a trampoline.
|
|
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
if int64(int32(t<<6)>>6) != t {
|
2016-10-11 09:26:40 -05:00
|
|
|
ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
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
|
|
|
return val | int64(uint32(t)&^0xfc000003), true
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_POWER_TOC: // S + A - .TOC.
|
2020-03-13 17:02:31 -04:00
|
|
|
return ld.Symaddr(r.Sym) + r.Add - symtoc(syms, s), true
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.R_POWER_TLS_LE:
|
2018-02-19 02:20:57 +09:00
|
|
|
// The thread pointer points 0x7000 bytes after the start of the
|
2015-10-30 10:13:13 +13:00
|
|
|
// thread local storage area as documented in section "3.7.2 TLS
|
|
|
|
|
// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
|
|
|
|
|
// Specification".
|
|
|
|
|
v := r.Sym.Value - 0x7000
|
2020-02-24 21:06:21 -05:00
|
|
|
if target.IsAIX() {
|
2018-09-28 17:02:16 +02:00
|
|
|
// On AIX, the thread pointer points 0x7800 bytes after
|
|
|
|
|
// the TLS.
|
|
|
|
|
v -= 0x800
|
|
|
|
|
}
|
2015-10-30 10:13:13 +13:00
|
|
|
if int64(int16(v)) != v {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "TLS offset out of range %d", v)
|
2015-10-30 10:13:13 +13:00
|
|
|
}
|
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
|
|
|
return (val &^ 0xffff) | (v & 0xffff), true
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
return val, false
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2020-02-24 21:06:21 -05:00
|
|
|
func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
|
2017-10-04 17:54:04 -04:00
|
|
|
switch r.Variant & sym.RV_TYPE_MASK {
|
2015-02-27 22:57:28 -05:00
|
|
|
default:
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
|
2015-02-27 22:57:28 -05:00
|
|
|
fallthrough
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
case sym.RV_NONE:
|
2015-02-27 22:57:28 -05:00
|
|
|
return t
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
case sym.RV_POWER_LO:
|
|
|
|
|
if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
|
2015-02-27 22:57:28 -05:00
|
|
|
// Whether to check for signed or unsigned
|
|
|
|
|
// overflow depends on the instruction
|
2015-03-02 12:35:15 -05:00
|
|
|
var o1 uint32
|
2020-02-24 21:06:21 -05:00
|
|
|
if target.IsBigEndian() {
|
2018-09-10 15:07:09 -04:00
|
|
|
o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2018-09-10 15:07:09 -04:00
|
|
|
o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
switch o1 >> 26 {
|
|
|
|
|
case 24, // ori
|
|
|
|
|
26, // xori
|
|
|
|
|
28: // andi
|
|
|
|
|
if t>>16 != 0 {
|
|
|
|
|
goto overflow
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if int64(int16(t)) != t {
|
|
|
|
|
goto overflow
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return int64(int16(t))
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
case sym.RV_POWER_HA:
|
2015-02-27 22:57:28 -05:00
|
|
|
t += 0x8000
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
// Fallthrough
|
2017-10-04 17:54:04 -04:00
|
|
|
case sym.RV_POWER_HI:
|
2015-02-27 22:57:28 -05:00
|
|
|
t >>= 16
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
|
2015-02-27 22:57:28 -05:00
|
|
|
// Whether to check for signed or unsigned
|
|
|
|
|
// overflow depends on the instruction
|
2015-03-02 12:35:15 -05:00
|
|
|
var o1 uint32
|
2020-02-24 21:06:21 -05:00
|
|
|
if target.IsBigEndian() {
|
2018-09-10 15:07:09 -04:00
|
|
|
o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2018-09-10 15:07:09 -04:00
|
|
|
o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
switch o1 >> 26 {
|
|
|
|
|
case 25, // oris
|
|
|
|
|
27, // xoris
|
|
|
|
|
29: // andis
|
|
|
|
|
if t>>16 != 0 {
|
|
|
|
|
goto overflow
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if int64(int16(t)) != t {
|
|
|
|
|
goto overflow
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return int64(int16(t))
|
|
|
|
|
|
2017-10-04 17:54:04 -04:00
|
|
|
case sym.RV_POWER_DS:
|
2015-03-02 12:35:15 -05:00
|
|
|
var o1 uint32
|
2020-02-24 21:06:21 -05:00
|
|
|
if target.IsBigEndian() {
|
2018-09-10 15:07:09 -04:00
|
|
|
o1 = uint32(binary.BigEndian.Uint16(s.P[r.Off:]))
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2018-09-10 15:07:09 -04:00
|
|
|
o1 = uint32(binary.LittleEndian.Uint16(s.P[r.Off:]))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
if t&3 != 0 {
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-10-04 17:54:04 -04:00
|
|
|
if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
|
2015-02-27 22:57:28 -05:00
|
|
|
goto overflow
|
|
|
|
|
}
|
|
|
|
|
return int64(o1)&0x3 | int64(int16(t))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
overflow:
|
2016-09-17 09:39:33 -04:00
|
|
|
ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
|
2015-02-27 22:57:28 -05:00
|
|
|
return t
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-02 08:27:09 -04:00
|
|
|
func addpltsym2(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) {
|
|
|
|
|
if ldr.SymPlt(s) >= 0 {
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-21 18:37:43 -04:00
|
|
|
ld.Adddynsym2(ldr, &ctxt.Target, &ctxt.ArchSyms, s)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-10-07 13:43:38 -04:00
|
|
|
if ctxt.IsELF {
|
2020-04-02 08:27:09 -04:00
|
|
|
plt := ldr.MakeSymbolUpdater(ctxt.PLT2)
|
|
|
|
|
rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT2)
|
|
|
|
|
if plt.Size() == 0 {
|
2020-03-11 12:12:41 -04:00
|
|
|
panic("plt is not set up")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create the glink resolver if necessary
|
2020-04-02 08:27:09 -04:00
|
|
|
glink := ensureglinkresolver2(ctxt, ldr)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Write symbol resolver stub (just a branch to the
|
|
|
|
|
// glink resolver stub)
|
2020-04-02 08:27:09 -04:00
|
|
|
rel := loader.Reloc{
|
|
|
|
|
Off: int32(glink.Size()),
|
|
|
|
|
Size: 4,
|
|
|
|
|
Type: objabi.R_CALLPOWER,
|
|
|
|
|
Sym: glink.Sym(),
|
|
|
|
|
}
|
|
|
|
|
glink.AddReloc(rel)
|
2017-09-30 15:06:44 +00:00
|
|
|
glink.AddUint32(ctxt.Arch, 0x48000000) // b .glink
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// In the ppc64 ABI, the dynamic linker is responsible
|
|
|
|
|
// for writing the entire PLT. We just need to
|
|
|
|
|
// reserve 8 bytes for each PLT entry and generate a
|
|
|
|
|
// JMP_SLOT dynamic relocation for it.
|
|
|
|
|
//
|
|
|
|
|
// TODO(austin): ABI v1 is different
|
2020-04-02 08:27:09 -04:00
|
|
|
ldr.SetPlt(s, int32(plt.Size()))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2020-04-02 08:27:09 -04:00
|
|
|
plt.Grow(plt.Size() + 8)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2020-04-02 08:27:09 -04:00
|
|
|
rela.AddAddrPlus(ctxt.Arch, plt.Sym(), int64(ldr.SymPlt(s)))
|
|
|
|
|
rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_PPC64_JMP_SLOT)))
|
2017-09-30 15:06:44 +00:00
|
|
|
rela.AddUint64(ctxt.Arch, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2020-04-02 08:27:09 -04:00
|
|
|
ctxt.Errorf(s, "addpltsym: unsupported binary format")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate the glink resolver stub if necessary and return the .glink section
|
2020-04-02 08:27:09 -04:00
|
|
|
func ensureglinkresolver2(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder {
|
|
|
|
|
gs := ldr.LookupOrCreateSym(".glink", 0)
|
|
|
|
|
glink := ldr.MakeSymbolUpdater(gs)
|
|
|
|
|
if glink.Size() != 0 {
|
2015-02-27 22:57:28 -05:00
|
|
|
return glink
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is essentially the resolver from the ppc64 ELF ABI.
|
|
|
|
|
// At entry, r12 holds the address of the symbol resolver stub
|
|
|
|
|
// for the target routine and the argument registers hold the
|
|
|
|
|
// arguments for the target routine.
|
|
|
|
|
//
|
|
|
|
|
// This stub is PIC, so first get the PC of label 1 into r11.
|
|
|
|
|
// Other things will be relative to this.
|
2017-09-30 15:06:44 +00:00
|
|
|
glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0
|
|
|
|
|
glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f
|
|
|
|
|
glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11
|
|
|
|
|
glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlf r0
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Compute the .plt array index from the entry point address.
|
|
|
|
|
// Because this is PIC, everything is relative to label 1b (in
|
|
|
|
|
// r11):
|
|
|
|
|
// r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4
|
2017-09-30 15:06:44 +00:00
|
|
|
glink.AddUint32(ctxt.Arch, 0x3800ffd0) // li r0,-(res_0-1b)=-48
|
|
|
|
|
glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12
|
|
|
|
|
glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11
|
|
|
|
|
glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// r11 = address of the first byte of the PLT
|
2020-04-02 08:27:09 -04:00
|
|
|
glink.AddSymRef(ctxt.Arch, ctxt.PLT2, 0, objabi.R_ADDRPOWER, 8)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-09-30 15:06:44 +00:00
|
|
|
glink.AddUint32(ctxt.Arch, 0x3d600000) // addis r11,0,.plt@ha
|
|
|
|
|
glink.AddUint32(ctxt.Arch, 0x396b0000) // addi r11,r11,.plt@l
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Load r12 = dynamic resolver address and r11 = DSO
|
|
|
|
|
// identifier from the first two doublewords of the PLT.
|
2017-09-30 15:06:44 +00:00
|
|
|
glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,0(r11)
|
|
|
|
|
glink.AddUint32(ctxt.Arch, 0xe96b0008) // ld r11,8(r11)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// Jump to the dynamic resolver
|
2017-09-30 15:06:44 +00:00
|
|
|
glink.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12
|
|
|
|
|
glink.AddUint32(ctxt.Arch, 0x4e800420) // bctr
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// The symbol resolvers must immediately follow.
|
|
|
|
|
// res_0:
|
|
|
|
|
|
|
|
|
|
// Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes
|
|
|
|
|
// before the first symbol resolver stub.
|
2020-04-02 08:27:09 -04:00
|
|
|
du := ldr.MakeSymbolUpdater(ctxt.Dynamic2)
|
|
|
|
|
ld.Elfwritedynentsymplus2(ctxt, du, ld.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
return glink
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 09:53:29 -04:00
|
|
|
func asmb(ctxt *ld.Link, _ *loader.Loader) {
|
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
|
|
|
}
|
|
|
|
|
|
2020-03-20 12:24:35 -04:00
|
|
|
var wg sync.WaitGroup
|
2017-04-18 21:52:06 +12:00
|
|
|
for _, sect := range ld.Segtext.Sections {
|
2020-03-20 12:24:35 -04:00
|
|
|
offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
|
2016-08-25 11:07:33 -05:00
|
|
|
// Handle additional text sections with Codeblk
|
|
|
|
|
if sect.Name == ".text" {
|
2020-03-20 12:24:35 -04:00
|
|
|
ld.WriteParallel(&wg, ld.Codeblk, ctxt, offset, sect.Vaddr, sect.Length)
|
2016-08-25 11:07:33 -05:00
|
|
|
} else {
|
2020-03-20 12:24:35 -04:00
|
|
|
ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
|
2016-08-25 11:07:33 -05:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2020-03-20 12:24:35 -04:00
|
|
|
for _, sect := range ld.Segtext.Sections[1:] {
|
|
|
|
|
offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
|
|
|
|
|
ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
if ld.Segrodata.Filelen > 0 {
|
2020-03-20 12:24:35 -04:00
|
|
|
ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2020-03-20 12:24:35 -04:00
|
|
|
|
2016-09-05 23:29:16 -04:00
|
|
|
if ld.Segrelrodata.Filelen > 0 {
|
2020-03-20 12:24:35 -04:00
|
|
|
ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
|
2016-09-05 23:29:16 -04:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2020-03-20 12:24:35 -04:00
|
|
|
ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2020-03-20 12:24:35 -04:00
|
|
|
ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
|
|
|
|
|
wg.Wait()
|
2019-04-03 22:41:48 -04:00
|
|
|
}
|
2016-03-14 09:23:04 -07:00
|
|
|
|
2019-04-03 22:41:48 -04:00
|
|
|
func asmb2(ctxt *ld.Link) {
|
2015-02-27 22:57:28 -05:00
|
|
|
/* output symbol table */
|
|
|
|
|
ld.Symsize = 0
|
|
|
|
|
|
|
|
|
|
ld.Lcsize = 0
|
2015-03-02 12:35:15 -05:00
|
|
|
symo := uint32(0)
|
2016-08-21 18:34:24 -04:00
|
|
|
if !*ld.FlagS {
|
2015-02-27 22:57:28 -05:00
|
|
|
// TODO: rationalize
|
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 {
|
2016-03-14 09:23:04 -07:00
|
|
|
symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
|
2016-08-21 18:34:24 -04:00
|
|
|
symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hplan9:
|
2015-02-27 22:57:28 -05:00
|
|
|
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
|
2018-09-28 17:02:16 +02:00
|
|
|
|
|
|
|
|
case objabi.Haix:
|
2018-11-23 11:17:36 +01:00
|
|
|
// Nothing to do
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.SeekSet(int64(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 {
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Asmelfsym(ctxt)
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write(ld.Elfstrdat)
|
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)
|
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)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2018-09-28 17:02:16 +02:00
|
|
|
|
|
|
|
|
case objabi.Haix:
|
2018-11-23 11:17:36 +01:00
|
|
|
// symtab must be added once sections have been created in ld.Asmbxcoff
|
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: /* plan 9 */
|
2017-10-01 02:37:20 +00:00
|
|
|
ctxt.Out.Write32(0x647) /* magic */
|
|
|
|
|
ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
|
|
|
|
|
ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
|
|
|
|
|
ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
|
|
|
|
|
ctxt.Out.Write32(uint32(ld.Symsize)) /* nsyms */
|
|
|
|
|
ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
|
|
|
|
|
ctxt.Out.Write32(0)
|
|
|
|
|
ctxt.Out.Write32(uint32(ld.Lcsize))
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
case objabi.Hlinux,
|
|
|
|
|
objabi.Hfreebsd,
|
|
|
|
|
objabi.Hnetbsd,
|
2019-10-09 16:22:47 +00:00
|
|
|
objabi.Hopenbsd:
|
2016-08-19 22:40:38 -04:00
|
|
|
ld.Asmbelf(ctxt, int64(symo))
|
2018-09-28 17:02:16 +02:00
|
|
|
|
|
|
|
|
case objabi.Haix:
|
2018-11-23 11:17:36 +01:00
|
|
|
fileoff := uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
|
|
|
|
|
fileoff = uint32(ld.Rnd(int64(fileoff), int64(*ld.FlagRound)))
|
|
|
|
|
ld.Asmbxcoff(ctxt, int64(fileoff))
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-21 18:34:24 -04:00
|
|
|
if *ld.FlagC {
|
2015-02-27 22:57:28 -05:00
|
|
|
fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
|
|
|
|
|
fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
|
|
|
|
|
fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
|
|
|
|
|
fmt.Printf("symsize=%d\n", ld.Symsize)
|
|
|
|
|
fmt.Printf("lcsize=%d\n", ld.Lcsize)
|
|
|
|
|
fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
|
|
|
|
|
}
|
|
|
|
|
}
|