PowerPC relocations for prefix insns
authorAlan Modra <amodra@gmail.com>
Wed, 29 Aug 2018 04:52:34 +0000 (14:22 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 24 May 2019 00:57:49 +0000 (10:27 +0930)
include/
* elf/ppc64.h (R_PPC64_PLTSEQ_NOTOC, R_PPC64_PLTCALL_NOTOC),
(R_PPC64_PCREL_OPT, R_PPC64_D34, R_PPC64_D34_LO, R_PPC64_D34_HI30),
(R_PPC64_D34_HA30, R_PPC64_PCREL34, R_PPC64_GOT_PCREL34),
(R_PPC64_PLT_PCREL34, R_PPC64_PLT_PCREL34_NOTOC),
(R_PPC64_ADDR16_HIGHER34, R_PPC64_ADDR16_HIGHERA34),
(R_PPC64_ADDR16_HIGHEST34, R_PPC64_ADDR16_HIGHESTA34),
(R_PPC64_REL16_HIGHER34, R_PPC64_REL16_HIGHERA34),
(R_PPC64_REL16_HIGHEST34, R_PPC64_REL16_HIGHESTA34),
(R_PPC64_D28, R_PPC64_PCREL28): Define.
bfd/
* reloc.c (BFD_RELOC_PPC64_D34, BFD_RELOC_PPC64_D34_LO),
(BFD_RELOC_PPC64_D34_HI30, BFD_RELOC_PPC64_D34_HA30),
(BFD_RELOC_PPC64_PCREL34, BFD_RELOC_PPC64_GOT_PCREL34),
(BFD_RELOC_PPC64_PLT_PCREL34),
(BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34),
(BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34),
(BFD_RELOC_PPC64_REL16_HIGHER34, BFD_RELOC_PPC64_REL16_HIGHERA34),
(BFD_RELOC_PPC64_REL16_HIGHEST34, BFD_RELOC_PPC64_REL16_HIGHESTA34),
(BFD_RELOC_PPC64_D28, BFD_RELOC_PPC64_PCREL28): New reloc enums.
* elf64-ppc.c (PNOP): Define.
(ppc64_elf_howto_raw): Add reloc howtos for new relocations.
(ppc64_elf_reloc_type_lookup): Translate new bfd reloc numbers.
(ppc64_elf_ha_reloc): Adjust addend for highera34 and highesta34
relocs.
(ppc64_elf_prefix_reloc): New function.
(struct ppc_link_hash_table): Add notoc_plt.
(is_branch_reloc): Add R_PPC64_PLTCALL_NOTOC.
(is_plt_seq_reloc): Add R_PPC64_PLT_PCREL34,
R_PPC64_PLT_PCREL34_NOTOC, and R_PPC64_PLTSEQ_NOTOC.
(ppc64_elf_check_relocs): Handle pcrel got and plt relocs.  Set
has_pltcall for section on seeing R_PPC64_PLTCALL_NOTOC.  Handle
possible need for dynamic relocs on non-pcrel powerxx relocs.
(dec_dynrel_count): Handle non-pcrel powerxx relocs.
(ppc64_elf_inline_plt): Handle R_PPC64_PLTCALL_NOTOC.
(toc_adjusting_stub_needed): Likewise.
(ppc64_elf_tls_optimize): Handle R_PPC64_PLTSEQ_NOTOC.
(ppc64_elf_relocate_section): Handle new powerxx relocs.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-ppc.c (ppc_elf_suffix): Support @pcrel, @got@pcrel,
@plt@pcrel, @higher34, @highera34, @highest34, and @highesta34.
(fixup_size): Handle new powerxx relocs.
(md_assemble): Warn for @pcrel on non-prefix insns.
Accept @l, @h and @ha on prefix insns, and infer reloc without
any @ suffix.  Translate powerxx relocs to suit DQ and DS field
instructions.  Include operand tests as well as opcode test to
translate BFD_RELOC_HI16_S to BFD_RELOC_PPC_16DX_HA.
(ppc_fix_adjustable): Return false for pcrel GOT and PLT relocs.
(md_apply_fix): Handle new powerxx relocs.
* config/tc-ppc.h (TC_FORCE_RELOCATION_SUB_LOCAL): Accept
BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34,
BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34,
BFD_RELOC_PPC64_D34, and BFD_RELOC_PPC64_D28.
* testsuite/gas/ppc/prefix-reloc.d,
* testsuite/gas/ppc/prefix-reloc.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.

13 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf64-ppc.c
bfd/libbfd.h
bfd/reloc.c
gas/ChangeLog
gas/config/tc-ppc.c
gas/config/tc-ppc.h
gas/testsuite/gas/ppc/ppc.exp
gas/testsuite/gas/ppc/prefix-reloc.d [new file with mode: 0644]
gas/testsuite/gas/ppc/prefix-reloc.s [new file with mode: 0644]
include/ChangeLog
include/elf/ppc64.h

index aa0a38db3aabd1c1beb07d724037f79211ad7e63..9091df029420dce727c53fa5a31ae0af0dd76d97 100644 (file)
@@ -1,3 +1,35 @@
+2019-05-24  Alan Modra  <amodra@gmail.com>
+
+       * reloc.c (BFD_RELOC_PPC64_D34, BFD_RELOC_PPC64_D34_LO),
+       (BFD_RELOC_PPC64_D34_HI30, BFD_RELOC_PPC64_D34_HA30),
+       (BFD_RELOC_PPC64_PCREL34, BFD_RELOC_PPC64_GOT_PCREL34),
+       (BFD_RELOC_PPC64_PLT_PCREL34),
+       (BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34),
+       (BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34),
+       (BFD_RELOC_PPC64_REL16_HIGHER34, BFD_RELOC_PPC64_REL16_HIGHERA34),
+       (BFD_RELOC_PPC64_REL16_HIGHEST34, BFD_RELOC_PPC64_REL16_HIGHESTA34),
+       (BFD_RELOC_PPC64_D28, BFD_RELOC_PPC64_PCREL28): New reloc enums.
+       * elf64-ppc.c (PNOP): Define.
+       (ppc64_elf_howto_raw): Add reloc howtos for new relocations.
+       (ppc64_elf_reloc_type_lookup): Translate new bfd reloc numbers.
+       (ppc64_elf_ha_reloc): Adjust addend for highera34 and highesta34
+       relocs.
+       (ppc64_elf_prefix_reloc): New function.
+       (struct ppc_link_hash_table): Add notoc_plt.
+       (is_branch_reloc): Add R_PPC64_PLTCALL_NOTOC.
+       (is_plt_seq_reloc): Add R_PPC64_PLT_PCREL34,
+       R_PPC64_PLT_PCREL34_NOTOC, and R_PPC64_PLTSEQ_NOTOC.
+       (ppc64_elf_check_relocs): Handle pcrel got and plt relocs.  Set
+       has_pltcall for section on seeing R_PPC64_PLTCALL_NOTOC.  Handle
+       possible need for dynamic relocs on non-pcrel powerxx relocs.
+       (dec_dynrel_count): Handle non-pcrel powerxx relocs.
+       (ppc64_elf_inline_plt): Handle R_PPC64_PLTCALL_NOTOC.
+       (toc_adjusting_stub_needed): Likewise.
+       (ppc64_elf_tls_optimize): Handle R_PPC64_PLTSEQ_NOTOC.
+       (ppc64_elf_relocate_section): Handle new powerxx relocs.
+       * bfd-in2.h: Regenerate.
+       * libbfd.h: Regenerate.
+
 2019-05-23  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * config.bfd (targ_cpu): Process bpf-*-none only if BFD64.
index 03d644c61e2d727a8988ed6d8bbd7fb8256ca42a..450c7b7fb18ba45354ca80ffae08b067474bfd49 100644 (file)
@@ -3498,6 +3498,23 @@ instruction.  */
   BFD_RELOC_PPC64_ADDR64_LOCAL,
   BFD_RELOC_PPC64_ENTRY,
   BFD_RELOC_PPC64_REL24_NOTOC,
+  BFD_RELOC_PPC64_D34,
+  BFD_RELOC_PPC64_D34_LO,
+  BFD_RELOC_PPC64_D34_HI30,
+  BFD_RELOC_PPC64_D34_HA30,
+  BFD_RELOC_PPC64_PCREL34,
+  BFD_RELOC_PPC64_GOT_PCREL34,
+  BFD_RELOC_PPC64_PLT_PCREL34,
+  BFD_RELOC_PPC64_ADDR16_HIGHER34,
+  BFD_RELOC_PPC64_ADDR16_HIGHERA34,
+  BFD_RELOC_PPC64_ADDR16_HIGHEST34,
+  BFD_RELOC_PPC64_ADDR16_HIGHESTA34,
+  BFD_RELOC_PPC64_REL16_HIGHER34,
+  BFD_RELOC_PPC64_REL16_HIGHERA34,
+  BFD_RELOC_PPC64_REL16_HIGHEST34,
+  BFD_RELOC_PPC64_REL16_HIGHESTA34,
+  BFD_RELOC_PPC64_D28,
+  BFD_RELOC_PPC64_PCREL28,
 
 /* PowerPC and PowerPC64 thread-local storage relocations.  */
   BFD_RELOC_PPC_TLS,
index 4eb0153dfba3fff4d56568a8f6ea25bb16622f75..ad47bed372dd0ffaa203a3f8a9866514d6a007f3 100644 (file)
@@ -51,6 +51,8 @@ static bfd_reloc_status_type ppc64_elf_toc_ha_reloc
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
 static bfd_reloc_status_type ppc64_elf_toc64_reloc
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+static bfd_reloc_status_type ppc64_elf_prefix_reloc
+  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
 static bfd_reloc_status_type ppc64_elf_unhandled_reloc
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
 static bfd_vma opd_entry_value
@@ -197,6 +199,7 @@ static bfd_vma opd_entry_value
 #define SLDI_R12_R12_32        0x799c07c6      /* sldi  %r12,%r12,32     */
 #define LDX_R12_R11_R12 0x7d8b602a     /* ldx   %r12,%r11,%r12   */
 #define ADD_R12_R11_R12 0x7d8b6214     /* add   %r12,%r11,%r12   */
+#define PNOP           0x0700000000000000ULL
 
 /* __glink_PLTresolve stub instructions.  We enter with the index in R0.  */
 #define GLINK_PLTRESOLVE_SIZE(htab)                    \
@@ -878,6 +881,69 @@ static reloc_howto_type ppc64_elf_howto_raw[] =
   HOW (R_PPC64_ADDR64_LOCAL, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
        bfd_elf_generic_reloc),
 
+  HOW (R_PPC64_PLTSEQ_NOTOC, 2, 32, 0, 0, FALSE, dont,
+       bfd_elf_generic_reloc),
+
+  HOW (R_PPC64_PLTCALL_NOTOC, 2, 32, 0, 0, FALSE, dont,
+       bfd_elf_generic_reloc),
+
+  HOW (R_PPC64_PCREL_OPT, 2, 32, 0, 0, FALSE, dont,
+       bfd_elf_generic_reloc),
+
+  HOW (R_PPC64_D34, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, signed,
+       ppc64_elf_prefix_reloc),
+
+  HOW (R_PPC64_D34_LO, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, dont,
+       ppc64_elf_prefix_reloc),
+
+  HOW (R_PPC64_D34_HI30, 4, 34, 0x3ffff0000ffffULL, 34, FALSE, dont,
+       ppc64_elf_prefix_reloc),
+
+  HOW (R_PPC64_D34_HA30, 4, 34, 0x3ffff0000ffffULL, 34, FALSE, dont,
+       ppc64_elf_prefix_reloc),
+
+  HOW (R_PPC64_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+       ppc64_elf_prefix_reloc),
+
+  HOW (R_PPC64_GOT_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+       ppc64_elf_unhandled_reloc),
+
+  HOW (R_PPC64_PLT_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+       ppc64_elf_unhandled_reloc),
+
+  HOW (R_PPC64_PLT_PCREL34_NOTOC, 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),
+
+  HOW (R_PPC64_ADDR16_HIGHERA34, 1, 16, 0xffff, 34, FALSE, dont,
+       ppc64_elf_ha_reloc),
+
+  HOW (R_PPC64_ADDR16_HIGHEST34, 1, 16, 0xffff, 50, FALSE, dont,
+       bfd_elf_generic_reloc),
+
+  HOW (R_PPC64_ADDR16_HIGHESTA34, 1, 16, 0xffff, 50, FALSE, dont,
+       ppc64_elf_ha_reloc),
+
+  HOW (R_PPC64_REL16_HIGHER34, 1, 16, 0xffff, 34, TRUE, dont,
+       bfd_elf_generic_reloc),
+
+  HOW (R_PPC64_REL16_HIGHERA34, 1, 16, 0xffff, 34, TRUE, dont,
+       ppc64_elf_ha_reloc),
+
+  HOW (R_PPC64_REL16_HIGHEST34, 1, 16, 0xffff, 50, TRUE, dont,
+       bfd_elf_generic_reloc),
+
+  HOW (R_PPC64_REL16_HIGHESTA34, 1, 16, 0xffff, 50, TRUE, dont,
+       ppc64_elf_ha_reloc),
+
+  HOW (R_PPC64_D28, 4, 28, 0xfff0000ffffULL, 0, FALSE, signed,
+       ppc64_elf_prefix_reloc),
+
+  HOW (R_PPC64_PCREL28, 4, 28, 0xfff0000ffffULL, 0, TRUE, signed,
+       ppc64_elf_prefix_reloc),
+
   /* GNU extension to record C++ vtable hierarchy.  */
   HOW (R_PPC64_GNU_VTINHERIT, 0, 0, 0, 0, FALSE, dont,
        NULL),
@@ -1167,6 +1233,40 @@ ppc64_elf_reloc_type_lookup (bfd *abfd,
       break;
     case BFD_RELOC_PPC64_ADDR64_LOCAL:         r = R_PPC64_ADDR64_LOCAL;
       break;
+    case BFD_RELOC_PPC64_D34:                  r = R_PPC64_D34;
+      break;
+    case BFD_RELOC_PPC64_D34_LO:               r = R_PPC64_D34_LO;
+      break;
+    case BFD_RELOC_PPC64_D34_HI30:             r = R_PPC64_D34_HI30;
+      break;
+    case BFD_RELOC_PPC64_D34_HA30:             r = R_PPC64_D34_HA30;
+      break;
+    case BFD_RELOC_PPC64_PCREL34:              r = R_PPC64_PCREL34;
+      break;
+    case BFD_RELOC_PPC64_GOT_PCREL34:          r = R_PPC64_GOT_PCREL34;
+      break;
+    case BFD_RELOC_PPC64_PLT_PCREL34:          r = R_PPC64_PLT_PCREL34;
+      break;
+    case BFD_RELOC_PPC64_ADDR16_HIGHER34:      r = R_PPC64_ADDR16_HIGHER34;
+      break;
+    case BFD_RELOC_PPC64_ADDR16_HIGHERA34:     r = R_PPC64_ADDR16_HIGHERA34;
+      break;
+    case BFD_RELOC_PPC64_ADDR16_HIGHEST34:     r = R_PPC64_ADDR16_HIGHEST34;
+      break;
+    case BFD_RELOC_PPC64_ADDR16_HIGHESTA34:    r = R_PPC64_ADDR16_HIGHESTA34;
+      break;
+    case BFD_RELOC_PPC64_REL16_HIGHER34:       r = R_PPC64_REL16_HIGHER34;
+      break;
+    case BFD_RELOC_PPC64_REL16_HIGHERA34:      r = R_PPC64_REL16_HIGHERA34;
+      break;
+    case BFD_RELOC_PPC64_REL16_HIGHEST34:      r = R_PPC64_REL16_HIGHEST34;
+      break;
+    case BFD_RELOC_PPC64_REL16_HIGHESTA34:     r = R_PPC64_REL16_HIGHESTA34;
+      break;
+    case BFD_RELOC_PPC64_D28:                  r = R_PPC64_D28;
+      break;
+    case BFD_RELOC_PPC64_PCREL28:              r = R_PPC64_PCREL28;
+      break;
     case BFD_RELOC_VTABLE_INHERIT:             r = R_PPC64_GNU_VTINHERIT;
       break;
     case BFD_RELOC_VTABLE_ENTRY:               r = R_PPC64_GNU_VTENTRY;
@@ -1243,11 +1343,17 @@ ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
                                  input_section, output_bfd, error_message);
 
-  /* Adjust the addend for sign extension of the low 16 bits.
-     We won't actually be using the low 16 bits, so trashing them
+  /* Adjust the addend for sign extension of the low 16 (or 34) bits.
+     We won't actually be using the low bits, so trashing them
      doesn't matter.  */
-  reloc_entry->addend += 0x8000;
   r_type = reloc_entry->howto->type;
+  if (r_type == R_PPC64_ADDR16_HIGHERA34
+      || r_type == R_PPC64_ADDR16_HIGHESTA34
+      || r_type == R_PPC64_REL16_HIGHERA34
+      || r_type == R_PPC64_REL16_HIGHESTA34)
+    reloc_entry->addend += 1ULL << 33;
+  else
+    reloc_entry->addend += 1U << 15;
   if (r_type != R_PPC64_REL16DX_HA)
     return bfd_reloc_continue;
 
@@ -1492,6 +1598,48 @@ ppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
   return bfd_reloc_ok;
 }
 
+static bfd_reloc_status_type
+ppc64_elf_prefix_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+                       void *data, asection *input_section,
+                       bfd *output_bfd, char **error_message)
+{
+  uint64_t insn;
+  bfd_vma targ;
+
+  if (output_bfd != NULL)
+    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+                                 input_section, output_bfd, error_message);
+
+  insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+  insn <<= 32;
+  insn |= bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address + 4);
+
+  targ = (symbol->section->output_section->vma
+         + symbol->section->output_offset
+         + reloc_entry->addend);
+  if (!bfd_is_com_section (symbol->section))
+    targ += symbol->value;
+  if (reloc_entry->howto->type == R_PPC64_D34_HA30)
+    targ += 1ULL << 33;
+  if (reloc_entry->howto->pc_relative)
+    {
+      bfd_vma from = (reloc_entry->address
+                     + input_section->output_offset
+                     + input_section->output_section->vma);
+      targ -=from;
+    }
+  targ >>= reloc_entry->howto->rightshift;
+  insn &= ~reloc_entry->howto->dst_mask;
+  insn |= ((targ << 16) | (targ & 0xffff)) & reloc_entry->howto->dst_mask;
+  bfd_put_32 (abfd, insn >> 32, (bfd_byte *) data + reloc_entry->address);
+  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address + 4);
+  if (reloc_entry->howto->complain_on_overflow == complain_overflow_signed
+      && (targ + (1ULL << (reloc_entry->howto->bitsize - 1))
+         >= 1ULL << reloc_entry->howto->bitsize))
+    return bfd_reloc_overflow;
+  return bfd_reloc_ok;
+}
+
 static bfd_reloc_status_type
 ppc64_elf_unhandled_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
                           void *data, asection *input_section,
@@ -2981,6 +3129,9 @@ struct ppc_link_hash_table
   /* Whether plt calls for ELFv2 localentry:0 funcs have been optimized.  */
   unsigned int has_plt_localentry0:1;
 
+  /* Whether calls are made via the PLT from NOTOC functions.  */
+  unsigned int notoc_plt:1;
+
   /* Incremented every time we size stubs.  */
   unsigned int stub_iteration;
 
@@ -4235,7 +4386,8 @@ is_branch_reloc (enum elf_ppc64_reloc_type r_type)
          || r_type == R_PPC64_ADDR14
          || r_type == R_PPC64_ADDR14_BRTAKEN
          || r_type == R_PPC64_ADDR14_BRNTAKEN
-         || r_type == R_PPC64_PLTCALL);
+         || r_type == R_PPC64_PLTCALL
+         || r_type == R_PPC64_PLTCALL_NOTOC);
 }
 
 /* Relocs on inline plt call sequence insns prior to the call.  */
@@ -4247,7 +4399,10 @@ is_plt_seq_reloc (enum elf_ppc64_reloc_type r_type)
          || r_type == R_PPC64_PLT16_HI
          || r_type == R_PPC64_PLT16_LO
          || r_type == R_PPC64_PLT16_LO_DS
-         || r_type == R_PPC64_PLTSEQ);
+         || r_type == R_PPC64_PLT_PCREL34
+         || r_type == R_PPC64_PLT_PCREL34_NOTOC
+         || r_type == R_PPC64_PLTSEQ
+         || r_type == R_PPC64_PLTSEQ_NOTOC);
 }
 
 /* Look through the relocs for a section during the first phase, and
@@ -4302,6 +4457,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       int tls_type;
       struct _ppc64_elf_section_data *ppc64_sec;
       struct plt_entry **ifunc, **plt_list;
+      bfd_vma sym_addend;
 
       r_symndx = ELF64_R_SYM (rel->r_info);
       if (r_symndx < symtab_hdr->sh_info)
@@ -4317,6 +4473,24 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
       tls_type = 0;
       ifunc = NULL;
+      r_type = ELF64_R_TYPE (rel->r_info);
+      switch (r_type)
+       {
+       default:
+         /* Somewhat foolishly, because the ABIs don't specifically
+            allow it, ppc64 gas and ld support GOT and PLT relocs
+            with non-zero addends where the addend results in
+            sym+addend being stored in the GOT or PLT entry.  This
+            can't be supported for pcrel relocs because the addend is
+            used to specify the pcrel offset.  */
+         sym_addend = rel->r_addend;
+         break;
+       case R_PPC64_GOT_PCREL34:
+       case R_PPC64_PLT_PCREL34:
+       case R_PPC64_PLT_PCREL34_NOTOC:
+         sym_addend = 0;
+         break;
+       }
       if (h != NULL)
        {
          if (h->type == STT_GNU_IFUNC)
@@ -4335,14 +4509,13 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
              ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx,
-                                            rel->r_addend,
+                                            sym_addend,
                                             NON_GOT | PLT_IFUNC);
              if (ifunc == NULL)
                return FALSE;
            }
        }
 
-      r_type = ELF64_R_TYPE (rel->r_info);
       switch (r_type)
        {
        case R_PPC64_TLSGD:
@@ -4353,7 +4526,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            ((struct ppc_link_hash_entry *) h)->tls_mask |= TLS_TLS | TLS_MARK;
          else
            if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
-                                       rel->r_addend,
+                                       sym_addend,
                                        NON_GOT | TLS_TLS | TLS_MARK))
              return FALSE;
          sec->has_tls_reloc = 1;
@@ -4401,6 +4574,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_GOT16:
        case R_PPC64_GOT16_HI:
        case R_PPC64_GOT16_LO:
+       case R_PPC64_GOT_PCREL34:
        dogot:
          /* This symbol requires a global offset table entry.  */
          sec->has_toc_reloc = 1;
@@ -4426,7 +4600,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
              eh = (struct ppc_link_hash_entry *) h;
              for (ent = eh->elf.got.glist; ent != NULL; ent = ent->next)
-               if (ent->addend == rel->r_addend
+               if (ent->addend == sym_addend
                    && ent->owner == abfd
                    && ent->tls_type == tls_type)
                  break;
@@ -4437,7 +4611,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  if (ent == NULL)
                    return FALSE;
                  ent->next = eh->elf.got.glist;
-                 ent->addend = rel->r_addend;
+                 ent->addend = sym_addend;
                  ent->owner = abfd;
                  ent->tls_type = tls_type;
                  ent->is_indirect = FALSE;
@@ -4450,14 +4624,14 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          else
            /* This is a global offset table entry for a local symbol.  */
            if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
-                                       rel->r_addend, tls_type))
+                                       sym_addend, tls_type))
              return FALSE;
 
          /* We may also need a plt entry if the symbol turns out to be
             an ifunc.  */
          if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1)
            {
-             if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
+             if (!update_plt_info (abfd, &h->plt.plist, sym_addend))
                return FALSE;
            }
          break;
@@ -4466,6 +4640,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_PLT16_HI:
        case R_PPC64_PLT16_LO:
        case R_PPC64_PLT16_LO_DS:
+       case R_PPC64_PLT_PCREL34:
+       case R_PPC64_PLT_PCREL34_NOTOC:
        case R_PPC64_PLT32:
        case R_PPC64_PLT64:
          /* This symbol requires a procedure linkage table entry.  */
@@ -4481,9 +4657,9 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            }
          if (plt_list == NULL)
            plt_list = update_local_sym_info (abfd, symtab_hdr, r_symndx,
-                                             rel->r_addend,
+                                             sym_addend,
                                              NON_GOT | PLT_KEEP);
-         if (!update_plt_info (abfd, plt_list, rel->r_addend))
+         if (!update_plt_info (abfd, plt_list, sym_addend))
            return FALSE;
          break;
 
@@ -4521,6 +4697,10 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_REL16_HIGHERA:
        case R_PPC64_REL16_HIGHEST:
        case R_PPC64_REL16_HIGHESTA:
+       case R_PPC64_REL16_HIGHER34:
+       case R_PPC64_REL16_HIGHERA34:
+       case R_PPC64_REL16_HIGHEST34:
+       case R_PPC64_REL16_HIGHESTA34:
        case R_PPC64_REL16DX_HA:
          break;
 
@@ -4603,6 +4783,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          goto rel24;
 
        case R_PPC64_PLTCALL:
+       case R_PPC64_PLTCALL_NOTOC:
          ppc64_elf_section_data (sec)->has_pltcall = 1;
          /* Fall through.  */
 
@@ -4636,7 +4817,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          /* We may need a .plt entry if the function this reloc
             refers to is in a shared lib.  */
          if (plt_list
-             && !update_plt_info (abfd, plt_list, rel->r_addend))
+             && !update_plt_info (abfd, plt_list, sym_addend))
            return FALSE;
          break;
 
@@ -4680,7 +4861,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            }
          else
            if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
-                                       rel->r_addend, tls_type))
+                                       sym_addend, tls_type))
              return FALSE;
 
          ppc64_sec = ppc64_elf_section_data (sec);
@@ -4702,7 +4883,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            }
          BFD_ASSERT (rel->r_offset % 8 == 0);
          ppc64_sec->u.toc.symndx[rel->r_offset / 8] = r_symndx;
-         ppc64_sec->u.toc.add[rel->r_offset / 8] = rel->r_addend;
+         ppc64_sec->u.toc.add[rel->r_offset / 8] = sym_addend;
 
          /* Mark the second slot of a GD or LD entry.
             -1 to indicate GD and -2 to indicate LD.  */
@@ -4750,12 +4931,21 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_ADDR16_HIGHESTA:
        case R_PPC64_ADDR16_LO:
        case R_PPC64_ADDR16_LO_DS:
+       case R_PPC64_D34:
+       case R_PPC64_D34_LO:
+       case R_PPC64_D34_HI30:
+       case R_PPC64_D34_HA30:
+       case R_PPC64_ADDR16_HIGHER34:
+       case R_PPC64_ADDR16_HIGHERA34:
+       case R_PPC64_ADDR16_HIGHEST34:
+       case R_PPC64_ADDR16_HIGHESTA34:
+       case R_PPC64_D28:
          if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1
              && rel->r_addend == 0)
            {
              /* We may need a .plt entry if this reloc refers to a
                 function in a shared lib.  */
-             if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
+             if (!update_plt_info (abfd, &h->plt.plist, 0))
                return FALSE;
              h->pointer_equality_needed = 1;
            }
@@ -6562,6 +6752,15 @@ dec_dynrel_count (bfd_vma r_info,
     case R_PPC64_UADDR32:
     case R_PPC64_UADDR64:
     case R_PPC64_TOC:
+    case R_PPC64_D34:
+    case R_PPC64_D34_LO:
+    case R_PPC64_D34_HI30:
+    case R_PPC64_D34_HA30:
+    case R_PPC64_ADDR16_HIGHER34:
+    case R_PPC64_ADDR16_HIGHERA34:
+    case R_PPC64_ADDR16_HIGHEST34:
+    case R_PPC64_ADDR16_HIGHESTA34:
+    case R_PPC64_D28:
       break;
     }
 
@@ -7167,7 +7366,8 @@ ppc64_elf_inline_plt (struct bfd_link_info *info)
                unsigned char *tls_maskp;
 
                r_type = ELF64_R_TYPE (rel->r_info);
-               if (r_type != R_PPC64_PLTCALL)
+               if (r_type != R_PPC64_PLTCALL
+                   && r_type != R_PPC64_PLTCALL_NOTOC)
                  continue;
 
                r_symndx = ELF64_R_SYM (rel->r_info);
@@ -7195,7 +7395,11 @@ ppc64_elf_inline_plt (struct bfd_link_info *info)
                    from = (rel->r_offset
                            + sec->output_offset
                            + sec->output_section->vma);
-                   if (to - from + limit < 2 * limit)
+                   if (to - from + limit < 2 * limit
+                       && !(r_type == R_PPC64_PLTCALL_NOTOC
+                            && (((h ? h->other : sym->st_other)
+                                 & STO_PPC64_LOCAL_MASK)
+                                != 1 << STO_PPC64_LOCAL_BIT)))
                      *tls_maskp &= ~PLT_KEEP;
                  }
              }
@@ -7574,7 +7778,9 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                        {
                          if (pass != 0
                              && (ELF64_R_TYPE (rel[1].r_info)
-                                 != R_PPC64_PLTSEQ))
+                                 != R_PPC64_PLTSEQ)
+                             && (ELF64_R_TYPE (rel[1].r_info)
+                                 != R_PPC64_PLTSEQ_NOTOC))
                            {
                              r_symndx = ELF64_R_SYM (rel[1].r_info);
                              if (!get_sym_h (&h, NULL, NULL, NULL, &locsyms,
@@ -11631,7 +11837,8 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
              && r_type != R_PPC64_REL14
              && r_type != R_PPC64_REL14_BRTAKEN
              && r_type != R_PPC64_REL14_BRNTAKEN
-             && r_type != R_PPC64_PLTCALL)
+             && r_type != R_PPC64_PLTCALL
+             && r_type != R_PPC64_PLTCALL_NOTOC)
            continue;
 
          r_symndx = ELF64_R_SYM (rel->r_info);
@@ -14030,10 +14237,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            {
              unsigned int insn2;
              bfd_vma offset = rel->r_offset;
+             enum elf_ppc64_reloc_type r_type1 = ELF64_R_TYPE (rel[1].r_info);
 
-             if (is_plt_seq_reloc (ELF64_R_TYPE (rel[1].r_info)))
+             if (is_plt_seq_reloc (r_type1))
                {
                  bfd_put_32 (output_bfd, NOP, contents + offset);
+                 if (r_type1 == R_PPC64_PLT_PCREL34
+                     || r_type1 == R_PPC64_PLT_PCREL34_NOTOC)
+                   bfd_put_32 (output_bfd, NOP, contents + offset + 4);
                  rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_PPC64_NONE);
                  break;
                }
@@ -14075,10 +14286,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            {
              unsigned int insn2;
              bfd_vma offset = rel->r_offset;
+             enum elf_ppc64_reloc_type r_type1 = ELF64_R_TYPE (rel[1].r_info);
 
-             if (is_plt_seq_reloc (ELF64_R_TYPE (rel[1].r_info)))
+             if (is_plt_seq_reloc (r_type1))
                {
                  bfd_put_32 (output_bfd, NOP, contents + offset);
+                 if (r_type1 == R_PPC64_PLT_PCREL34
+                     || r_type1 == R_PPC64_PLT_PCREL34_NOTOC)
+                   bfd_put_32 (output_bfd, NOP, contents + offset + 4);
                  rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_PPC64_NONE);
                  break;
                }
@@ -14279,6 +14494,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_REL24:
        case R_PPC64_REL24_NOTOC:
        case R_PPC64_PLTCALL:
+       case R_PPC64_PLTCALL_NOTOC:
          /* Calls to functions with a different TOC, such as calls to
             shared objects, need to alter the TOC pointer.  This is
             done using a linkage stub.  A REL24 branching to these
@@ -14292,7 +14508,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            fdh = ppc_follow_link (h->oh);
          stub_entry = ppc_get_stub_entry (input_section, sec, fdh, &orig_rel,
                                           htab);
-         if (r_type == R_PPC64_PLTCALL
+         if ((r_type == R_PPC64_PLTCALL
+              || r_type == R_PPC64_PLTCALL_NOTOC)
              && stub_entry != NULL
              && stub_entry->stub_type >= ppc_stub_plt_call
              && stub_entry->stub_type <= ppc_stub_plt_call_both)
@@ -14522,6 +14739,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                        || stub_entry->stub_type == ppc_stub_plt_call_both)
                       && r_type == R_PPC64_REL24_NOTOC)
                relocation += 4;
+
+             if (r_type == R_PPC64_REL24_NOTOC
+                 && (stub_entry->stub_type == ppc_stub_plt_call_notoc
+                     || stub_entry->stub_type == ppc_stub_plt_call_both))
+               htab->notoc_plt = 1;
            }
 
          if (insn != 0)
@@ -14665,6 +14887,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_GOT16_HA:
        case R_PPC64_GOT16_DS:
        case R_PPC64_GOT16_LO_DS:
+       case R_PPC64_GOT_PCREL34:
        dogot:
          {
            /* Relocation is to the entry for this symbol in the global
@@ -14674,6 +14897,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            bfd_vma off;
            unsigned long indx = 0;
            struct got_entry *ent;
+           bfd_vma sym_addend = orig_rel.r_addend;
+
+           if (r_type == R_PPC64_GOT_PCREL34)
+             sym_addend = 0;
 
            if (tls_type == (TLS_TLS | TLS_LD)
                && (h == NULL
@@ -14707,7 +14934,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  }
 
                for (; ent != NULL; ent = ent->next)
-                 if (ent->addend == orig_rel.r_addend
+                 if (ent->addend == sym_addend
                      && ent->owner == input_bfd
                      && ent->tls_type == tls_type)
                    break;
@@ -14764,7 +14991,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                    outrel.r_offset = (got->output_section->vma
                                       + got->output_offset
                                       + off);
-                   outrel.r_addend = addend;
+                   outrel.r_addend = sym_addend;
                    if (tls_type & (TLS_LD | TLS_GD))
                      {
                        outrel.r_addend = 0;
@@ -14777,7 +15004,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                            bfd_elf64_swap_reloca_out (output_bfd,
                                                       &outrel, loc);
                            outrel.r_offset += 8;
-                           outrel.r_addend = addend;
+                           outrel.r_addend = sym_addend;
                            outrel.r_info
                              = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
                          }
@@ -14823,7 +15050,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                   emitting a reloc.  */
                else
                  {
-                   relocation += addend;
+                   relocation += sym_addend;
                    if (tls_type != 0)
                      {
                        if (htab->elf.tls_sec == NULL)
@@ -14854,7 +15081,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              abort ();
 
            relocation = got->output_section->vma + got->output_offset + off;
-           addend = -(TOCstart + htab->sec_info[input_section->id].toc_off);
+           if (r_type != R_PPC64_GOT_PCREL34)
+             addend = -(TOCstart + htab->sec_info[input_section->id].toc_off);
          }
          break;
 
@@ -14862,10 +15090,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_PLT16_HI:
        case R_PPC64_PLT16_LO:
        case R_PPC64_PLT16_LO_DS:
+       case R_PPC64_PLT_PCREL34:
+       case R_PPC64_PLT_PCREL34_NOTOC:
        case R_PPC64_PLT32:
        case R_PPC64_PLT64:
        case R_PPC64_PLTSEQ:
+       case R_PPC64_PLTSEQ_NOTOC:
        case R_PPC64_PLTCALL:
+       case R_PPC64_PLTCALL_NOTOC:
          /* Relocation is to the entry for this symbol in the
             procedure linkage table.  */
          unresolved_reloc = TRUE;
@@ -14882,10 +15114,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            if (plt_list)
              {
                struct plt_entry *ent;
+               bfd_vma sym_addend = orig_rel.r_addend;
+
+               if (r_type == R_PPC64_PLT_PCREL34
+                   || r_type == R_PPC64_PLT_PCREL34_NOTOC)
+                 sym_addend = 0;
 
                for (ent = *plt_list; ent != NULL; ent = ent->next)
                  if (ent->plt.offset != (bfd_vma) -1
-                     && ent->addend == orig_rel.r_addend)
+                     && ent->addend == sym_addend)
                    {
                      asection *plt;
                      bfd_vma got;
@@ -14914,7 +15151,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                                 + htab->sec_info[input_section->id].toc_off);
                          relocation -= got;
                        }
-                     addend = 0;
+                     if (r_type != R_PPC64_PLT_PCREL34
+                         && r_type != R_PPC64_PLT_PCREL34_NOTOC)
+                       addend = 0;
                      unresolved_reloc = FALSE;
                      break;
                    }
@@ -14969,14 +15208,18 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_REL16_HIGHERA:
        case R_PPC64_REL16_HIGHEST:
        case R_PPC64_REL16_HIGHESTA:
+       case R_PPC64_REL16_HIGHER34:
+       case R_PPC64_REL16_HIGHERA34:
+       case R_PPC64_REL16_HIGHEST34:
+       case R_PPC64_REL16_HIGHESTA34:
        case R_PPC64_REL16DX_HA:
-         break;
-
        case R_PPC64_REL14:
        case R_PPC64_REL14_BRNTAKEN:
        case R_PPC64_REL14_BRTAKEN:
        case R_PPC64_REL24:
        case R_PPC64_REL24_NOTOC:
+       case R_PPC64_PCREL34:
+       case R_PPC64_PCREL28:
          break;
 
        case R_PPC64_TPREL16:
@@ -15071,12 +15314,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_ADDR16_HIGHESTA:
        case R_PPC64_ADDR16_LO:
        case R_PPC64_ADDR16_LO_DS:
+       case R_PPC64_ADDR16_HIGHER34:
+       case R_PPC64_ADDR16_HIGHERA34:
+       case R_PPC64_ADDR16_HIGHEST34:
+       case R_PPC64_ADDR16_HIGHESTA34:
        case R_PPC64_ADDR24:
        case R_PPC64_ADDR32:
        case R_PPC64_ADDR64:
        case R_PPC64_UADDR16:
        case R_PPC64_UADDR32:
        case R_PPC64_UADDR64:
+       case R_PPC64_D34:
+       case R_PPC64_D34_LO:
+       case R_PPC64_D34_HI30:
+       case R_PPC64_D34_HA30:
+       case R_PPC64_D28:
        dodyn:
          if ((input_section->flags & SEC_ALLOC) == 0)
            break;
@@ -15328,6 +15580,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
             insn.  */
          break;
 
+       case R_PPC64_PLTCALL_NOTOC:
+         if (!unresolved_reloc)
+           htab->notoc_plt = 1;
+         /* Fall through.  */
        case R_PPC64_PLTCALL:
          if (unresolved_reloc)
            {
@@ -15336,12 +15592,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              insn = bfd_get_32 (input_bfd, p);
              insn &= 1;
              bfd_put_32 (input_bfd, B_DOT | insn, p);
-             bfd_put_32 (input_bfd, NOP, p + 4);
+             if (r_type == R_PPC64_PLTCALL)
+               bfd_put_32 (input_bfd, NOP, p + 4);
              unresolved_reloc = save_unresolved_reloc;
              r_type = R_PPC64_REL24;
            }
          break;
 
+       case R_PPC64_PLTSEQ_NOTOC:
        case R_PPC64_PLTSEQ:
          if (unresolved_reloc)
            {
@@ -15350,6 +15608,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            }
          break;
 
+       case R_PPC64_PLT_PCREL34_NOTOC:
+         if (!unresolved_reloc)
+           htab->notoc_plt = 1;
+         /* Fall through.  */
+       case R_PPC64_PLT_PCREL34:
+         if (unresolved_reloc)
+           {
+             bfd_byte *p = contents + rel->r_offset;
+             bfd_put_32 (input_bfd, PNOP >> 32, p);
+             bfd_put_32 (input_bfd, PNOP, p + 4);
+             unresolved_reloc = FALSE;
+             goto copy_reloc;
+           }
+         break;
+
        case R_PPC64_PLT16_HA:
          if (unresolved_reloc)
            {
@@ -15488,6 +15761,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          addend += 0x8000;
          break;
 
+       case R_PPC64_D34_HA30:
+       case R_PPC64_ADDR16_HIGHERA34:
+       case R_PPC64_ADDR16_HIGHESTA34:
+       case R_PPC64_REL16_HIGHERA34:
+       case R_PPC64_REL16_HIGHESTA34:
+         if (sec != NULL)
+           addend += 1ULL << 33;
+         break;
+
        case R_PPC64_ADDR16_DS:
        case R_PPC64_ADDR16_LO_DS:
        case R_PPC64_GOT16_DS:
@@ -15583,9 +15865,50 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            }
        }
 
-      if (r_type == R_PPC64_REL16DX_HA)
+      switch (r_type)
        {
-         /* Split field reloc isn't handled by _bfd_final_link_relocate.  */
+         /* Split field relocs aren't handled by _bfd_final_link_relocate.  */
+       case R_PPC64_D34:
+       case R_PPC64_D34_LO:
+       case R_PPC64_D34_HI30:
+       case R_PPC64_D34_HA30:
+       case R_PPC64_PCREL34:
+       case R_PPC64_GOT_PCREL34:
+       case R_PPC64_PLT_PCREL34:
+       case R_PPC64_PLT_PCREL34_NOTOC:
+       case R_PPC64_D28:
+       case R_PPC64_PCREL28:
+         if (rel->r_offset + 8 > input_section->size)
+           r = bfd_reloc_outofrange;
+         else
+           {
+             uint64_t pinsn;
+
+             relocation += addend;
+             if (howto->pc_relative)
+               relocation -= (rel->r_offset
+                              + input_section->output_offset
+                              + input_section->output_section->vma);
+             relocation >>= howto->rightshift;
+
+             pinsn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+             pinsn <<= 32;
+             pinsn |= bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+
+             pinsn &= ~howto->dst_mask;
+             pinsn |= (((relocation << 16) | (relocation & 0xffff))
+                       & howto->dst_mask);
+             bfd_put_32 (input_bfd, pinsn >> 32, contents + rel->r_offset);
+             bfd_put_32 (input_bfd, pinsn, contents + rel->r_offset + 4);
+             r = bfd_reloc_ok;
+             if (howto->complain_on_overflow == complain_overflow_signed
+                 && (relocation + (1ULL << (howto->bitsize - 1))
+                     >= 1ULL << howto->bitsize))
+               r = bfd_reloc_overflow;
+           }
+         break;
+
+       case R_PPC64_REL16DX_HA:
          if (rel->r_offset + 4 > input_section->size)
            r = bfd_reloc_outofrange;
          else
@@ -15603,10 +15926,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              if (relocation + 0x8000 > 0xffff)
                r = bfd_reloc_overflow;
            }
+         break;
+
+       default:
+         r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+                                       contents, rel->r_offset,
+                                       relocation, addend);
        }
-      else
-       r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
-                                     rel->r_offset, relocation, addend);
 
       if (r != bfd_reloc_ok)
        {
@@ -15884,7 +16210,8 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_PPC64_OPT:
-             if (htab->do_multi_toc && htab->multi_toc_needed)
+             if ((htab->do_multi_toc && htab->multi_toc_needed)
+                 || htab->notoc_plt)
                dyn.d_un.d_val |= PPC64_OPT_MULTI_TOC;
              if (htab->has_plt_localentry0)
                dyn.d_un.d_val |= PPC64_OPT_LOCALENTRY;
index da52a2b0982d96fe9532e98e8ac2c4bbcf64ad8e..ff6e0eaef4449cdb0b2c97050297c16cc78e4936 100644 (file)
@@ -1476,6 +1476,23 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_PPC64_ADDR64_LOCAL",
   "BFD_RELOC_PPC64_ENTRY",
   "BFD_RELOC_PPC64_REL24_NOTOC",
+  "BFD_RELOC_PPC64_D34",
+  "BFD_RELOC_PPC64_D34_LO",
+  "BFD_RELOC_PPC64_D34_HI30",
+  "BFD_RELOC_PPC64_D34_HA30",
+  "BFD_RELOC_PPC64_PCREL34",
+  "BFD_RELOC_PPC64_GOT_PCREL34",
+  "BFD_RELOC_PPC64_PLT_PCREL34",
+  "BFD_RELOC_PPC64_ADDR16_HIGHER34",
+  "BFD_RELOC_PPC64_ADDR16_HIGHERA34",
+  "BFD_RELOC_PPC64_ADDR16_HIGHEST34",
+  "BFD_RELOC_PPC64_ADDR16_HIGHESTA34",
+  "BFD_RELOC_PPC64_REL16_HIGHER34",
+  "BFD_RELOC_PPC64_REL16_HIGHERA34",
+  "BFD_RELOC_PPC64_REL16_HIGHEST34",
+  "BFD_RELOC_PPC64_REL16_HIGHESTA34",
+  "BFD_RELOC_PPC64_D28",
+  "BFD_RELOC_PPC64_PCREL28",
   "BFD_RELOC_PPC_TLS",
   "BFD_RELOC_PPC_TLSGD",
   "BFD_RELOC_PPC_TLSLD",
index 8f0263e35491dac5e561525e375f4a80ab1233e4..266e775fa4eeeae81f90f4558c86b985cc658280 100644 (file)
@@ -2878,6 +2878,40 @@ ENUMX
   BFD_RELOC_PPC64_ENTRY
 ENUMX
   BFD_RELOC_PPC64_REL24_NOTOC
+ENUMX
+  BFD_RELOC_PPC64_D34
+ENUMX
+  BFD_RELOC_PPC64_D34_LO
+ENUMX
+  BFD_RELOC_PPC64_D34_HI30
+ENUMX
+  BFD_RELOC_PPC64_D34_HA30
+ENUMX
+  BFD_RELOC_PPC64_PCREL34
+ENUMX
+  BFD_RELOC_PPC64_GOT_PCREL34
+ENUMX
+  BFD_RELOC_PPC64_PLT_PCREL34
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGHER34
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGHERA34
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGHEST34
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGHESTA34
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHER34
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHERA34
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHEST34
+ENUMX
+  BFD_RELOC_PPC64_REL16_HIGHESTA34
+ENUMX
+  BFD_RELOC_PPC64_D28
+ENUMX
+  BFD_RELOC_PPC64_PCREL28
 ENUMDOC
   Power(rs6000) and PowerPC relocations.
 
index 2d05746753fbad9a0453232f11cb007be50f362b..1caa4785dac937f6a3f8b9ca19b5348b4a9e253e 100644 (file)
@@ -1,3 +1,23 @@
+2019-05-24  Alan Modra  <amodra@gmail.com>
+
+       * config/tc-ppc.c (ppc_elf_suffix): Support @pcrel, @got@pcrel,
+       @plt@pcrel, @higher34, @highera34, @highest34, and @highesta34.
+       (fixup_size): Handle new powerxx relocs.
+       (md_assemble): Warn for @pcrel on non-prefix insns.
+       Accept @l, @h and @ha on prefix insns, and infer reloc without
+       any @ suffix.  Translate powerxx relocs to suit DQ and DS field
+       instructions.  Include operand tests as well as opcode test to
+       translate BFD_RELOC_HI16_S to BFD_RELOC_PPC_16DX_HA.
+       (ppc_fix_adjustable): Return false for pcrel GOT and PLT relocs.
+       (md_apply_fix): Handle new powerxx relocs.
+       * config/tc-ppc.h (TC_FORCE_RELOCATION_SUB_LOCAL): Accept
+       BFD_RELOC_PPC64_ADDR16_HIGHER34, BFD_RELOC_PPC64_ADDR16_HIGHERA34,
+       BFD_RELOC_PPC64_ADDR16_HIGHEST34, BFD_RELOC_PPC64_ADDR16_HIGHESTA34,
+       BFD_RELOC_PPC64_D34, and BFD_RELOC_PPC64_D28.
+       * testsuite/gas/ppc/prefix-reloc.d,
+       * testsuite/gas/ppc/prefix-reloc.s: New test.
+       * testsuite/gas/ppc/ppc.exp: Run it.
+
 2019-05-24  Peter Bergner  <bergner@linux.ibm.com>
            Alan Modra  <amodra@gmail.com>
 
index 4026c722939dd992ddbff29fe169ba62feebb502..64ff149b215a53af06224c4a2c93ccbe64e02a21 100644 (file)
@@ -2151,6 +2151,13 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
     MAP64 ("tprel@highest",    BFD_RELOC_PPC64_TPREL16_HIGHEST),
     MAP64 ("tprel@highesta",   BFD_RELOC_PPC64_TPREL16_HIGHESTA),
     MAP64 ("notoc",            BFD_RELOC_PPC64_REL24_NOTOC),
+    MAP64 ("pcrel",            BFD_RELOC_PPC64_PCREL34),
+    MAP64 ("got@pcrel",                BFD_RELOC_PPC64_GOT_PCREL34),
+    MAP64 ("plt@pcrel",                BFD_RELOC_PPC64_PLT_PCREL34),
+    MAP64 ("higher34",         BFD_RELOC_PPC64_ADDR16_HIGHER34),
+    MAP64 ("highera34",                BFD_RELOC_PPC64_ADDR16_HIGHERA34),
+    MAP64 ("highest34",                BFD_RELOC_PPC64_ADDR16_HIGHEST34),
+    MAP64 ("highesta34",       BFD_RELOC_PPC64_ADDR16_HIGHESTA34),
     { (char *) 0, 0, 0, 0,     BFD_RELOC_NONE }
   };
 
@@ -2931,6 +2938,10 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
     case BFD_RELOC_PPC64_ADDR16_DS:
     case BFD_RELOC_PPC64_ADDR16_HIGH:
     case BFD_RELOC_PPC64_ADDR16_HIGHA:
+    case BFD_RELOC_PPC64_ADDR16_HIGHER34:
+    case BFD_RELOC_PPC64_ADDR16_HIGHERA34:
+    case BFD_RELOC_PPC64_ADDR16_HIGHEST34:
+    case BFD_RELOC_PPC64_ADDR16_HIGHESTA34:
     case BFD_RELOC_PPC64_ADDR16_LO_DS:
     case BFD_RELOC_PPC64_DTPREL16_DS:
     case BFD_RELOC_PPC64_DTPREL16_HIGH:
@@ -3018,9 +3029,13 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
     case BFD_RELOC_PPC64_REL16_HIGH:
     case BFD_RELOC_PPC64_REL16_HIGHA:
     case BFD_RELOC_PPC64_REL16_HIGHER:
+    case BFD_RELOC_PPC64_REL16_HIGHER34:
     case BFD_RELOC_PPC64_REL16_HIGHERA:
+    case BFD_RELOC_PPC64_REL16_HIGHERA34:
     case BFD_RELOC_PPC64_REL16_HIGHEST:
+    case BFD_RELOC_PPC64_REL16_HIGHEST34:
     case BFD_RELOC_PPC64_REL16_HIGHESTA:
+    case BFD_RELOC_PPC64_REL16_HIGHESTA34:
 #ifdef OBJ_XCOFF
     case BFD_RELOC_PPC_B16:
 #endif
@@ -3100,12 +3115,21 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
     case BFD_RELOC_64:
     case BFD_RELOC_64_PLTOFF:
     case BFD_RELOC_PPC64_ADDR64_LOCAL:
+    case BFD_RELOC_PPC64_D28:
+    case BFD_RELOC_PPC64_D34:
+    case BFD_RELOC_PPC64_D34_LO:
+    case BFD_RELOC_PPC64_D34_HI30:
+    case BFD_RELOC_PPC64_D34_HA30:
     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_PCREL28:
+    case BFD_RELOC_PPC64_PCREL34:
+    case BFD_RELOC_PPC64_PLT_PCREL34:
       size = 8;
       pcrel = TRUE;
       break;
@@ -3665,24 +3689,47 @@ md_assemble (char *str)
                  reloc = BFD_RELOC_PPC_TPREL16;
                  break;
 
-               case BFD_RELOC_LO16:
-                 if ((operand->bitm | 0xf) != 0xffff
-                     || operand->shift != 0
+               case BFD_RELOC_PPC64_PCREL34:
+                 if (operand->bitm == 0xfffffffULL)
+                   {
+                     reloc = BFD_RELOC_PPC64_PCREL28;
+                     break;
+                   }
+                 /* Fall through.  */
+               case BFD_RELOC_PPC64_GOT_PCREL34:
+               case BFD_RELOC_PPC64_PLT_PCREL34:
+                 if (operand->bitm != 0x3ffffffffULL
                      || (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
+                   as_warn (_("%s unsupported on this instruction"), "@pcrel");
+                 break;
+
+               case BFD_RELOC_LO16:
+                 if (operand->bitm == 0x3ffffffffULL
+                     && (operand->flags & PPC_OPERAND_NEGATIVE) == 0)
+                   reloc = BFD_RELOC_PPC64_D34_LO;
+                 else if ((operand->bitm | 0xf) != 0xffff
+                          || operand->shift != 0
+                          || (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
                    as_warn (_("%s unsupported on this instruction"), "@l");
                  break;
 
                case BFD_RELOC_HI16:
-                 if (operand->bitm != 0xffff
-                     || operand->shift != 0
-                     || (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
+                 if (operand->bitm == 0x3ffffffffULL
+                     && (operand->flags & PPC_OPERAND_NEGATIVE) == 0)
+                   reloc = BFD_RELOC_PPC64_D34_HI30;
+                 else if (operand->bitm != 0xffff
+                          || operand->shift != 0
+                          || (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
                    as_warn (_("%s unsupported on this instruction"), "@h");
                  break;
 
                case BFD_RELOC_HI16_S:
-                 if (operand->bitm == 0xffff
-                     && operand->shift == (int) PPC_OPSHIFT_INV
-                     && opcode->opcode == (19 << 26) + (2 << 1))
+                 if (operand->bitm == 0x3ffffffffULL
+                     && (operand->flags & PPC_OPERAND_NEGATIVE) == 0)
+                   reloc = BFD_RELOC_PPC64_D34_HA30;
+                 else if (operand->bitm == 0xffff
+                          && operand->shift == (int) PPC_OPSHIFT_INV
+                          && opcode->opcode == (19 << 26) + (2 << 1))
                    /* addpcis.  */
                    reloc = BFD_RELOC_PPC_16DX_HA;
                  else if (operand->bitm != 0xffff
@@ -3738,6 +3785,10 @@ md_assemble (char *str)
                }
 #endif
            }
+         else if (operand->bitm == 0x3ffffffffULL)
+           reloc = BFD_RELOC_PPC64_D34;
+         else if (operand->bitm == 0xfffffffULL)
+           reloc = BFD_RELOC_PPC64_D28;
 
          /* For the absolute forms of branches, convert the PC
             relative form back into the absolute.  */
@@ -3787,53 +3838,69 @@ md_assemble (char *str)
                case BFD_RELOC_16:
                  reloc = BFD_RELOC_PPC64_ADDR16_DS;
                  break;
+
                case BFD_RELOC_LO16:
                  reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
                  break;
+
                case BFD_RELOC_16_GOTOFF:
                  reloc = BFD_RELOC_PPC64_GOT16_DS;
                  break;
+
                case BFD_RELOC_LO16_GOTOFF:
                  reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
                  break;
+
                case BFD_RELOC_LO16_PLTOFF:
                  reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
                  break;
+
                case BFD_RELOC_16_BASEREL:
                  reloc = BFD_RELOC_PPC64_SECTOFF_DS;
                  break;
+
                case BFD_RELOC_LO16_BASEREL:
                  reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
                  break;
+
                case BFD_RELOC_PPC_TOC16:
                  reloc = BFD_RELOC_PPC64_TOC16_DS;
                  break;
+
                case BFD_RELOC_PPC64_TOC16_LO:
                  reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
                  break;
+
                case BFD_RELOC_PPC64_PLTGOT16:
                  reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
                  break;
+
                case BFD_RELOC_PPC64_PLTGOT16_LO:
                  reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
                  break;
+
                case BFD_RELOC_PPC_DTPREL16:
                  reloc = BFD_RELOC_PPC64_DTPREL16_DS;
                  break;
+
                case BFD_RELOC_PPC_DTPREL16_LO:
                  reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
                  break;
+
                case BFD_RELOC_PPC_TPREL16:
                  reloc = BFD_RELOC_PPC64_TPREL16_DS;
                  break;
+
                case BFD_RELOC_PPC_TPREL16_LO:
                  reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
                  break;
+
                case BFD_RELOC_PPC_GOT_DTPREL16:
                case BFD_RELOC_PPC_GOT_DTPREL16_LO:
                case BFD_RELOC_PPC_GOT_TPREL16:
                case BFD_RELOC_PPC_GOT_TPREL16_LO:
                  break;
+
                default:
                  as_bad (_("unsupported relocation for DS offset field"));
                  break;
@@ -6903,6 +6970,7 @@ ppc_fix_adjustable (fixS *fix)
          && fix->fx_r_type != BFD_RELOC_PPC64_GOT16_LO_DS
          && fix->fx_r_type != BFD_RELOC_16_GOT_PCREL
          && fix->fx_r_type != BFD_RELOC_32_GOTOFF
+         && fix->fx_r_type != BFD_RELOC_PPC64_GOT_PCREL34
          && fix->fx_r_type != BFD_RELOC_24_PLT_PCREL
          && fix->fx_r_type != BFD_RELOC_32_PLTOFF
          && fix->fx_r_type != BFD_RELOC_32_PLT_PCREL
@@ -6912,6 +6980,7 @@ ppc_fix_adjustable (fixS *fix)
          && fix->fx_r_type != BFD_RELOC_64_PLTOFF
          && fix->fx_r_type != BFD_RELOC_64_PLT_PCREL
          && fix->fx_r_type != BFD_RELOC_PPC64_PLT16_LO_DS
+         && fix->fx_r_type != BFD_RELOC_PPC64_PLT_PCREL34
          && fix->fx_r_type != BFD_RELOC_PPC64_PLTGOT16
          && fix->fx_r_type != BFD_RELOC_PPC64_PLTGOT16_LO
          && fix->fx_r_type != BFD_RELOC_PPC64_PLTGOT16_HI
@@ -7120,10 +7189,34 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
          fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHESTA;
          break;
 
+       case BFD_RELOC_PPC64_ADDR16_HIGHER34:
+         fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHER34;
+         break;
+
+       case BFD_RELOC_PPC64_ADDR16_HIGHERA34:
+         fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHERA34;
+         break;
+
+       case BFD_RELOC_PPC64_ADDR16_HIGHEST34:
+         fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHEST34;
+         break;
+
+       case BFD_RELOC_PPC64_ADDR16_HIGHESTA34:
+         fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHESTA34;
+         break;
+
        case BFD_RELOC_PPC_16DX_HA:
          fixP->fx_r_type = BFD_RELOC_PPC_REL16DX_HA;
          break;
 
+       case BFD_RELOC_PPC64_D34:
+         fixP->fx_r_type = BFD_RELOC_PPC64_PCREL34;
+         break;
+
+       case BFD_RELOC_PPC64_D28:
+         fixP->fx_r_type = BFD_RELOC_PPC64_PCREL28;
+         break;
+
        default:
          break;
        }
@@ -7370,6 +7463,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
        case BFD_RELOC_PPC_VLE_SDAREL_HI16D:
        case BFD_RELOC_PPC_VLE_SDAREL_HA16A:
        case BFD_RELOC_PPC_VLE_SDAREL_HA16D:
+       case BFD_RELOC_PPC64_GOT_PCREL34:
+       case BFD_RELOC_PPC64_PLT_PCREL34:
          gas_assert (fixP->fx_addsy != NULL);
          /* Fallthru */
 
@@ -7421,9 +7516,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
 #else
 #define APPLY_RELOC 1
 #endif
+      /* We need to call the insert function even when fieldval is
+        zero if the insert function would translate that zero to a
+        bit pattern other than all zeros.  */
       if ((fieldval != 0 && APPLY_RELOC) || operand->insert != NULL)
        {
-         unsigned long insn;
+         uint64_t insn;
          unsigned char *where;
 
          /* Fetch the instruction, insert the fully resolved operand
@@ -7431,34 +7529,56 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
          where = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
          if (target_big_endian)
            {
-             if (fixP->fx_size == 4)
-               insn = bfd_getb32 (where);
-             else
+             if (fixP->fx_size < 4)
                insn = bfd_getb16 (where);
+             else
+               {
+                 insn = bfd_getb32 (where);
+                 if (fixP->fx_size > 4)
+                   insn = insn << 32 | bfd_getb32 (where + 4);
+               }
            }
          else
            {
-             if (fixP->fx_size == 4)
-               insn = bfd_getl32 (where);
-             else
+             if (fixP->fx_size < 4)
                insn = bfd_getl16 (where);
+             else
+               {
+                 insn = bfd_getl32 (where);
+                 if (fixP->fx_size > 4)
+                   insn = insn << 32 | bfd_getl32 (where + 4);
+               }
            }
          insn = ppc_insert_operand (insn, operand, fieldval,
                                     fixP->tc_fix_data.ppc_cpu,
                                     fixP->fx_file, fixP->fx_line);
          if (target_big_endian)
            {
-             if (fixP->fx_size == 4)
-               bfd_putb32 (insn, where);
-             else
+             if (fixP->fx_size < 4)
                bfd_putb16 (insn, where);
+             else
+               {
+                 if (fixP->fx_size > 4)
+                   {
+                     bfd_putb32 (insn, where + 4);
+                     insn >>= 32;
+                   }
+                 bfd_putb32 (insn, where);
+               }
            }
          else
            {
-             if (fixP->fx_size == 4)
-               bfd_putl32 (insn, where);
-             else
+             if (fixP->fx_size < 4)
                bfd_putl16 (insn, where);
+             else
+               {
+                 if (fixP->fx_size > 4)
+                   {
+                     bfd_putl32 (insn, where + 4);
+                     insn >>= 32;
+                   }
+                 bfd_putl32 (insn, where);
+               }
            }
        }
 
index 08e381e293c25eb8c0443811bd5dc03e53d472d7..9de5c08441b5bd36768ecf5bc1ec9fc38299ad05 100644 (file)
@@ -273,7 +273,13 @@ extern int ppc_force_relocation (struct fix *);
      || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHER_S           \
      || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST            \
      || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST_S          \
-     || (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA))
+     || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHER34    \
+     || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHERA34   \
+     || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHEST34   \
+     || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHESTA34  \
+     || (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA              \
+     || (FIX)->fx_r_type == BFD_RELOC_PPC64_D34                        \
+     || (FIX)->fx_r_type == BFD_RELOC_PPC64_D28))
 #endif
 
 #define TC_VALIDATE_FIX_SUB(FIX, SEG) 0
index aa199d5e85ea7f3f10b85d0411f9b7395309b759..1660d530f0a06911f3148477ae8a67f18defec51 100644 (file)
@@ -116,3 +116,4 @@ run_dump_test "htm"
 run_dump_test "titan"
 run_dump_test "prefix-align"
 run_dump_test "prefix-pcrel"
+run_dump_test "prefix-reloc"
diff --git a/gas/testsuite/gas/ppc/prefix-reloc.d b/gas/testsuite/gas/ppc/prefix-reloc.d
new file mode 100644 (file)
index 0000000..9f554ac
--- /dev/null
@@ -0,0 +1,35 @@
+#as: -a64 -mfuture
+#objdump: -dr -Mfuture
+#name: Prefix insn relocations
+
+.*
+
+Disassembly of section \.text:
+
+0+ <\.text>:
+   0:  (00 00 00 06|06 00 00 00)       pli     r9,0
+   4:  (00 00 20 39|39 20 00 00) 
+                       0: R_PPC64_D34_HA30     ext
+   8:  (46 17 29 79|79 29 17 46)       rldicr  r9,r9,34,29
+   c:  (00 00 00 06|06 00 00 00)       paddi   r9,r9,0
+  10:  (00 00 29 39|39 29 00 00) 
+                       c: R_PPC64_D34_LO       ext
+  14:  (00 00 10 04|04 10 00 00)       pld     r3,0
+  18:  (00 00 60 e4|e4 60 00 00) 
+                       14: R_PPC64_PCREL34     ext
+  1c:  (00 00 10 04|04 10 00 00)       pld     r4,0
+  20:  (00 00 80 e4|e4 80 00 00) 
+                       1c: R_PPC64_GOT_PCREL34 ext
+  24:  (00 00 10 04|04 10 00 00)       pld     r5,0
+  28:  (00 00 a0 e4|e4 a0 00 00) 
+                       24: R_PPC64_PLT_PCREL34 ext
+  2c:  (00 00 10 04|04 10 00 00)       pld     r6,0
+  30:  (00 00 c0 e4|e4 c0 00 00) 
+                       2c: R_PPC64_PCREL34     ext
+  34:  (00 00 00 04|04 00 00 00)       pld     r7,0\(0\)
+  38:  (00 00 e0 e4|e4 e0 00 00) 
+                       34: R_PPC64_D34 ext
+  3c:  (00 00 00 60|60 00 00 00)       nop
+  40:  (00 00 10 04|04 10 00 00)       pld     r8,0
+  44:  (00 00 00 e5|e5 00 00 00) 
+                       40: R_PPC64_PCREL34     ext
diff --git a/gas/testsuite/gas/ppc/prefix-reloc.s b/gas/testsuite/gas/ppc/prefix-reloc.s
new file mode 100644 (file)
index 0000000..a2f2307
--- /dev/null
@@ -0,0 +1,13 @@
+ .text
+ pli 9,ext@ha
+ sldi 9,9,34
+ paddi 9,9,ext@l
+ pld 3,ext@pcrel
+ pld 4,ext@got@pcrel
+ pld 5,ext@plt@pcrel
+0: pld 6,ext-0b(0),1
+ pld 7,ext(0),0
+# The following insn will need an alignment nop, testing the behaviour
+# of "dot" in the expression.  Don't stupidly edit this file and lose
+# the nop.
+ pld 8,ext-.(0),1
index c02b33aa309aa1a03592e843c0ca1e6db2406fbb..2e8408402fbe98d7efdb921f197806bf66581a7f 100644 (file)
@@ -1,3 +1,15 @@
+2019-05-24  Alan Modra  <amodra@gmail.com>
+
+       * elf/ppc64.h (R_PPC64_PLTSEQ_NOTOC, R_PPC64_PLTCALL_NOTOC),
+       (R_PPC64_PCREL_OPT, R_PPC64_D34, R_PPC64_D34_LO, R_PPC64_D34_HI30),
+       (R_PPC64_D34_HA30, R_PPC64_PCREL34, R_PPC64_GOT_PCREL34),
+       (R_PPC64_PLT_PCREL34, R_PPC64_PLT_PCREL34_NOTOC),
+       (R_PPC64_ADDR16_HIGHER34, R_PPC64_ADDR16_HIGHERA34),
+       (R_PPC64_ADDR16_HIGHEST34, R_PPC64_ADDR16_HIGHESTA34),
+       (R_PPC64_REL16_HIGHER34, R_PPC64_REL16_HIGHERA34),
+       (R_PPC64_REL16_HIGHEST34, R_PPC64_REL16_HIGHESTA34),
+       (R_PPC64_D28, R_PPC64_PCREL28): Define.
+
 2019-05-24  Peter Bergner  <bergner@linux.ibm.com>
            Alan Modra  <amodra@gmail.com>
 
index 6dd29cdf8a935f4c27c9db1251dd7f4cd9fef1d9..e90c7fd2efc2532f751f8d11cf56131b09a38ebd 100644 (file)
@@ -158,6 +158,30 @@ START_RELOC_NUMBERS (elf_ppc64_reloc_type)
   RELOC_NUMBER (R_PPC64_PLTSEQ,                   119)
   RELOC_NUMBER (R_PPC64_PLTCALL,          120)
 
+/* Powerxx support.  */
+  RELOC_NUMBER (R_PPC64_PLTSEQ_NOTOC,     121)
+  RELOC_NUMBER (R_PPC64_PLTCALL_NOTOC,    122)
+  RELOC_NUMBER (R_PPC64_PCREL_OPT,        123)
+
+  RELOC_NUMBER (R_PPC64_D34,              128)
+  RELOC_NUMBER (R_PPC64_D34_LO,                   129)
+  RELOC_NUMBER (R_PPC64_D34_HI30,         130)
+  RELOC_NUMBER (R_PPC64_D34_HA30,         131)
+  RELOC_NUMBER (R_PPC64_PCREL34,          132)
+  RELOC_NUMBER (R_PPC64_GOT_PCREL34,      133)
+  RELOC_NUMBER (R_PPC64_PLT_PCREL34,      134)
+  RELOC_NUMBER (R_PPC64_PLT_PCREL34_NOTOC, 135)
+  RELOC_NUMBER (R_PPC64_ADDR16_HIGHER34,   136)
+  RELOC_NUMBER (R_PPC64_ADDR16_HIGHERA34,  137)
+  RELOC_NUMBER (R_PPC64_ADDR16_HIGHEST34,  138)
+  RELOC_NUMBER (R_PPC64_ADDR16_HIGHESTA34, 139)
+  RELOC_NUMBER (R_PPC64_REL16_HIGHER34,    140)
+  RELOC_NUMBER (R_PPC64_REL16_HIGHERA34,   141)
+  RELOC_NUMBER (R_PPC64_REL16_HIGHEST34,   142)
+  RELOC_NUMBER (R_PPC64_REL16_HIGHESTA34,  143)
+  RELOC_NUMBER (R_PPC64_D28,              144)
+  RELOC_NUMBER (R_PPC64_PCREL28,          145)
+
 #ifndef RELOC_MACROS_GEN_FUNC
 /* Relocation only used internally by gas or ld.  If you need to use
    these reloc numbers, you can change them to some other unused value
This page took 0.051371 seconds and 4 git commands to generate.