diff options
-rw-r--r-- | bfd/ChangeLog | 14 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 7 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 237 | ||||
-rw-r--r-- | bfd/libbfd.h | 7 | ||||
-rw-r--r-- | bfd/reloc.c | 14 | ||||
-rw-r--r-- | gas/ChangeLog | 8 | ||||
-rw-r--r-- | gas/config/tc-ppc.c | 44 | ||||
-rw-r--r-- | include/ChangeLog | 7 | ||||
-rw-r--r-- | include/elf/ppc64.h | 10 | ||||
-rw-r--r-- | ld/ChangeLog | 10 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/powerpc.exp | 3 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/tlsgd.d | 31 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/tlsgd.s | 52 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/tlsie.d | 54 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/tlsie.s | 77 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/tlsld.d | 36 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/tlsld.s | 58 |
17 files changed, 634 insertions, 35 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a9dce78..62e4beb 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +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 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 05e3219..8374390 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3563,6 +3563,13 @@ instruction. */ 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, diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index df4a12c..abbdfed 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -920,6 +920,24 @@ static reloc_howto_type ppc64_elf_howto_raw[] = 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), @@ -1119,6 +1137,7 @@ ppc64_elf_reloc_type_lookup (bfd *abfd, 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; @@ -1253,6 +1272,18 @@ ppc64_elf_reloc_type_lookup (bfd *abfd, 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; @@ -2727,6 +2758,7 @@ must_be_dyn_reloc (struct bfd_link_info *info, 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); @@ -4514,6 +4546,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *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: @@ -4528,6 +4562,10 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 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: @@ -4580,6 +4618,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 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; @@ -4587,6 +4626,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 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; @@ -4594,6 +4634,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 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; @@ -4603,6 +4644,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 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; @@ -4949,6 +4991,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 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; @@ -6769,6 +6812,7 @@ dec_dynrel_count (bfd_vma r_info, 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: @@ -7733,6 +7777,12 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) 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; } } @@ -7764,6 +7814,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) { 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. */ @@ -7784,6 +7835,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) 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. */ @@ -7800,6 +7852,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info) 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: @@ -14436,29 +14489,72 @@ ppc64_elf_relocate_section (bfd *output_bfd, } 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; @@ -14584,6 +14680,51 @@ ppc64_elf_relocate_section (bfd *output_bfd, } 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) @@ -14619,16 +14760,27 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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; @@ -14654,18 +14806,27 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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; @@ -15267,6 +15428,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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; @@ -15274,6 +15436,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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; @@ -15281,6 +15444,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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; @@ -15288,6 +15452,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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; @@ -15309,7 +15474,11 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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) @@ -15491,7 +15660,11 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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; @@ -15644,6 +15817,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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) @@ -15679,6 +15853,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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; @@ -16301,6 +16476,12 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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: diff --git a/bfd/libbfd.h b/bfd/libbfd.h index ff6e0ea..fd45595 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1539,6 +1539,13 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "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", diff --git a/bfd/reloc.c b/bfd/reloc.c index 266e775..9ca68ca 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -3007,6 +3007,20 @@ ENUMX 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. diff --git a/gas/ChangeLog b/gas/ChangeLog index 6e457d9..b445ba3 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +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 diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 5f8d120..7d6459a 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -2224,6 +2224,11 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p) 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), @@ -3155,6 +3160,7 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative) 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; @@ -3196,6 +3202,8 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative) 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; @@ -3203,6 +3211,10 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative) 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: @@ -3744,6 +3756,7 @@ md_assemble (char *str) 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); @@ -3756,13 +3769,19 @@ md_assemble (char *str) 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: @@ -3774,6 +3793,10 @@ md_assemble (char *str) /* 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"); @@ -7003,7 +7026,7 @@ ppc_force_relocation (fixS *fix) } 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); @@ -7071,7 +7094,7 @@ ppc_fix_adjustable (fixS *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 @@ -7503,6 +7526,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) 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; @@ -7573,6 +7602,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) 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 @@ -7826,6 +7856,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) 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 @@ -7918,6 +7949,9 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) 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) { diff --git a/include/ChangeLog b/include/ChangeLog index 07e0c5c..bb5abb1 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,10 @@ +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. diff --git a/include/elf/ppc64.h b/include/elf/ppc64.h index e90c7fd..226c989 100644 --- a/include/elf/ppc64.h +++ b/include/elf/ppc64.h @@ -181,6 +181,12 @@ START_RELOC_NUMBERS (elf_ppc64_reloc_type) 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 @@ -218,8 +224,8 @@ END_RELOC_NUMBERS (R_PPC64_max) #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, diff --git a/ld/ChangeLog b/ld/ChangeLog index c031b0e..9fcc55c 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,15 @@ 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. * testsuite/ld-powerpc/tlsldopt.s: Rename from tlsld.s. * testsuite/ld-powerpc/tlsldopt32.d: Rename from tlsld32.d. diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp index 508d48e..87a7462 100644 --- a/ld/testsuite/ld-powerpc/powerpc.exp +++ b/ld/testsuite/ld-powerpc/powerpc.exp @@ -343,6 +343,9 @@ if [ supports_ppc64 ] then { 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" diff --git a/ld/testsuite/ld-powerpc/tlsgd.d b/ld/testsuite/ld-powerpc/tlsgd.d new file mode 100644 index 0000000..42c9b5f --- /dev/null +++ b/ld/testsuite/ld-powerpc/tlsgd.d @@ -0,0 +1,31 @@ +#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 diff --git a/ld/testsuite/ld-powerpc/tlsgd.s b/ld/testsuite/ld-powerpc/tlsgd.s new file mode 100644 index 0000000..304bd60 --- /dev/null +++ b/ld/testsuite/ld-powerpc/tlsgd.s @@ -0,0 +1,52 @@ + .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) diff --git a/ld/testsuite/ld-powerpc/tlsie.d b/ld/testsuite/ld-powerpc/tlsie.d new file mode 100644 index 0000000..79613bd --- /dev/null +++ b/ld/testsuite/ld-powerpc/tlsie.d @@ -0,0 +1,54 @@ +#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\) diff --git a/ld/testsuite/ld-powerpc/tlsie.s b/ld/testsuite/ld-powerpc/tlsie.s new file mode 100644 index 0000000..384e7ce --- /dev/null +++ b/ld/testsuite/ld-powerpc/tlsie.s @@ -0,0 +1,77 @@ + .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 diff --git a/ld/testsuite/ld-powerpc/tlsld.d b/ld/testsuite/ld-powerpc/tlsld.d new file mode 100644 index 0000000..740b15b --- /dev/null +++ b/ld/testsuite/ld-powerpc/tlsld.d @@ -0,0 +1,36 @@ +#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 diff --git a/ld/testsuite/ld-powerpc/tlsld.s b/ld/testsuite/ld-powerpc/tlsld.s new file mode 100644 index 0000000..4ab2630 --- /dev/null +++ b/ld/testsuite/ld-powerpc/tlsld.s @@ -0,0 +1,58 @@ + .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) |