2021-08-15 16:25:46 +08:00
|
|
|
// Copyright 2022 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package loong64
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"cmd/internal/objabi"
|
|
|
|
|
"cmd/internal/sys"
|
|
|
|
|
"cmd/link/internal/ld"
|
|
|
|
|
"cmd/link/internal/loader"
|
|
|
|
|
"cmd/link/internal/sym"
|
|
|
|
|
"debug/elf"
|
2023-11-01 17:25:20 +08:00
|
|
|
"fmt"
|
2021-08-15 16:25:46 +08:00
|
|
|
"log"
|
|
|
|
|
)
|
|
|
|
|
|
2022-12-13 16:30:45 +08:00
|
|
|
func gentext(ctxt *ld.Link, ldr *loader.Loader) {
|
|
|
|
|
initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
|
|
|
|
|
if initfunc == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
o := func(op uint32) {
|
|
|
|
|
initfunc.AddUint32(ctxt.Arch, op)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Emit the following function:
|
|
|
|
|
//
|
|
|
|
|
// local.dso_init:
|
|
|
|
|
// la.pcrel $a0, local.moduledata
|
|
|
|
|
// b runtime.addmoduledata
|
|
|
|
|
|
|
|
|
|
// 0000000000000000 <local.dso_init>:
|
|
|
|
|
// 0: 1a000004 pcalau12i $a0, 0
|
|
|
|
|
// 0: R_LARCH_PCALA_HI20 local.moduledata
|
|
|
|
|
o(0x1a000004)
|
2023-10-11 18:00:04 +08:00
|
|
|
rel, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_HI)
|
2022-12-13 16:30:45 +08:00
|
|
|
rel.SetOff(0)
|
|
|
|
|
rel.SetSiz(4)
|
|
|
|
|
rel.SetSym(ctxt.Moduledata)
|
|
|
|
|
|
|
|
|
|
// 4: 02c00084 addi.d $a0, $a0, 0
|
|
|
|
|
// 4: R_LARCH_PCALA_LO12 local.moduledata
|
|
|
|
|
o(0x02c00084)
|
2023-10-11 18:00:04 +08:00
|
|
|
rel2, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_LO)
|
2022-12-13 16:30:45 +08:00
|
|
|
rel2.SetOff(4)
|
|
|
|
|
rel2.SetSiz(4)
|
|
|
|
|
rel2.SetSym(ctxt.Moduledata)
|
|
|
|
|
|
|
|
|
|
// 8: 50000000 b 0
|
|
|
|
|
// 8: R_LARCH_B26 runtime.addmoduledata
|
|
|
|
|
o(0x50000000)
|
|
|
|
|
rel3, _ := initfunc.AddRel(objabi.R_CALLLOONG64)
|
|
|
|
|
rel3.SetOff(8)
|
|
|
|
|
rel3.SetSiz(4)
|
|
|
|
|
rel3.SetSym(addmoduledata)
|
|
|
|
|
}
|
2021-08-15 16:25:46 +08:00
|
|
|
|
|
|
|
|
func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
|
|
|
|
|
log.Fatalf("adddynrel not implemented")
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
|
|
|
|
|
// loong64 ELF relocation (endian neutral)
|
|
|
|
|
// offset uint64
|
|
|
|
|
// symreloc uint64 // The high 32-bit is the symbol, the low 32-bit is the relocation type.
|
|
|
|
|
// addend int64
|
|
|
|
|
|
|
|
|
|
elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
|
|
|
|
|
switch r.Type {
|
|
|
|
|
default:
|
|
|
|
|
return false
|
|
|
|
|
case objabi.R_ADDR, objabi.R_DWARFSECREF:
|
|
|
|
|
switch r.Size {
|
|
|
|
|
case 4:
|
|
|
|
|
out.Write64(uint64(sectoff))
|
|
|
|
|
out.Write64(uint64(elf.R_LARCH_32) | uint64(elfsym)<<32)
|
|
|
|
|
out.Write64(uint64(r.Xadd))
|
|
|
|
|
case 8:
|
|
|
|
|
out.Write64(uint64(sectoff))
|
|
|
|
|
out.Write64(uint64(elf.R_LARCH_64) | uint64(elfsym)<<32)
|
|
|
|
|
out.Write64(uint64(r.Xadd))
|
|
|
|
|
default:
|
|
|
|
|
return false
|
|
|
|
|
}
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_TLS_LE_LO:
|
2021-08-15 16:25:46 +08:00
|
|
|
out.Write64(uint64(sectoff))
|
2022-12-03 21:16:49 +08:00
|
|
|
out.Write64(uint64(elf.R_LARCH_TLS_LE_LO12) | uint64(elfsym)<<32)
|
2021-08-15 16:25:46 +08:00
|
|
|
out.Write64(uint64(r.Xadd))
|
|
|
|
|
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_TLS_LE_HI:
|
2021-08-15 16:25:46 +08:00
|
|
|
out.Write64(uint64(sectoff))
|
2022-12-03 21:16:49 +08:00
|
|
|
out.Write64(uint64(elf.R_LARCH_TLS_LE_HI20) | uint64(elfsym)<<32)
|
2021-08-15 16:25:46 +08:00
|
|
|
out.Write64(uint64(r.Xadd))
|
|
|
|
|
|
|
|
|
|
case objabi.R_CALLLOONG64:
|
|
|
|
|
out.Write64(uint64(sectoff))
|
2022-12-03 21:16:49 +08:00
|
|
|
out.Write64(uint64(elf.R_LARCH_B26) | uint64(elfsym)<<32)
|
2021-08-15 16:25:46 +08:00
|
|
|
out.Write64(uint64(r.Xadd))
|
|
|
|
|
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_TLS_IE_HI:
|
2022-08-25 11:13:10 +08:00
|
|
|
out.Write64(uint64(sectoff))
|
|
|
|
|
out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_HI20) | uint64(elfsym)<<32)
|
|
|
|
|
out.Write64(uint64(0x0))
|
|
|
|
|
|
|
|
|
|
case objabi.R_LOONG64_TLS_IE_LO:
|
|
|
|
|
out.Write64(uint64(sectoff))
|
|
|
|
|
out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_LO12) | uint64(elfsym)<<32)
|
|
|
|
|
out.Write64(uint64(0x0))
|
|
|
|
|
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_ADDR_LO:
|
2021-08-15 16:25:46 +08:00
|
|
|
out.Write64(uint64(sectoff))
|
2022-12-03 21:16:49 +08:00
|
|
|
out.Write64(uint64(elf.R_LARCH_PCALA_LO12) | uint64(elfsym)<<32)
|
|
|
|
|
out.Write64(uint64(r.Xadd))
|
2021-08-15 16:25:46 +08:00
|
|
|
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_ADDR_HI:
|
2021-08-15 16:25:46 +08:00
|
|
|
out.Write64(uint64(sectoff))
|
2022-12-03 21:16:49 +08:00
|
|
|
out.Write64(uint64(elf.R_LARCH_PCALA_HI20) | uint64(elfsym)<<32)
|
|
|
|
|
out.Write64(uint64(r.Xadd))
|
2023-10-10 20:16:36 +08:00
|
|
|
|
|
|
|
|
case objabi.R_LOONG64_GOT_HI:
|
|
|
|
|
out.Write64(uint64(sectoff))
|
|
|
|
|
out.Write64(uint64(elf.R_LARCH_GOT_PC_HI20) | uint64(elfsym)<<32)
|
|
|
|
|
out.Write64(uint64(0x0))
|
|
|
|
|
|
|
|
|
|
case objabi.R_LOONG64_GOT_LO:
|
|
|
|
|
out.Write64(uint64(sectoff))
|
|
|
|
|
out.Write64(uint64(elf.R_LARCH_GOT_PC_LO12) | uint64(elfsym)<<32)
|
|
|
|
|
out.Write64(uint64(0x0))
|
2021-08-15 16:25:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-31 18:18:19 +10:00
|
|
|
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
2021-08-15 16:25:46 +08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
|
|
|
|
|
rs := r.Sym()
|
|
|
|
|
if target.IsExternal() {
|
|
|
|
|
switch r.Type() {
|
|
|
|
|
default:
|
|
|
|
|
return val, 0, false
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_ADDR_HI,
|
|
|
|
|
objabi.R_LOONG64_ADDR_LO:
|
2021-08-15 16:25:46 +08:00
|
|
|
// set up addend for eventual relocation via outer symbol.
|
|
|
|
|
rs, _ := ld.FoldSubSymbolOffset(ldr, rs)
|
|
|
|
|
rst := ldr.SymType(rs)
|
|
|
|
|
if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
|
|
|
|
|
ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
|
|
|
|
|
}
|
2022-12-03 21:16:49 +08:00
|
|
|
return val, 1, true
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_TLS_LE_HI,
|
|
|
|
|
objabi.R_LOONG64_TLS_LE_LO,
|
2021-08-15 16:25:46 +08:00
|
|
|
objabi.R_CALLLOONG64,
|
2022-08-25 11:13:10 +08:00
|
|
|
objabi.R_JMPLOONG64,
|
2023-10-11 18:00:04 +08:00
|
|
|
objabi.R_LOONG64_TLS_IE_HI,
|
2023-10-10 20:16:36 +08:00
|
|
|
objabi.R_LOONG64_TLS_IE_LO,
|
|
|
|
|
objabi.R_LOONG64_GOT_HI,
|
|
|
|
|
objabi.R_LOONG64_GOT_LO:
|
2022-12-03 21:16:49 +08:00
|
|
|
return val, 1, true
|
2021-08-15 16:25:46 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isOk = true
|
|
|
|
|
const noExtReloc = 0
|
|
|
|
|
|
|
|
|
|
switch r.Type() {
|
|
|
|
|
case objabi.R_CONST:
|
|
|
|
|
return r.Add(), noExtReloc, isOk
|
|
|
|
|
case objabi.R_GOTOFF:
|
|
|
|
|
return ldr.SymValue(r.Sym()) + r.Add() - ldr.SymValue(syms.GOT), noExtReloc, isOk
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_ADDR_HI,
|
|
|
|
|
objabi.R_LOONG64_ADDR_LO:
|
2021-08-15 16:25:46 +08:00
|
|
|
pc := ldr.SymValue(s) + int64(r.Off())
|
2022-12-03 21:16:49 +08:00
|
|
|
t := calculatePCAlignedReloc(r.Type(), ldr.SymAddr(rs)+r.Add(), pc)
|
2023-10-11 18:00:04 +08:00
|
|
|
if r.Type() == objabi.R_LOONG64_ADDR_LO {
|
2022-12-03 21:16:49 +08:00
|
|
|
return int64(val&0xffc003ff | (t << 10)), noExtReloc, isOk
|
2021-08-15 16:25:46 +08:00
|
|
|
}
|
2022-12-03 21:16:49 +08:00
|
|
|
return int64(val&0xfe00001f | (t << 5)), noExtReloc, isOk
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_TLS_LE_HI,
|
|
|
|
|
objabi.R_LOONG64_TLS_LE_LO:
|
2021-08-15 16:25:46 +08:00
|
|
|
t := ldr.SymAddr(rs) + r.Add()
|
2023-10-11 18:00:04 +08:00
|
|
|
if r.Type() == objabi.R_LOONG64_TLS_LE_LO {
|
2021-08-15 16:25:46 +08:00
|
|
|
return int64(val&0xffc003ff | ((t & 0xfff) << 10)), noExtReloc, isOk
|
|
|
|
|
}
|
|
|
|
|
return int64(val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk
|
|
|
|
|
case objabi.R_CALLLOONG64,
|
|
|
|
|
objabi.R_JMPLOONG64:
|
|
|
|
|
pc := ldr.SymValue(s) + int64(r.Off())
|
|
|
|
|
t := ldr.SymAddr(rs) + r.Add() - pc
|
|
|
|
|
return int64(val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16)), noExtReloc, isOk
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return val, 0, false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
|
|
|
|
|
switch r.Type() {
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_ADDR_HI,
|
|
|
|
|
objabi.R_LOONG64_ADDR_LO,
|
2023-10-10 20:16:36 +08:00
|
|
|
objabi.R_LOONG64_GOT_HI,
|
|
|
|
|
objabi.R_LOONG64_GOT_LO:
|
2021-08-15 16:25:46 +08:00
|
|
|
return ld.ExtrelocViaOuterSym(ldr, r, s), true
|
|
|
|
|
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_TLS_LE_HI,
|
|
|
|
|
objabi.R_LOONG64_TLS_LE_LO,
|
2021-08-15 16:25:46 +08:00
|
|
|
objabi.R_CONST,
|
|
|
|
|
objabi.R_GOTOFF,
|
|
|
|
|
objabi.R_CALLLOONG64,
|
2022-08-25 11:13:10 +08:00
|
|
|
objabi.R_JMPLOONG64,
|
2023-10-11 18:00:04 +08:00
|
|
|
objabi.R_LOONG64_TLS_IE_HI,
|
2022-08-25 11:13:10 +08:00
|
|
|
objabi.R_LOONG64_TLS_IE_LO:
|
2021-08-15 16:25:46 +08:00
|
|
|
return ld.ExtrelocSimple(ldr, r), true
|
|
|
|
|
}
|
|
|
|
|
return loader.ExtReloc{}, false
|
|
|
|
|
}
|
2022-12-03 21:16:49 +08:00
|
|
|
|
|
|
|
|
func isRequestingLowPageBits(t objabi.RelocType) bool {
|
|
|
|
|
switch t {
|
2023-10-11 18:00:04 +08:00
|
|
|
case objabi.R_LOONG64_ADDR_LO:
|
2022-12-03 21:16:49 +08:00
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calculates the value to put into the immediate slot, according to the
|
|
|
|
|
// desired relocation type, target and PC.
|
|
|
|
|
// The value to use varies based on the reloc type. Namely, the absolute low
|
|
|
|
|
// bits of the target are to be used for the low part, while the page-aligned
|
|
|
|
|
// offset is to be used for the higher part. A "page" here is not related to
|
|
|
|
|
// the system's actual page size, but rather a fixed 12-bit range (designed to
|
|
|
|
|
// cooperate with ADDI/LD/ST's 12-bit immediates).
|
|
|
|
|
func calculatePCAlignedReloc(t objabi.RelocType, tgt int64, pc int64) int64 {
|
|
|
|
|
if isRequestingLowPageBits(t) {
|
|
|
|
|
// corresponding immediate field is 12 bits wide
|
|
|
|
|
return tgt & 0xfff
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pageDelta := (tgt >> 12) - (pc >> 12)
|
|
|
|
|
if tgt&0xfff >= 0x800 {
|
|
|
|
|
// adjust for sign-extended addition of the low bits
|
|
|
|
|
pageDelta += 1
|
|
|
|
|
}
|
|
|
|
|
// corresponding immediate field is 20 bits wide
|
|
|
|
|
return pageDelta & 0xfffff
|
|
|
|
|
}
|
2023-11-01 17:25:20 +08:00
|
|
|
|
|
|
|
|
// Convert the direct jump relocation r to refer to a trampoline if the target is too far.
|
|
|
|
|
func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
|
|
|
|
|
relocs := ldr.Relocs(s)
|
|
|
|
|
r := relocs.At(ri)
|
|
|
|
|
switch r.Type() {
|
|
|
|
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26):
|
2025-03-05 17:47:41 +08:00
|
|
|
// Nothing to do.
|
|
|
|
|
// The plt symbol has not been added. If we add tramp
|
|
|
|
|
// here, plt will not work.
|
2023-11-01 17:25:20 +08:00
|
|
|
case objabi.R_CALLLOONG64:
|
|
|
|
|
var t int64
|
|
|
|
|
// ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet
|
|
|
|
|
// laid out. Conservatively use a trampoline. This should be rare, as we lay out packages
|
|
|
|
|
// in dependency order.
|
|
|
|
|
if ldr.SymValue(rs) != 0 {
|
|
|
|
|
t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
|
|
|
|
|
}
|
|
|
|
|
if t >= 1<<27 || t < -1<<27 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && (ldr.SymPkg(s) == "" || ldr.SymPkg(s) != ldr.SymPkg(rs))) {
|
|
|
|
|
// direct call too far need to insert trampoline.
|
|
|
|
|
// look up existing trampolines first. if we found one within the range
|
|
|
|
|
// of direct call, we can reuse it. otherwise create a new one.
|
|
|
|
|
var tramp loader.Sym
|
|
|
|
|
for i := 0; ; i++ {
|
|
|
|
|
oName := ldr.SymName(rs)
|
|
|
|
|
name := oName + fmt.Sprintf("%+x-tramp%d", r.Add(), i)
|
|
|
|
|
tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
|
|
|
|
|
ldr.SetAttrReachable(tramp, true)
|
|
|
|
|
if ldr.SymType(tramp) == sym.SDYNIMPORT {
|
|
|
|
|
// don't reuse trampoline defined in other module
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if oName == "runtime.deferreturn" {
|
|
|
|
|
ldr.SetIsDeferReturnTramp(tramp, true)
|
|
|
|
|
}
|
|
|
|
|
if ldr.SymValue(tramp) == 0 {
|
|
|
|
|
// either the trampoline does not exist -- we need to create one,
|
|
|
|
|
// or found one the address which is not assigned -- this will be
|
|
|
|
|
// laid down immediately after the current function. use this one.
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
|
|
|
|
|
if t >= -1<<27 && t < 1<<27 {
|
|
|
|
|
// found an existing trampoline that is not too far
|
|
|
|
|
// we can just use it.
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ldr.SymType(tramp) == 0 {
|
|
|
|
|
// trampoline does not exist, create one
|
|
|
|
|
trampb := ldr.MakeSymbolUpdater(tramp)
|
2024-11-21 20:03:18 -05:00
|
|
|
ctxt.AddTramp(trampb, ldr.SymType(s))
|
2023-11-01 17:25:20 +08:00
|
|
|
if ldr.SymType(rs) == sym.SDYNIMPORT {
|
|
|
|
|
if r.Add() != 0 {
|
|
|
|
|
ctxt.Errorf(s, "nonzero addend for DYNIMPORT call: %v+%d", ldr.SymName(rs), r.Add())
|
|
|
|
|
}
|
|
|
|
|
gentrampgot(ctxt, ldr, trampb, rs)
|
|
|
|
|
} else {
|
|
|
|
|
gentramp(ctxt, ldr, trampb, rs, r.Add())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// modify reloc to point to tramp, which will be resolved later
|
|
|
|
|
sb := ldr.MakeSymbolUpdater(s)
|
|
|
|
|
relocs := sb.Relocs()
|
|
|
|
|
r := relocs.At(ri)
|
|
|
|
|
r.SetSym(tramp)
|
|
|
|
|
r.SetAdd(0) // clear the offset embedded in the instruction
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generate a trampoline to target+offset.
|
|
|
|
|
func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
|
|
|
|
|
tramp.SetSize(12) // 3 instructions
|
|
|
|
|
P := make([]byte, tramp.Size())
|
|
|
|
|
|
|
|
|
|
o1 := uint32(0x1a00001e) // pcalau12i $r30, 0
|
|
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P, o1)
|
|
|
|
|
r1, _ := tramp.AddRel(objabi.R_LOONG64_ADDR_HI)
|
|
|
|
|
r1.SetOff(0)
|
|
|
|
|
r1.SetSiz(4)
|
|
|
|
|
r1.SetSym(target)
|
|
|
|
|
r1.SetAdd(offset)
|
|
|
|
|
|
|
|
|
|
o2 := uint32(0x02c003de) // addi.d $r30, $r30, 0
|
|
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
|
|
|
|
|
r2, _ := tramp.AddRel(objabi.R_LOONG64_ADDR_LO)
|
|
|
|
|
r2.SetOff(4)
|
|
|
|
|
r2.SetSiz(4)
|
|
|
|
|
r2.SetSym(target)
|
|
|
|
|
r2.SetAdd(offset)
|
|
|
|
|
|
|
|
|
|
o3 := uint32(0x4c0003c0) // jirl $r0, $r30, 0
|
|
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
|
|
|
|
|
|
|
|
|
|
tramp.SetData(P)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func gentrampgot(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym) {
|
|
|
|
|
tramp.SetSize(12) // 3 instructions
|
|
|
|
|
P := make([]byte, tramp.Size())
|
|
|
|
|
|
|
|
|
|
o1 := uint32(0x1a00001e) // pcalau12i $r30, 0
|
|
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P, o1)
|
|
|
|
|
r1, _ := tramp.AddRel(objabi.R_LOONG64_GOT_HI)
|
|
|
|
|
r1.SetOff(0)
|
|
|
|
|
r1.SetSiz(4)
|
|
|
|
|
r1.SetSym(target)
|
|
|
|
|
|
|
|
|
|
o2 := uint32(0x28c003de) // ld.d $r30, $r30, 0
|
|
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
|
|
|
|
|
r2, _ := tramp.AddRel(objabi.R_LOONG64_GOT_LO)
|
|
|
|
|
r2.SetOff(4)
|
|
|
|
|
r2.SetSiz(4)
|
|
|
|
|
r2.SetSym(target)
|
|
|
|
|
|
|
|
|
|
o3 := uint32(0x4c0003c0) // jirl $r0, $r30, 0
|
|
|
|
|
ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
|
|
|
|
|
|
|
|
|
|
tramp.SetData(P)
|
|
|
|
|
}
|