_ = x[R_POWER_TLS_LE-47]
_ = x[R_POWER_TLS_IE-48]
_ = x[R_POWER_TLS-49]
- _ = x[R_ADDRPOWER_DS-50]
- _ = x[R_ADDRPOWER_GOT-51]
- _ = x[R_ADDRPOWER_PCREL-52]
- _ = x[R_ADDRPOWER_TOCREL-53]
- _ = x[R_ADDRPOWER_TOCREL_DS-54]
- _ = x[R_RISCV_CALL-55]
- _ = x[R_RISCV_CALL_TRAMP-56]
- _ = x[R_RISCV_PCREL_ITYPE-57]
- _ = x[R_RISCV_PCREL_STYPE-58]
- _ = x[R_RISCV_TLS_IE_ITYPE-59]
- _ = x[R_RISCV_TLS_IE_STYPE-60]
- _ = x[R_PCRELDBL-61]
- _ = x[R_ADDRLOONG64-62]
- _ = x[R_ADDRLOONG64U-63]
- _ = x[R_ADDRLOONG64TLS-64]
- _ = x[R_ADDRLOONG64TLSU-65]
- _ = x[R_CALLLOONG64-66]
- _ = x[R_JMPLOONG64-67]
- _ = x[R_ADDRMIPSU-68]
- _ = x[R_ADDRMIPSTLS-69]
- _ = x[R_ADDRCUOFF-70]
- _ = x[R_WASMIMPORT-71]
- _ = x[R_XCOFFREF-72]
+ _ = x[R_POWER_TLS_IE_PCREL34-50]
+ _ = x[R_POWER_TLS_LE_TPREL34-51]
+ _ = x[R_ADDRPOWER_DS-52]
+ _ = x[R_ADDRPOWER_GOT-53]
+ _ = x[R_ADDRPOWER_GOT_PCREL34-54]
+ _ = x[R_ADDRPOWER_PCREL-55]
+ _ = x[R_ADDRPOWER_TOCREL-56]
+ _ = x[R_ADDRPOWER_TOCREL_DS-57]
+ _ = x[R_ADDRPOWER_D34-58]
+ _ = x[R_ADDRPOWER_PCREL34-59]
+ _ = x[R_RISCV_CALL-60]
+ _ = x[R_RISCV_CALL_TRAMP-61]
+ _ = x[R_RISCV_PCREL_ITYPE-62]
+ _ = x[R_RISCV_PCREL_STYPE-63]
+ _ = x[R_RISCV_TLS_IE_ITYPE-64]
+ _ = x[R_RISCV_TLS_IE_STYPE-65]
+ _ = x[R_PCRELDBL-66]
+ _ = x[R_ADDRLOONG64-67]
+ _ = x[R_ADDRLOONG64U-68]
+ _ = x[R_ADDRLOONG64TLS-69]
+ _ = x[R_ADDRLOONG64TLSU-70]
+ _ = x[R_CALLLOONG64-71]
+ _ = x[R_JMPLOONG64-72]
+ _ = x[R_ADDRMIPSU-73]
+ _ = x[R_ADDRMIPSTLS-74]
+ _ = x[R_ADDRCUOFF-75]
+ _ = x[R_WASMIMPORT-76]
+ _ = x[R_XCOFFREF-77]
}
-const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USEGENERICIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRLOONG64R_ADDRLOONG64UR_ADDRLOONG64TLSR_ADDRLOONG64TLSUR_CALLLOONG64R_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
+const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USEGENERICIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRLOONG64R_ADDRLOONG64UR_ADDRLOONG64TLSR_ADDRLOONG64TLSUR_CALLLOONG64R_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
-var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 233, 244, 250, 261, 271, 280, 293, 307, 321, 335, 351, 362, 375, 394, 414, 434, 454, 467, 481, 495, 509, 524, 538, 552, 563, 577, 592, 609, 627, 648, 660, 678, 697, 716, 736, 756, 766, 779, 793, 809, 826, 839, 851, 862, 875, 886, 898, 908}
+var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 233, 244, 250, 261, 271, 280, 293, 307, 321, 335, 351, 362, 375, 394, 414, 434, 454, 467, 481, 495, 509, 524, 538, 552, 563, 585, 607, 621, 636, 659, 676, 694, 715, 730, 749, 761, 779, 798, 817, 837, 857, 867, 880, 894, 910, 927, 940, 952, 963, 976, 987, 999, 1009}
func (i RelocType) String() string {
i -= 1
default:
return false
}
+ case objabi.R_ADDRPOWER_D34:
+ out.Write64(uint64(elf.R_PPC64_D34) | uint64(elfsym)<<32)
+ case objabi.R_ADDRPOWER_PCREL34:
+ out.Write64(uint64(elf.R_PPC64_PCREL34) | uint64(elfsym)<<32)
case objabi.R_POWER_TLS:
out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
case objabi.R_POWER_TLS_LE:
out.Write64(uint64(r.Xadd))
out.Write64(uint64(sectoff + 4))
out.Write64(uint64(elf.R_PPC64_TPREL16_LO) | uint64(elfsym)<<32)
+ case objabi.R_POWER_TLS_LE_TPREL34:
+ out.Write64(uint64(elf.R_PPC64_TPREL34) | uint64(elfsym)<<32)
+ case objabi.R_POWER_TLS_IE_PCREL34:
+ out.Write64(uint64(elf.R_PPC64_GOT_TPREL_PCREL34) | uint64(elfsym)<<32)
case objabi.R_POWER_TLS_IE:
out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
out.Write64(uint64(r.Xadd))
if target.IsAIX() {
ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
}
- var o1, o2 uint32
- if target.IsBigEndian() {
- o1 = uint32(val >> 32)
- o2 = uint32(val)
- } else {
- o1 = uint32(val)
- o2 = uint32(val >> 32)
- }
-
- // 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).
+ o1, o2 := unpackInstPair(target, val)
+ // Verify resulting address fits within a 31 bit (2GB) address space.
+ // This is a restriction arising from the usage of lis (HA) + d-form
+ // (LO) instruction sequences used to implement absolute relocations
+ // on PPC64 prior to ISA 3.1 (P10). For consistency, maintain this
+ // restriction for ISA 3.1 unless it becomes problematic.
t := ldr.SymAddr(rs) + r.Add()
if t < 0 || t >= 1<<31 {
ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs))
}
- if t&0x8000 != 0 {
- t += 0x10000
- }
switch r.Type() {
+ case objabi.R_ADDRPOWER_PCREL34:
+ // S + A - P
+ t -= (ldr.SymValue(s) + int64(r.Off()))
+ o1 |= computePrefix34HI(t)
+ o2 |= computeLO(int32(t))
+ case objabi.R_ADDRPOWER_D34:
+ o1 |= computePrefix34HI(t)
+ o2 |= computeLO(int32(t))
case objabi.R_ADDRPOWER:
- o1 |= (uint32(t) >> 16) & 0xffff
- o2 |= uint32(t) & 0xffff
+ o1 |= computeHA(int32(t))
+ o2 |= computeLO(int32(t))
case objabi.R_ADDRPOWER_DS:
- o1 |= (uint32(t) >> 16) & 0xffff
+ o1 |= computeHA(int32(t))
+ o2 |= computeLO(int32(t))
if t&3 != 0 {
ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
}
- o2 |= uint32(t) & 0xfffc
default:
return -1
}
- if target.IsBigEndian() {
- return int64(o1)<<32 | int64(o2)
- }
- return int64(o2)<<32 | int64(o1)
+ return packInstPair(target, o1, o2)
}
// Determine if the code was compiled so that the TOC register R2 is initialized and maintained
tramp.SetData(P)
}
+// Unpack a pair of 32 bit instruction words from
+// a 64 bit relocation into instN and instN+1 in endian order.
+func unpackInstPair(target *ld.Target, r int64) (uint32, uint32) {
+ if target.IsBigEndian() {
+ return uint32(r >> 32), uint32(r)
+ }
+ return uint32(r), uint32(r >> 32)
+}
+
+// Pack a pair of 32 bit instruction words o1, o2 into 64 bit relocation
+// in endian order.
+func packInstPair(target *ld.Target, o1, o2 uint32) int64 {
+ if target.IsBigEndian() {
+ return (int64(o1) << 32) | int64(o2)
+ }
+ return int64(o1) | (int64(o2) << 32)
+}
+
+// Compute the high-adjusted value (always a signed 32b value) per the ELF ABI.
+// The returned value is always 0 <= x <= 0xFFFF.
+func computeHA(val int32) uint32 {
+ return uint32(uint16((val + 0x8000) >> 16))
+}
+
+// Compute the low value (the lower 16 bits of any 32b value) per the ELF ABI.
+// The returned value is always 0 <= x <= 0xFFFF.
+func computeLO(val int32) uint32 {
+ return uint32(uint16(val))
+}
+
+// Compute the high 18 bits of a signed 34b constant. Used to pack the high 18 bits
+// of a prefix34 relocation field. This assumes the input is already restricted to
+// 34 bits.
+func computePrefix34HI(val int64) uint32 {
+ return uint32((val >> 16) & 0x3FFFF)
+}
+
+func computeTLSLEReloc(target *ld.Target, ldr *loader.Loader, rs, s loader.Sym) int64 {
+ // The thread pointer points 0x7000 bytes after the start of the
+ // thread local storage area as documented in section "3.7.2 TLS
+ // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
+ // Specification".
+ v := ldr.SymValue(rs) - 0x7000
+ if target.IsAIX() {
+ // On AIX, the thread pointer points 0x7800 bytes after
+ // the TLS.
+ v -= 0x800
+ }
+
+ if int64(int32(v)) != v {
+ ldr.Errorf(s, "TLS offset out of range %d", v)
+ }
+ return v
+}
+
func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (relocatedOffset int64, nExtReloc int, ok bool) {
rs := r.Sym()
if target.IsExternal() {
if !target.IsAIX() {
return val, nExtReloc, false
}
- case objabi.R_POWER_TLS:
+ case objabi.R_POWER_TLS, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34:
nExtReloc = 1
return val, nExtReloc, true
case objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
if !target.IsAIX() {
return val, nExtReloc, true
}
- case objabi.R_CALLPOWER:
+ case objabi.R_CALLPOWER, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
nExtReloc = 1
if !target.IsAIX() {
return val, nExtReloc, true
switch r.Type() {
case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true
- case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
+ case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true
case objabi.R_CALLPOWER:
// Bits 6 through 29 = (S + A - P) >> 2
case objabi.R_ADDRPOWER_PCREL: // S + A - P
t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
- ha := uint16(((t + 0x8000) >> 16) & 0xFFFF)
- l := uint16(t)
- if target.IsBigEndian() {
- val |= int64(l)
- val |= int64(ha) << 32
- } else {
- val |= int64(ha)
- val |= int64(l) << 32
- }
- return val, nExtReloc, true
+ ha, l := unpackInstPair(target, val)
+ l |= computeLO(int32(t))
+ ha |= computeHA(int32(t))
+ return packInstPair(target, ha, l), nExtReloc, true
case objabi.R_POWER_TLS:
const OP_ADD = 31<<26 | 266<<1
const OP_ADDI = 14 << 26
const OP_MASK = 0x3F << 26
const OP_RA_MASK = 0x1F << 16
- uval := uint64(val)
// convert r2 to r0, and ld to addi
- if target.IsBigEndian() {
- uval = uval &^ (OP_RA_MASK << 32)
- uval = (uval &^ OP_MASK) | OP_ADDI
- } else {
- uval = uval &^ (OP_RA_MASK)
- uval = (uval &^ (OP_MASK << 32)) | (OP_ADDI << 32)
- }
- val = int64(uval)
- // Treat this like an R_POWER_TLS_LE relocation now.
+ mask := packInstPair(target, OP_RA_MASK, OP_MASK)
+ addi_op := packInstPair(target, 0, OP_ADDI)
+ val &^= mask
+ val |= addi_op
fallthrough
case objabi.R_POWER_TLS_LE:
- // The thread pointer points 0x7000 bytes after the start of the
- // thread local storage area as documented in section "3.7.2 TLS
- // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
- // Specification".
- v := ldr.SymValue(rs) - 0x7000
- if target.IsAIX() {
- // On AIX, the thread pointer points 0x7800 bytes after
- // the TLS.
- v -= 0x800
- }
+ v := computeTLSLEReloc(target, ldr, rs, s)
+ o1, o2 := unpackInstPair(target, val)
+ o1 |= computeHA(int32(v))
+ o2 |= computeLO(int32(v))
+ return packInstPair(target, o1, o2), nExtReloc, true
- var o1, o2 uint32
- if int64(int32(v)) != v {
- ldr.Errorf(s, "TLS offset out of range %d", v)
- }
- if target.IsBigEndian() {
- o1 = uint32(val >> 32)
- o2 = uint32(val)
- } else {
- o1 = uint32(val)
- o2 = uint32(val >> 32)
+ case objabi.R_POWER_TLS_IE_PCREL34:
+ // Convert TLS_IE relocation to TLS_LE if supported.
+ if !(target.IsPIE() && target.IsElf()) {
+ log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
}
- o1 |= uint32(((v + 0x8000) >> 16) & 0xFFFF)
- o2 |= uint32(v & 0xFFFF)
+ // We are an ELF binary, we can safely convert to TLS_LE_TPREL34 from:
+ // pld rX, x@got@tprel@pcrel
+ //
+ // to TLS_LE_TPREL32 by converting to:
+ // pla rX, x@tprel
+
+ const OP_MASK_PFX = 0xFFFFFFFF // Discard prefix word
+ const OP_MASK = (0x3F << 26) | 0xFFFF // Preserve RT, RA
+ const OP_PFX = 1<<26 | 2<<24
+ const OP_PLA = 14 << 26
+ mask := packInstPair(target, OP_MASK_PFX, OP_MASK)
+ pla_op := packInstPair(target, OP_PFX, OP_PLA)
+ val &^= mask
+ val |= pla_op
+ fallthrough
- if target.IsBigEndian() {
- return int64(o1)<<32 | int64(o2), nExtReloc, true
- }
- return int64(o2)<<32 | int64(o1), nExtReloc, true
+ case objabi.R_POWER_TLS_LE_TPREL34:
+ v := computeTLSLEReloc(target, ldr, rs, s)
+ o1, o2 := unpackInstPair(target, val)
+ o1 |= computePrefix34HI(v)
+ o2 |= computeLO(int32(v))
+ return packInstPair(target, o1, o2), nExtReloc, true
}
return val, nExtReloc, false
func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
switch r.Type() {
- case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE, objabi.R_CALLPOWER:
+ case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34, objabi.R_CALLPOWER:
return ld.ExtrelocSimple(ldr, r), true
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:
+ objabi.R_ADDRPOWER_PCREL,
+ objabi.R_ADDRPOWER_D34,
+ objabi.R_ADDRPOWER_PCREL34:
return ld.ExtrelocViaOuterSym(ldr, r, s), true
}
return loader.ExtReloc{}, false