+2019-07-19 Alan Modra <amodra@gmail.com>
+
+ * reloc.c (BFD_RELOC_PPC64_TPREL34, BFD_RELOC_PPC64_DTPREL34),
+ (BFD_RELOC_PPC64_GOT_TLSGD34, BFD_RELOC_PPC64_GOT_TLSLD34),
+ (BFD_RELOC_PPC64_GOT_TPREL34, BFD_RELOC_PPC64_GOT_DTPREL34),
+ (BFD_RELOC_PPC64_TLS_PCREL): New pcrel tls relocs.
+ * elf64-ppc.c (ppc64_elf_howto_raw): Add howtos for pcrel tls relocs.
+ (ppc64_elf_reloc_type_lookup): Translate pcrel tls relocs.
+ (must_be_dyn_reloc, dec_dynrel_count): Add R_PPC64_TPREL64.
+ (ppc64_elf_check_relocs): Support pcrel tls relocs.
+ (ppc64_elf_tls_optimize, ppc64_elf_relocate_section): Likewise.
+ * bfd-in2.h: Regenerate.
+ * libbfd.h: Regenerate.
+
2019-07-18 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_relocate_section): Don't bother selecting
BFD_RELOC_PPC64_DTPREL16_HIGHERA,
BFD_RELOC_PPC64_DTPREL16_HIGHEST,
BFD_RELOC_PPC64_DTPREL16_HIGHESTA,
+ BFD_RELOC_PPC64_TPREL34,
+ BFD_RELOC_PPC64_DTPREL34,
+ BFD_RELOC_PPC64_GOT_TLSGD34,
+ BFD_RELOC_PPC64_GOT_TLSLD34,
+ BFD_RELOC_PPC64_GOT_TPREL34,
+ BFD_RELOC_PPC64_GOT_DTPREL34,
+ BFD_RELOC_PPC64_TLS_PCREL,
/* IBM 370/390 relocations */
BFD_RELOC_I370_D12,
HOW (R_PPC64_PLT_PCREL34_NOTOC, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
ppc64_elf_unhandled_reloc),
+ HOW (R_PPC64_TPREL34, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, signed,
+ ppc64_elf_unhandled_reloc),
+
+ HOW (R_PPC64_DTPREL34, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, signed,
+ ppc64_elf_unhandled_reloc),
+
+ HOW (R_PPC64_GOT_TLSGD34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ ppc64_elf_unhandled_reloc),
+
+ HOW (R_PPC64_GOT_TLSLD34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ ppc64_elf_unhandled_reloc),
+
+ HOW (R_PPC64_GOT_TPREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ ppc64_elf_unhandled_reloc),
+
+ HOW (R_PPC64_GOT_DTPREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ ppc64_elf_unhandled_reloc),
+
HOW (R_PPC64_ADDR16_HIGHER34, 1, 16, 0xffff, 34, FALSE, dont,
bfd_elf_generic_reloc),
break;
case BFD_RELOC_PPC64_PLTGOT16_LO_DS: r = R_PPC64_PLTGOT16_LO_DS;
break;
+ case BFD_RELOC_PPC64_TLS_PCREL:
case BFD_RELOC_PPC_TLS: r = R_PPC64_TLS;
break;
case BFD_RELOC_PPC_TLSGD: r = R_PPC64_TLSGD;
break;
case BFD_RELOC_PPC64_PLT_PCREL34: r = R_PPC64_PLT_PCREL34;
break;
+ case BFD_RELOC_PPC64_TPREL34: r = R_PPC64_TPREL34;
+ break;
+ case BFD_RELOC_PPC64_DTPREL34: r = R_PPC64_DTPREL34;
+ break;
+ case BFD_RELOC_PPC64_GOT_TLSGD34: r = R_PPC64_GOT_TLSGD34;
+ break;
+ case BFD_RELOC_PPC64_GOT_TLSLD34: r = R_PPC64_GOT_TLSLD34;
+ break;
+ case BFD_RELOC_PPC64_GOT_TPREL34: r = R_PPC64_GOT_TPREL34;
+ break;
+ case BFD_RELOC_PPC64_GOT_DTPREL34: r = R_PPC64_GOT_DTPREL34;
+ break;
case BFD_RELOC_PPC64_ADDR16_HIGHER34: r = R_PPC64_ADDR16_HIGHER34;
break;
case BFD_RELOC_PPC64_ADDR16_HIGHERA34: r = R_PPC64_ADDR16_HIGHERA34;
case R_PPC64_TPREL16_HIGHEST:
case R_PPC64_TPREL16_HIGHESTA:
case R_PPC64_TPREL64:
+ case R_PPC64_TPREL34:
/* These relocations are relative but in a shared library the
linker doesn't know the thread pointer base. */
return bfd_link_dll (info);
case R_PPC64_D34_HI30:
case R_PPC64_D34_HA30:
case R_PPC64_D28:
+ case R_PPC64_TPREL34:
+ case R_PPC64_DTPREL34:
htab->powerxx_stubs = 1;
/* Fall through. */
default:
case R_PPC64_PCREL34:
case R_PPC64_GOT_PCREL34:
+ case R_PPC64_GOT_TLSGD34:
+ case R_PPC64_GOT_TLSLD34:
+ case R_PPC64_GOT_TPREL34:
+ case R_PPC64_GOT_DTPREL34:
case R_PPC64_PLT_PCREL34:
case R_PPC64_PLT_PCREL34_NOTOC:
case R_PPC64_PCREL28:
case R_PPC64_GOT_TLSLD16_LO:
case R_PPC64_GOT_TLSLD16_HI:
case R_PPC64_GOT_TLSLD16_HA:
+ case R_PPC64_GOT_TLSLD34:
tls_type = TLS_TLS | TLS_LD;
goto dogottls;
case R_PPC64_GOT_TLSGD16_LO:
case R_PPC64_GOT_TLSGD16_HI:
case R_PPC64_GOT_TLSGD16_HA:
+ case R_PPC64_GOT_TLSGD34:
tls_type = TLS_TLS | TLS_GD;
goto dogottls;
case R_PPC64_GOT_TPREL16_LO_DS:
case R_PPC64_GOT_TPREL16_HI:
case R_PPC64_GOT_TPREL16_HA:
+ case R_PPC64_GOT_TPREL34:
if (bfd_link_dll (info))
info->flags |= DF_STATIC_TLS;
tls_type = TLS_TLS | TLS_TPREL;
case R_PPC64_GOT_DTPREL16_LO_DS:
case R_PPC64_GOT_DTPREL16_HI:
case R_PPC64_GOT_DTPREL16_HA:
+ case R_PPC64_GOT_DTPREL34:
tls_type = TLS_TLS | TLS_DTPREL;
dogottls:
sec->has_tls_reloc = 1;
case R_PPC64_TPREL16_HIGHERA:
case R_PPC64_TPREL16_HIGHEST:
case R_PPC64_TPREL16_HIGHESTA:
+ case R_PPC64_TPREL34:
if (bfd_link_dll (info))
info->flags |= DF_STATIC_TLS;
goto dodyn;
case R_PPC64_TPREL16_HIGHEST:
case R_PPC64_TPREL16_HIGHESTA:
case R_PPC64_TPREL64:
+ case R_PPC64_TPREL34:
case R_PPC64_DTPMOD64:
case R_PPC64_DTPREL64:
case R_PPC64_ADDR64:
value += sym_sec->output_offset;
value += sym_sec->output_section->vma;
value -= htab->elf.tls_sec->vma + TP_OFFSET;
+ /* Note that even though the prefix insns
+ allow a 1<<33 offset we use the same test
+ as for addis;addi. There may be a mix of
+ pcrel and non-pcrel code and the decision
+ to optimise is per symbol, not per TLS
+ sequence. */
ok_tprel = value + 0x80008000ULL < 1ULL << 32;
}
}
{
case R_PPC64_GOT_TLSLD16:
case R_PPC64_GOT_TLSLD16_LO:
+ case R_PPC64_GOT_TLSLD34:
expecting_tls_get_addr = 1;
found_tls_get_addr_arg = 1;
/* Fall through. */
case R_PPC64_GOT_TLSGD16:
case R_PPC64_GOT_TLSGD16_LO:
+ case R_PPC64_GOT_TLSGD34:
expecting_tls_get_addr = 1;
found_tls_get_addr_arg = 1;
/* Fall through. */
tls_type = TLS_TLS | TLS_GD;
break;
+ case R_PPC64_GOT_TPREL34:
case R_PPC64_GOT_TPREL16_DS:
case R_PPC64_GOT_TPREL16_LO_DS:
case R_PPC64_GOT_TPREL16_HI:
}
break;
+ case R_PPC64_GOT_TPREL34:
+ if ((tls_mask & TLS_TLS) != 0
+ && (tls_mask & TLS_TPREL) == 0)
+ {
+ /* pld ra,sym@got@tprel@pcrel -> paddi ra,r13,sym@tprel */
+ pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ pinsn <<= 32;
+ pinsn |= bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+ pinsn += ((2ULL << 56) + (-1ULL << 52)
+ + (14ULL << 26) - (57ULL << 26) + (13ULL << 16));
+ bfd_put_32 (input_bfd, pinsn >> 32,
+ contents + rel->r_offset);
+ bfd_put_32 (input_bfd, pinsn & 0xffffffff,
+ contents + rel->r_offset + 4);
+ r_type = R_PPC64_TPREL34;
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ }
+ break;
+
case R_PPC64_TLS:
if ((tls_mask & TLS_TLS) != 0
&& (tls_mask & TLS_TPREL) == 0)
{
- insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
insn = _bfd_elf_ppc_at_tls_transform (insn, 13);
if (insn == 0)
- abort ();
- bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
- /* Was PPC64_TLS which sits on insn boundary, now
- PPC64_TPREL16_LO which is at low-order half-word. */
- rel->r_offset += d_offset;
- r_type = R_PPC64_TPREL16_LO;
- if (toc_symndx != 0)
+ break;
+ if ((rel->r_offset & 3) == 0)
{
- rel->r_info = ELF64_R_INFO (toc_symndx, r_type);
- rel->r_addend = toc_addend;
- /* We changed the symbol. Start over in order to
- get h, sym, sec etc. right. */
- goto again;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+ /* Was PPC64_TLS which sits on insn boundary, now
+ PPC64_TPREL16_LO which is at low-order half-word. */
+ rel->r_offset += d_offset;
+ r_type = R_PPC64_TPREL16_LO;
+ if (toc_symndx != 0)
+ {
+ rel->r_info = ELF64_R_INFO (toc_symndx, r_type);
+ rel->r_addend = toc_addend;
+ /* We changed the symbol. Start over in order to
+ get h, sym, sec etc. right. */
+ goto again;
+ }
+ else
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ }
+ else if ((rel->r_offset & 3) == 1)
+ {
+ /* For pcrel IE to LE we already have the full
+ offset and thus don't need an addi here. A nop
+ or mr will do. */
+ if ((insn & (0x3f << 26)) == 14 << 26)
+ {
+ /* Extract regs from addi rt,ra,si. */
+ unsigned int rt = (insn >> 21) & 0x1f;
+ unsigned int ra = (insn >> 16) & 0x1f;
+ if (rt == ra)
+ insn = NOP;
+ else
+ {
+ /* Build or ra,rs,rb with rb==rs, ie. mr ra,rs. */
+ insn = (rt << 16) | (ra << 21) | (ra << 11);
+ insn |= (31u << 26) | (444u << 1);
+ }
+ }
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset - 1);
}
- else
- rel->r_info = ELF64_R_INFO (r_symndx, r_type);
}
break;
}
break;
+ case R_PPC64_GOT_TLSGD34:
+ if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
+ {
+ pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ pinsn <<= 32;
+ pinsn |= bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+ if ((tls_mask & TLS_GDIE) != 0)
+ {
+ /* IE, pla -> pld */
+ pinsn += (-2ULL << 56) + (57ULL << 26) - (14ULL << 26);
+ r_type = R_PPC64_GOT_TPREL34;
+ }
+ else
+ {
+ /* LE, pla pcrel -> paddi r13 */
+ pinsn += (-1ULL << 52) + (13ULL << 16);
+ r_type = R_PPC64_TPREL34;
+ }
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ bfd_put_32 (input_bfd, pinsn >> 32,
+ contents + rel->r_offset);
+ bfd_put_32 (input_bfd, pinsn & 0xffffffff,
+ contents + rel->r_offset + 4);
+ }
+ break;
+
+ case R_PPC64_GOT_TLSLD34:
+ if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0)
+ {
+ pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ pinsn <<= 32;
+ pinsn |= bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+ pinsn += (-1ULL << 52) + (13ULL << 16);
+ bfd_put_32 (input_bfd, pinsn >> 32,
+ contents + rel->r_offset);
+ bfd_put_32 (input_bfd, pinsn & 0xffffffff,
+ contents + rel->r_offset + 4);
+ rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
+ r_symndx = STN_UNDEF;
+ r_type = R_PPC64_TPREL34;
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ goto again;
+ }
+ break;
+
case R_PPC64_TLSGD:
if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
&& rel + 1 < relend)
r_symndx = toc_symndx;
rel->r_addend = toc_addend;
}
- r_type = R_PPC64_TPREL16_LO;
- rel->r_offset = offset + d_offset;
- insn2 = 0x38630000; /* addi 3,3,0 */
+ if (r_type1 == R_PPC64_REL24_NOTOC
+ || r_type1 == R_PPC64_PLTCALL_NOTOC)
+ {
+ r_type = R_PPC64_NONE;
+ insn2 = NOP;
+ }
+ else
+ {
+ rel->r_offset = offset + d_offset;
+ r_type = R_PPC64_TPREL16_LO;
+ insn2 = 0x38630000; /* addi 3,3,0 */
+ }
}
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
/* Zap the reloc on the _tls_get_addr call too. */
BFD_ASSERT (offset == rel[1].r_offset);
rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_PPC64_NONE);
bfd_put_32 (input_bfd, insn2, contents + offset);
- if ((tls_mask & TLS_GDIE) == 0 && toc_symndx != 0)
+ if ((tls_mask & TLS_GDIE) == 0
+ && toc_symndx != 0
+ && r_type != R_PPC64_NONE)
goto again;
}
break;
if (ELF64_R_TYPE (rel[1].r_info) == R_PPC64_PLTCALL)
bfd_put_32 (output_bfd, NOP, contents + offset + 4);
- rel->r_offset = offset + d_offset;
- r_symndx = STN_UNDEF;
- r_type = R_PPC64_TPREL16_LO;
+ if (r_type1 == R_PPC64_REL24_NOTOC
+ || r_type1 == R_PPC64_PLTCALL_NOTOC)
+ {
+ r_type = R_PPC64_NONE;
+ insn2 = NOP;
+ }
+ else
+ {
+ rel->r_offset = offset + d_offset;
+ r_symndx = STN_UNDEF;
+ r_type = R_PPC64_TPREL16_LO;
+ rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
+ insn2 = 0x38630000; /* addi 3,3,0 */
+ }
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
- rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
-
/* Zap the reloc on the _tls_get_addr call too. */
BFD_ASSERT (offset == rel[1].r_offset);
rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_PPC64_NONE);
- insn2 = 0x38630000; /* addi 3,3,0 */
bfd_put_32 (input_bfd, insn2, contents + offset);
- goto again;
+ if (r_type != R_PPC64_NONE)
+ goto again;
}
break;
case R_PPC64_GOT_TLSGD16_LO:
case R_PPC64_GOT_TLSGD16_HI:
case R_PPC64_GOT_TLSGD16_HA:
+ case R_PPC64_GOT_TLSGD34:
tls_type = TLS_TLS | TLS_GD;
goto dogot;
case R_PPC64_GOT_TLSLD16_LO:
case R_PPC64_GOT_TLSLD16_HI:
case R_PPC64_GOT_TLSLD16_HA:
+ case R_PPC64_GOT_TLSLD34:
tls_type = TLS_TLS | TLS_LD;
goto dogot;
case R_PPC64_GOT_TPREL16_LO_DS:
case R_PPC64_GOT_TPREL16_HI:
case R_PPC64_GOT_TPREL16_HA:
+ case R_PPC64_GOT_TPREL34:
tls_type = TLS_TLS | TLS_TPREL;
goto dogot;
case R_PPC64_GOT_DTPREL16_LO_DS:
case R_PPC64_GOT_DTPREL16_HI:
case R_PPC64_GOT_DTPREL16_HA:
+ case R_PPC64_GOT_DTPREL34:
tls_type = TLS_TLS | TLS_DTPREL;
goto dogot;
struct got_entry *ent;
bfd_vma sym_addend = orig_rel.r_addend;
- if (r_type == R_PPC64_GOT_PCREL34)
+ if (r_type == R_PPC64_GOT_PCREL34
+ || r_type == R_PPC64_GOT_TLSGD34
+ || r_type == R_PPC64_GOT_TLSLD34
+ || r_type == R_PPC64_GOT_TPREL34
+ || r_type == R_PPC64_GOT_DTPREL34)
sym_addend = 0;
if (tls_type == (TLS_TLS | TLS_LD)
abort ();
relocation = got->output_section->vma + got->output_offset + off;
- if (r_type != R_PPC64_GOT_PCREL34)
+ if (!(r_type == R_PPC64_GOT_PCREL34
+ || r_type == R_PPC64_GOT_TLSGD34
+ || r_type == R_PPC64_GOT_TLSLD34
+ || r_type == R_PPC64_GOT_TPREL34
+ || r_type == R_PPC64_GOT_DTPREL34))
addend = -(TOCstart + htab->sec_info[input_section->id].toc_off);
}
break;
case R_PPC64_TPREL16_HIGHERA:
case R_PPC64_TPREL16_HIGHEST:
case R_PPC64_TPREL16_HIGHESTA:
+ case R_PPC64_TPREL34:
if (h != NULL
&& h->elf.root.type == bfd_link_hash_undefweak
&& h->elf.dynindx == -1)
case R_PPC64_DTPREL16_HIGHERA:
case R_PPC64_DTPREL16_HIGHEST:
case R_PPC64_DTPREL16_HIGHESTA:
+ case R_PPC64_DTPREL34:
if (htab->elf.tls_sec != NULL)
addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
break;
case R_PPC64_D34_HA30:
case R_PPC64_PCREL34:
case R_PPC64_GOT_PCREL34:
+ case R_PPC64_TPREL34:
+ case R_PPC64_DTPREL34:
+ case R_PPC64_GOT_TLSGD34:
+ case R_PPC64_GOT_TLSLD34:
+ case R_PPC64_GOT_TPREL34:
+ case R_PPC64_GOT_DTPREL34:
case R_PPC64_PLT_PCREL34:
case R_PPC64_PLT_PCREL34_NOTOC:
case R_PPC64_D28:
"BFD_RELOC_PPC64_DTPREL16_HIGHERA",
"BFD_RELOC_PPC64_DTPREL16_HIGHEST",
"BFD_RELOC_PPC64_DTPREL16_HIGHESTA",
+ "BFD_RELOC_PPC64_TPREL34",
+ "BFD_RELOC_PPC64_DTPREL34",
+ "BFD_RELOC_PPC64_GOT_TLSGD34",
+ "BFD_RELOC_PPC64_GOT_TLSLD34",
+ "BFD_RELOC_PPC64_GOT_TPREL34",
+ "BFD_RELOC_PPC64_GOT_DTPREL34",
+ "BFD_RELOC_PPC64_TLS_PCREL",
"BFD_RELOC_I370_D12",
"BFD_RELOC_CTOR",
"BFD_RELOC_ARM_PCREL_BRANCH",
BFD_RELOC_PPC64_DTPREL16_HIGHEST
ENUMX
BFD_RELOC_PPC64_DTPREL16_HIGHESTA
+ENUMX
+ BFD_RELOC_PPC64_TPREL34
+ENUMX
+ BFD_RELOC_PPC64_DTPREL34
+ENUMX
+ BFD_RELOC_PPC64_GOT_TLSGD34
+ENUMX
+ BFD_RELOC_PPC64_GOT_TLSLD34
+ENUMX
+ BFD_RELOC_PPC64_GOT_TPREL34
+ENUMX
+ BFD_RELOC_PPC64_GOT_DTPREL34
+ENUMX
+ BFD_RELOC_PPC64_TLS_PCREL
ENUMDOC
PowerPC and PowerPC64 thread-local storage relocations.
+2019-07-19 Alan Modra <amodra@gmail.com>
+
+ * config/tc-ppc.c (ppc_elf_suffix): Map "tls@pcrel", "got@tlsgd@pcrel",
+ "got@tlsld@pcrel", "got@tprel@pcrel", and "got@dtprel@pcrel".
+ (fixup_size, md_assemble): Handle pcrel tls relocs.
+ (ppc_force_relocation, ppc_fix_adjustable): Likewise.
+ (md_apply_fix, tc_gen_reloc): Likewise.
+
2019-07-17 Jose E. Marchesi <jose.marchesi@oracle.com>
* config/tc-bpf.c: Make .lcomm to get a third argument with the
MAP64 ("pcrel", BFD_RELOC_PPC64_PCREL34),
MAP64 ("got@pcrel", BFD_RELOC_PPC64_GOT_PCREL34),
MAP64 ("plt@pcrel", BFD_RELOC_PPC64_PLT_PCREL34),
+ MAP64 ("tls@pcrel", BFD_RELOC_PPC64_TLS_PCREL),
+ MAP64 ("got@tlsgd@pcrel", BFD_RELOC_PPC64_GOT_TLSGD34),
+ MAP64 ("got@tlsld@pcrel", BFD_RELOC_PPC64_GOT_TLSLD34),
+ MAP64 ("got@tprel@pcrel", BFD_RELOC_PPC64_GOT_TPREL34),
+ MAP64 ("got@dtprel@pcrel", BFD_RELOC_PPC64_GOT_DTPREL34),
MAP64 ("higher34", BFD_RELOC_PPC64_ADDR16_HIGHER34),
MAP64 ("highera34", BFD_RELOC_PPC64_ADDR16_HIGHERA34),
MAP64 ("highest34", BFD_RELOC_PPC64_ADDR16_HIGHEST34),
case BFD_RELOC_PPC_VLE_SDAREL_HI16D:
case BFD_RELOC_PPC_VLE_SDAREL_LO16A:
case BFD_RELOC_PPC_VLE_SDAREL_LO16D:
+ case BFD_RELOC_PPC64_TLS_PCREL:
case BFD_RELOC_RVA:
size = 4;
break;
case BFD_RELOC_PPC64_D34_LO:
case BFD_RELOC_PPC64_D34_HI30:
case BFD_RELOC_PPC64_D34_HA30:
+ case BFD_RELOC_PPC64_TPREL34:
+ case BFD_RELOC_PPC64_DTPREL34:
case BFD_RELOC_PPC64_TOC:
size = 8;
break;
case BFD_RELOC_64_PCREL:
case BFD_RELOC_64_PLT_PCREL:
case BFD_RELOC_PPC64_GOT_PCREL34:
+ case BFD_RELOC_PPC64_GOT_TLSGD34:
+ case BFD_RELOC_PPC64_GOT_TLSLD34:
+ case BFD_RELOC_PPC64_GOT_TPREL34:
+ case BFD_RELOC_PPC64_GOT_DTPREL34:
case BFD_RELOC_PPC64_PCREL28:
case BFD_RELOC_PPC64_PCREL34:
case BFD_RELOC_PPC64_PLT_PCREL34:
break;
case BFD_RELOC_PPC_TLS:
+ case BFD_RELOC_PPC64_TLS_PCREL:
if (!_bfd_elf_ppc_at_tls_transform (opcode->opcode, 0))
as_bad (_("@tls may not be used with \"%s\" operands"),
opcode->name);
break;
/* We'll only use the 32 (or 64) bit form of these relocations
- in constants. Instructions get the 16 bit form. */
+ in constants. Instructions get the 16 or 34 bit form. */
case BFD_RELOC_PPC_DTPREL:
- reloc = BFD_RELOC_PPC_DTPREL16;
+ if (operand->bitm == 0x3ffffffffULL)
+ reloc = BFD_RELOC_PPC64_DTPREL34;
+ else
+ reloc = BFD_RELOC_PPC_DTPREL16;
break;
case BFD_RELOC_PPC_TPREL:
- reloc = BFD_RELOC_PPC_TPREL16;
+ if (operand->bitm == 0x3ffffffffULL)
+ reloc = BFD_RELOC_PPC64_TPREL34;
+ else
+ reloc = BFD_RELOC_PPC_TPREL16;
break;
case BFD_RELOC_PPC64_PCREL34:
/* Fall through. */
case BFD_RELOC_PPC64_GOT_PCREL34:
case BFD_RELOC_PPC64_PLT_PCREL34:
+ case BFD_RELOC_PPC64_GOT_TLSGD34:
+ case BFD_RELOC_PPC64_GOT_TLSLD34:
+ case BFD_RELOC_PPC64_GOT_TPREL34:
+ case BFD_RELOC_PPC64_GOT_DTPREL34:
if (operand->bitm != 0x3ffffffffULL
|| (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
as_warn (_("%s unsupported on this instruction"), "@pcrel");
}
if (fix->fx_r_type >= BFD_RELOC_PPC_TLS
- && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
+ && fix->fx_r_type <= BFD_RELOC_PPC64_TLS_PCREL)
return 1;
return generic_force_reloc (fix);
&& fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT
&& fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY
&& !(fix->fx_r_type >= BFD_RELOC_PPC_TLS
- && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA));
+ && fix->fx_r_type <= BFD_RELOC_PPC64_TLS_PCREL));
}
#endif
case BFD_RELOC_PPC64_DTPREL16_HIGHERA:
case BFD_RELOC_PPC64_DTPREL16_HIGHEST:
case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:
+ case BFD_RELOC_PPC64_TPREL34:
+ case BFD_RELOC_PPC64_DTPREL34:
+ case BFD_RELOC_PPC64_GOT_TLSGD34:
+ case BFD_RELOC_PPC64_GOT_TLSLD34:
+ case BFD_RELOC_PPC64_GOT_TPREL34:
+ case BFD_RELOC_PPC64_GOT_DTPREL34:
gas_assert (fixP->fx_addsy != NULL);
S_SET_THREAD_LOCAL (fixP->fx_addsy);
fieldval = 0;
case BFD_RELOC_PPC_TLS:
case BFD_RELOC_PPC_TLSGD:
case BFD_RELOC_PPC_TLSLD:
+ case BFD_RELOC_PPC64_TLS_PCREL:
fieldval = 0;
break;
#endif
case BFD_RELOC_PPC64_TPREL16_HIGHERA:
case BFD_RELOC_PPC64_TPREL16_HIGHEST:
case BFD_RELOC_PPC64_TPREL16_HIGHESTA:
+ case BFD_RELOC_PPC64_TLS_PCREL:
fixP->fx_done = 0;
break;
#endif
reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ /* BFD_RELOC_PPC64_TLS_PCREL generates R_PPC64_TLS with an odd r_offset. */
+ if (fixp->fx_r_type == BFD_RELOC_PPC64_TLS_PCREL)
+ reloc->address++;
reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
if (reloc->howto == (reloc_howto_type *) NULL)
{
+2019-07-19 Alan Modra <amodra@gmail.com>
+
+ * elf/ppc64.h (R_PPC64_TPREL34, R_PPC64_DTPREL34),
+ (R_PPC64_GOT_TLSGD34, R_PPC64_GOT_TLSLD34),
+ (R_PPC64_GOT_TPREL34, R_PPC64_GOT_DTPREL34): Define.
+ (IS_PPC64_TLS_RELOC): Include new tls relocs.
+
2019-07-18 Nick Alcock <nick.alcock@oracle.com>
* ctf-api.h (ECTF_NOTFUNC): Fix description.
RELOC_NUMBER (R_PPC64_REL16_HIGHESTA34, 143)
RELOC_NUMBER (R_PPC64_D28, 144)
RELOC_NUMBER (R_PPC64_PCREL28, 145)
+ RELOC_NUMBER (R_PPC64_TPREL34, 146)
+ RELOC_NUMBER (R_PPC64_DTPREL34, 147)
+ RELOC_NUMBER (R_PPC64_GOT_TLSGD34, 148)
+ RELOC_NUMBER (R_PPC64_GOT_TLSLD34, 149)
+ RELOC_NUMBER (R_PPC64_GOT_TPREL34, 150)
+ RELOC_NUMBER (R_PPC64_GOT_DTPREL34, 151)
#ifndef RELOC_MACROS_GEN_FUNC
/* Relocation only used internally by gas or ld. If you need to use
#define IS_PPC64_TLS_RELOC(R) \
(((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA) \
- || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA))
-
+ || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA) \
+ || ((R) >= R_PPC64_TPREL34 && (R) <= R_PPC64_GOT_DTPREL34))
/* e_flags bits specifying ABI.
1 for original function descriptor using ABI,
+2019-07-19 Alan Modra <amodra@gmail.com>
+
+ * testsuite/ld-powerpc/tlsgd.d,
+ * testsuite/ld-powerpc/tlsgd.s,
+ * testsuite/ld-powerpc/tlsie.d,
+ * testsuite/ld-powerpc/tlsie.s,
+ * testsuite/ld-powerpc/tlsld.d,
+ * testsuite/ld-powerpc/tlsld.s: New tests.
+ * testsuite/ld-powerpc/powerpc.exp: Run them.
+
2019-07-19 Alan Modra <amodra@gmail.com>
* testsuite/ld-powerpc/tlsldopt.d: Rename from tlsld.d.
run_dump_test "pr23937"
run_dump_test "callstub-1"
run_dump_test "callstub-2"
+ run_dump_test "tlsgd"
+ run_dump_test "tlsld"
+ run_dump_test "tlsie"
}
run_dump_test "tlsldopt32"
--- /dev/null
+#source: tlsgd.s
+#as: -a64 -mfuture
+#ld: -melf64ppc
+#objdump: -dr -Mfuture
+
+.*: file format .*
+
+Disassembly of section \.text:
+
+.*:
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 90 08|08 90 6d 38) addi r3,r13,-28664
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 90 10|10 90 6d 38) addi r3,r13,-28656
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (06 03 ff ff|ff ff 03 06) paddi r3,r13,-28648
+.*: (38 6d 90 18|18 90 6d 38)
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 90 20|20 90 6d 38) addi r3,r13,-28640
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 90 20|20 90 6d 38) addi r3,r13,-28640
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (06 03 ff ff|ff ff 03 06) paddi r3,r13,-28640
+.*: (38 6d 90 20|20 90 6d 38)
+.*: (60 00 00 00|00 00 00 60) nop
--- /dev/null
+ .section ".tbss","awT",@nobits
+ .p2align 3
+pad: .space 8
+ .global a
+a: .space 8
+ .global b
+b: .space 8
+ .global c
+c: .space 8
+ .global d
+d: .space 8
+
+ .text
+ .globl _start
+_start:
+#Small model OpenPower
+ addi 3,2,.La@toc
+ bl __tls_get_addr(.La@tlsgd)
+ nop
+ .section .toc,"aw",@progbits
+ .p2align 3
+.La:
+ .quad a@dtpmod
+ .quad a@dtprel
+ .text
+
+#Medium mode ELF
+ addis 3,2,b@got@tlsgd@ha
+ addi 3,3,b@got@tlsgd@l
+ bl __tls_get_addr(b@tlsgd)
+ nop
+
+#PCrel
+ pla 3,c@got@tlsgd@pcrel
+ bl __tls_get_addr@notoc(c@tlsgd)
+
+#All of the above using the same symbol
+ addis 3,2,.Ld@toc@ha
+ addi 3,3,.Ld@toc@l
+ bl __tls_get_addr(.Ld@tlsgd)
+ nop
+ .section .toc,"aw",@progbits
+.Ld:
+ .quad d@dtpmod
+ .quad d@dtprel
+ .text
+ addis 3,2,d@got@tlsgd@ha
+ addi 3,3,d@got@tlsgd@l
+ bl __tls_get_addr(d@tlsgd)
+ nop
+ pla 3,d@got@tlsgd@pcrel
+ bl __tls_get_addr@notoc(d@tlsgd)
--- /dev/null
+#source: tlsie.s
+#as: -a64 -mfuture
+#ld: -melf64ppc
+#objdump: -dr -Mfuture
+
+.*: file format .*
+
+Disassembly of section \.text:
+
+.*:
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (39 4d 90 08|08 90 4d 39) addi r10,r13,-28664
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 90 10|10 90 6d 38) addi r3,r13,-28656
+.*: (06 03 ff ff|ff ff 03 06) paddi r4,r13,-28648
+.*: (38 8d 90 18|18 90 8d 38)
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (39 4d 90 20|20 90 4d 39) addi r10,r13,-28640
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 90 20|20 90 6d 38) addi r3,r13,-28640
+.*: (06 03 ff ff|ff ff 03 06) paddi r30,r13,-28640
+.*: (3b cd 90 20|20 90 cd 3b)
+.*: (7f c3 f3 78|78 f3 c3 7f) mr r3,r30
+.*: (80 9e 00 00|00 00 9e 80) lwz r4,0\(r30\)
+.*: (84 9e 00 00|00 00 9e 84) lwzu r4,0\(r30\)
+.*: (88 be 00 00|00 00 be 88) lbz r5,0\(r30\)
+.*: (8c be 00 00|00 00 be 8c) lbzu r5,0\(r30\)
+.*: (90 de 00 00|00 00 de 90) stw r6,0\(r30\)
+.*: (94 de 00 00|00 00 de 94) stwu r6,0\(r30\)
+.*: (98 fe 00 00|00 00 fe 98) stb r7,0\(r30\)
+.*: (9c fe 00 00|00 00 fe 9c) stbu r7,0\(r30\)
+.*: (a1 1e 00 00|00 00 1e a1) lhz r8,0\(r30\)
+.*: (a5 1e 00 00|00 00 1e a5) lhzu r8,0\(r30\)
+.*: (a9 3e 00 00|00 00 3e a9) lha r9,0\(r30\)
+.*: (ad 3e 00 00|00 00 3e ad) lhau r9,0\(r30\)
+.*: (b1 5e 00 00|00 00 5e b1) sth r10,0\(r30\)
+.*: (b5 5e 00 00|00 00 5e b5) sthu r10,0\(r30\)
+.*: (c1 7e 00 00|00 00 7e c1) lfs f11,0\(r30\)
+.*: (c5 7e 00 00|00 00 7e c5) lfsu f11,0\(r30\)
+.*: (c9 9e 00 00|00 00 9e c9) lfd f12,0\(r30\)
+.*: (cd 9e 00 00|00 00 9e cd) lfdu f12,0\(r30\)
+.*: (d1 be 00 00|00 00 be d1) stfs f13,0\(r30\)
+.*: (d5 be 00 00|00 00 be d5) stfsu f13,0\(r30\)
+.*: (d9 de 00 00|00 00 de d9) stfd f14,0\(r30\)
+.*: (dd de 00 00|00 00 de dd) stfdu f14,0\(r30\)
+.*: (e9 fe 00 00|00 00 fe e9) ld r15,0\(r30\)
+.*: (e9 fe 00 01|01 00 fe e9) ldu r15,0\(r30\)
+.*: (fa 1e 00 00|00 00 1e fa) std r16,0\(r30\)
+.*: (fa 1e 00 01|01 00 1e fa) stdu r16,0\(r30\)
+.*: (ea 3e 00 02|02 00 3e ea) lwa r17,0\(r30\)
--- /dev/null
+ .section ".tbss","awT",@nobits
+ .p2align 3
+pad: .space 8
+ .global a
+a: .space 8
+ .global b
+b: .space 8
+ .global c
+c: .space 8
+ .global d
+d: .space 8
+
+ .text
+ .globl _start
+_start:
+#Small model OpenPower
+ ld 9,.La@toc(2)
+ add 10,9,.La@tls
+ .section .toc,"aw",@progbits
+.La:
+ .quad a@tprel
+ .text
+
+#Medium model ELF
+ addi 9,2,b@got@tprel@ha
+ ld 10,b@got@tprel@l(9)
+ add 3,10,b@tls
+
+#PCrel
+ pld 4,c@got@tprel@pcrel
+ add 4,4,c@tls@pcrel
+
+#All of the above using the same symbol
+ addis 9,2,.Ld@toc@ha
+ ld 9,.Ld@toc@l(9)
+ add 10,9,.Ld@tls
+ .section .toc,"aw",@progbits
+.Ld:
+ .quad d@tprel
+ .text
+ addi 9,2,d@got@tprel@ha
+ ld 31,d@got@tprel@l(9)
+ add 3,31,d@tls
+ pld 30,d@got@tprel@pcrel
+ add 3,30,d@tls@pcrel
+#Note that after optimisation r31 and r30 above have a different value to
+#what they would have without optimisation. r31 may not even be written.
+#Here are all the other insns that gas/ld accept as the final insn of an
+#IE sequence. The r30 value below will be different after optimisation
+#for the non-update forms.
+ lwzx 4,30,d@tls@pcrel
+ lwzux 4,30,d@tls@pcrel
+ lbzx 5,30,d@tls@pcrel
+ lbzux 5,30,d@tls@pcrel
+ stwx 6,30,d@tls@pcrel
+ stwux 6,30,d@tls@pcrel
+ stbx 7,30,d@tls@pcrel
+ stbux 7,30,d@tls@pcrel
+ lhzx 8,30,d@tls@pcrel
+ lhzux 8,30,d@tls@pcrel
+ lhax 9,30,d@tls@pcrel
+ lhaux 9,30,d@tls@pcrel
+ sthx 10,30,d@tls@pcrel
+ sthux 10,30,d@tls@pcrel
+ lfsx 11,30,d@tls@pcrel
+ lfsux 11,30,d@tls@pcrel
+ lfdx 12,30,d@tls@pcrel
+ lfdux 12,30,d@tls@pcrel
+ stfsx 13,30,d@tls@pcrel
+ stfsux 13,30,d@tls@pcrel
+ stfdx 14,30,d@tls@pcrel
+ stfdux 14,30,d@tls@pcrel
+ ldx 15,30,d@tls@pcrel
+ ldux 15,30,d@tls@pcrel
+ stdx 16,30,d@tls@pcrel
+ stdux 16,30,d@tls@pcrel
+ lwax 17,30,d@tls@pcrel
--- /dev/null
+#source: tlsld.s
+#as: -a64 -mfuture
+#ld: -melf64ppc
+#objdump: -dr -Mfuture
+
+.*: file format .*
+
+Disassembly of section \.text:
+
+.*:
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 10 00|00 10 6d 38) addi r3,r13,4096
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 10 00|00 10 6d 38) addi r3,r13,4096
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (06 00 00 00|00 00 00 06) paddi r3,r13,4096
+.*: (38 6d 10 00|00 10 6d 38)
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (06 03 ff ff|ff ff 03 06) paddi r9,r3,-32728
+.*: (39 23 80 28|28 80 23 39)
+.*: (04 10 00 01|01 00 10 04) pld r10,65784
+.*: (e5 40 00 f8|f8 00 40 e5)
+.*: (7d 4a 1a 14|14 1a 4a 7d) add r10,r10,r3
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 10 00|00 10 6d 38) addi r3,r13,4096
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (38 6d 10 00|00 10 6d 38) addi r3,r13,4096
+.*: (60 00 00 00|00 00 00 60) nop
+.*: (06 00 00 00|00 00 00 06) paddi r3,r13,4096
+.*: (38 6d 10 00|00 10 6d 38)
+.*: (60 00 00 00|00 00 00 60) nop
--- /dev/null
+ .section ".tbss","awT",@nobits
+ .p2align 3
+pad: .space 8
+ .global a
+a: .space 8
+ .global b
+b: .space 8
+ .global c
+c: .space 8
+ .global d
+d: .space 8
+z2: .space 8
+z3: .space 8
+
+ .text
+ .globl _start
+_start:
+#Small model OpenPower
+ addi 3,2,.La@toc
+ bl __tls_get_addr(.La@tlsld)
+ nop
+ .section .toc,"aw",@progbits
+ .p2align 3
+.La:
+ .quad a@dtpmod
+ .quad 0
+ .text
+
+#Medium mode ELF
+ addis 3,2,b@got@tlsld@ha
+ addi 3,3,b@got@tlsld@l
+ bl __tls_get_addr(b@tlsld)
+ nop
+
+#PCrel, with dtprel access to vars
+ pla 3,c@got@tlsld@pcrel
+ bl __tls_get_addr@notoc(c@tlsld)
+ paddi 9,3,z2@dtprel
+ pld 10,z3@got@dtprel@pcrel
+ add 10,10,3
+
+#All of the above using the same symbol
+ addis 3,2,.Ld@toc@ha
+ addi 3,3,.Ld@toc@l
+ bl __tls_get_addr(.Ld@tlsld)
+ nop
+ .section .toc,"aw",@progbits
+ .p2align 3
+.Ld:
+ .quad d@dtpmod
+ .quad 0
+ .text
+ addis 3,2,d@got@tlsld@ha
+ addi 3,3,d@got@tlsld@l
+ bl __tls_get_addr(d@tlsld)
+ nop
+ pla 3,d@got@tlsld@pcrel
+ bl __tls_get_addr@notoc(d@tlsld)