Fix "PowerPC64 ELFv2 entry code" for big-endian
[external/binutils.git] / bfd / elf64-ppc.c
index 46cba68..f0bcee1 100644 (file)
@@ -1,5 +1,5 @@
 /* PowerPC64-specific support for 64-bit ELF.
-   Copyright (C) 1999-2014 Free Software Foundation, Inc.
+   Copyright (C) 1999-2016 Free Software Foundation, Inc.
    Written by Linus Nordberg, Swox AB <info@swox.com>,
    based on elf32-ppc.c by Ian Lance Taylor.
    Largely rewritten by Alan Modra.
@@ -64,7 +64,7 @@ static bfd_vma opd_entry_value
 #define ELF_TARGET_ID          PPC64_ELF_DATA
 #define ELF_MACHINE_CODE       EM_PPC64
 #define ELF_MAXPAGESIZE                0x10000
-#define ELF_COMMONPAGESIZE     0x1000
+#define ELF_COMMONPAGESIZE     0x10000
 #define elf_info_to_howto      ppc64_elf_info_to_howto
 
 #define elf_backend_want_got_sym 0
@@ -138,6 +138,8 @@ static bfd_vma opd_entry_value
 
 /* TOC base pointers offset from start of TOC.  */
 #define TOC_BASE_OFF   0x8000
+/* TOC base alignment.  */
+#define TOC_BASE_ALIGN 256
 
 /* Offset of tp and dtp pointers from start of TLS block.  */
 #define TP_OFFSET      0x7000
@@ -171,8 +173,12 @@ static bfd_vma opd_entry_value
 #define LD_R2_0R2      0xe8420000      /* ld    %r2,xxx+0(%r2)  */
 
 #define LD_R2_0R1      0xe8410000      /* ld    %r2,0(%r1)      */
+#define LD_R2_0R12     0xe84c0000      /* ld    %r2,0(%r12)     */
+#define ADD_R2_R2_R12  0x7c426214      /* add   %r2,%r2,%r12    */
 
-#define ADDIS_R12_R2   0x3d820000      /* addis %r12,%r2,xxx@ha     */
+#define LIS_R2         0x3c400000      /* lis %r2,xxx@ha         */
+#define ADDIS_R2_R12   0x3c4c0000      /* addis %r2,%r12,xxx@ha  */
+#define ADDIS_R12_R2   0x3d820000      /* addis %r12,%r2,xxx@ha  */
 #define ADDIS_R12_R12  0x3d8c0000      /* addis %r12,%r12,xxx@ha */
 #define LD_R12_0R12    0xe98c0000      /* ld    %r12,xxx@l(%r12) */
 
@@ -235,6 +241,23 @@ static bfd_vma opd_entry_value
 #ifndef NO_OPD_RELOCS
 #define NO_OPD_RELOCS 0
 #endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+#endif
+
+static inline int
+abiversion (bfd *abfd)
+{
+  return elf_elfheader (abfd)->e_flags & EF_PPC64_ABI;
+}
+
+static inline void
+set_abiversion (bfd *abfd, int ver)
+{
+  elf_elfheader (abfd)->e_flags &= ~EF_PPC64_ABI;
+  elf_elfheader (abfd)->e_flags |= ver & EF_PPC64_ABI;
+}
 \f
 #define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1)
 
@@ -245,8 +268,8 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
   /* This reloc does nothing.  */
   HOWTO (R_PPC64_NONE,         /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
@@ -2003,6 +2026,21 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
         0xffff,                /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
+  /* Like R_PPC64_REL16_HA but for split field in addpcis.  */
+  HOWTO (R_PPC64_REL16DX_HA,   /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        TRUE,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        ppc64_elf_ha_reloc,    /* special_function */
+        "R_PPC64_REL16DX_HA",  /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x1fffc1,              /* dst_mask */
+        TRUE),                 /* pcrel_offset */
+
   /* Like R_PPC64_ADDR16_HI, but no overflow.  */
   HOWTO (R_PPC64_ADDR16_HIGH,  /* type */
         16,                    /* rightshift */
@@ -2093,6 +2131,21 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
         0xffff,                /* dst_mask */
         FALSE),                /* pcrel_offset */
 
+  /* Marker reloc on ELFv2 large-model function entry.  */
+  HOWTO (R_PPC64_ENTRY,
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_PPC64_ENTRY",       /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
   /* Like ADDR64, but use local entry point of function.  */
   HOWTO (R_PPC64_ADDR64_LOCAL, /* type */
         0,                     /* rightshift */
@@ -2148,13 +2201,10 @@ ppc_howto_init (void)
 {
   unsigned int i, type;
 
-  for (i = 0;
-       i < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]);
-       i++)
+  for (i = 0; i < ARRAY_SIZE (ppc64_elf_howto_raw); i++)
     {
       type = ppc64_elf_howto_raw[i].type;
-      BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table)
-                         / sizeof (ppc64_elf_howto_table[0])));
+      BFD_ASSERT (type < ARRAY_SIZE (ppc64_elf_howto_table));
       ppc64_elf_howto_table[type] = &ppc64_elf_howto_raw[i];
     }
 }
@@ -2396,6 +2446,10 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       break;
     case BFD_RELOC_HI16_S_PCREL:               r = R_PPC64_REL16_HA;
       break;
+    case BFD_RELOC_PPC_REL16DX_HA:             r = R_PPC64_REL16DX_HA;
+      break;
+    case BFD_RELOC_PPC64_ENTRY:                        r = R_PPC64_ENTRY;
+      break;
     case BFD_RELOC_PPC64_ADDR64_LOCAL:         r = R_PPC64_ADDR64_LOCAL;
       break;
     case BFD_RELOC_VTABLE_INHERIT:             r = R_PPC64_GNU_VTINHERIT;
@@ -2413,9 +2467,7 @@ ppc64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 {
   unsigned int i;
 
-  for (i = 0;
-       i < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]);
-       i++)
+  for (i = 0; i < ARRAY_SIZE (ppc64_elf_howto_raw); i++)
     if (ppc64_elf_howto_raw[i].name != NULL
        && strcasecmp (ppc64_elf_howto_raw[i].name, r_name) == 0)
       return &ppc64_elf_howto_raw[i];
@@ -2436,8 +2488,7 @@ ppc64_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
     ppc_howto_init ();
 
   type = ELF64_R_TYPE (dst->r_info);
-  if (type >= (sizeof (ppc64_elf_howto_table)
-              / sizeof (ppc64_elf_howto_table[0])))
+  if (type >= ARRAY_SIZE (ppc64_elf_howto_table))
     {
       (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
                             abfd, (int) type);
@@ -2453,6 +2504,11 @@ ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
                    void *data, asection *input_section,
                    bfd *output_bfd, char **error_message)
 {
+  enum elf_ppc64_reloc_type r_type;
+  long insn;
+  bfd_size_type octets;
+  bfd_vma value;
+
   /* If this is a relocatable link (output_bfd test tells us), just
      call the generic function.  Any adjustment will be done at final
      link time.  */
@@ -2464,7 +2520,29 @@ ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
      We won't actually be using the low 16 bits, so trashing them
      doesn't matter.  */
   reloc_entry->addend += 0x8000;
-  return bfd_reloc_continue;
+  r_type = reloc_entry->howto->type;
+  if (r_type != R_PPC64_REL16DX_HA)
+    return bfd_reloc_continue;
+
+  value = 0;
+  if (!bfd_is_com_section (symbol->section))
+    value = symbol->value;
+  value += (reloc_entry->addend
+           + symbol->section->output_offset
+           + symbol->section->output_section->vma);
+  value -= (reloc_entry->address
+           + input_section->output_offset
+           + input_section->output_section->vma);
+  value = (bfd_signed_vma) value >> 16;
+
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
+  insn &= ~0x1fffc1;
+  insn |= (value & 0xffc1) | ((value & 0x3e) << 15);
+  bfd_put_32 (abfd, insn, (bfd_byte *) data + octets);
+  if (value + 0x8000 > 0xffff)
+    return bfd_reloc_overflow;
+  return bfd_reloc_ok;
 }
 
 static bfd_reloc_status_type
@@ -2487,6 +2565,29 @@ ppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
                                      + symbol->section->output_section->vma
                                      + symbol->section->output_offset);
     }
+  else
+    {
+      elf_symbol_type *elfsym = (elf_symbol_type *) symbol;
+
+      if (symbol->section->owner != abfd
+         && abiversion (symbol->section->owner) >= 2)
+       {
+         unsigned int i;
+
+         for (i = 0; i < symbol->section->owner->symcount; ++i)
+           {
+             asymbol *symdef = symbol->section->owner->outsymbols[i];
+
+             if (strcmp (symdef->name, symbol->name) == 0)
+               {
+                 elfsym = (elf_symbol_type *) symdef;
+                 break;
+               }
+           }
+       }
+      reloc_entry->addend
+       += PPC64_LOCAL_ENTRY_OFFSET (elfsym->internal_elf_sym.st_other);
+    }
   return bfd_reloc_continue;
 }
 
@@ -2918,7 +3019,9 @@ struct _ppc64_elf_section_data
 
   union
   {
-    /* An array with one entry for each opd function descriptor.  */
+    /* An array with one entry for each opd function descriptor,
+       and some spares since opd entries may be either 16 or 24 bytes.  */
+#define OPD_NDX(OFF) ((OFF) >> 4)
     struct _opd_sec_data
     {
       /* Points to the function code section for local opd entries.  */
@@ -2975,19 +3078,6 @@ get_opd_info (asection * sec)
     return &ppc64_elf_section_data (sec)->u.opd;
   return NULL;
 }
-
-static inline int
-abiversion (bfd *abfd)
-{
-  return elf_elfheader (abfd)->e_flags & EF_PPC64_ABI;
-}
-
-static inline void
-set_abiversion (bfd *abfd, int ver)
-{
-  elf_elfheader (abfd)->e_flags &= ~EF_PPC64_ABI;
-  elf_elfheader (abfd)->e_flags |= ver & EF_PPC64_ABI;
-}
 \f
 /* Parameters for the qsort hook.  */
 static bfd_boolean synthetic_relocatable;
@@ -3074,11 +3164,11 @@ compare_symbols (const void *ap, const void *bp)
 /* Search SYMS for a symbol of the given VALUE.  */
 
 static asymbol *
-sym_exists_at (asymbol **syms, long lo, long hi, int id, bfd_vma value)
+sym_exists_at (asymbol **syms, long lo, long hi, unsigned int id, bfd_vma value)
 {
   long mid;
 
-  if (id == -1)
+  if (id == (unsigned) -1)
     {
       while (lo < hi)
        {
@@ -3121,7 +3211,8 @@ section_covers_vma (bfd *abfd ATTRIBUTE_UNUSED, asection *section, void *ptr)
 }
 
 /* Create synthetic symbols, effectively restoring "dot-symbol" function
-   entry syms.  Also generate @plt symbols for the glink branch table.  */
+   entry syms.  Also generate @plt symbols for the glink branch table.
+   Returns count of synthetic symbols in RET or -1 on error.  */
 
 static long
 ppc64_elf_get_synthetic_symtab (bfd *abfd,
@@ -3264,6 +3355,8 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
            }
        }
 
+      if (size == 0)
+       goto done;
       s = *ret = bfd_malloc (size);
       if (s == NULL)
        {
@@ -3324,10 +3417,11 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
 
       if (opd != NULL && !bfd_malloc_and_get_section (abfd, opd, &contents))
        {
+       free_contents_and_exit_err:
+         count = -1;
        free_contents_and_exit:
          if (contents)
            free (contents);
-         count = -1;
          goto done;
        }
 
@@ -3358,7 +3452,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
          void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
 
          if (!bfd_malloc_and_get_section (abfd, dynamic, &dynbuf))
-           goto free_contents_and_exit;
+           goto free_contents_and_exit_err;
 
          extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
          swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
@@ -3420,7 +3514,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
            {
              slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
              if (! (*slurp_relocs) (abfd, relplt, dyn_syms, TRUE))
-               goto free_contents_and_exit;
+               goto free_contents_and_exit_err;
 
              plt_count = relplt->size / sizeof (Elf64_External_Rela);
              size += plt_count * sizeof (asymbol);
@@ -3435,9 +3529,11 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
            }
        }
 
+      if (size == 0)
+       goto free_contents_and_exit;
       s = *ret = bfd_malloc (size);
       if (s == NULL)
-       goto free_contents_and_exit;
+       goto free_contents_and_exit_err;
 
       names = (char *) (s + count + plt_count + (resolv_vma != 0));
 
@@ -3683,7 +3779,7 @@ must_be_dyn_reloc (struct bfd_link_info *info,
     case R_PPC64_TPREL16_HIGHEST:
     case R_PPC64_TPREL16_HIGHESTA:
     case R_PPC64_TPREL64:
-      return !info->executable;
+      return !bfd_link_executable (info);
     }
 }
 
@@ -3762,7 +3858,23 @@ enum ppc_stub_type {
   ppc_stub_plt_branch,
   ppc_stub_plt_branch_r2off,
   ppc_stub_plt_call,
-  ppc_stub_plt_call_r2save
+  ppc_stub_plt_call_r2save,
+  ppc_stub_global_entry,
+  ppc_stub_save_res
+};
+
+/* Information on stub grouping.  */
+struct map_stub
+{
+  /* The stub section.  */
+  asection *stub_sec;
+  /* This is the section to which stubs in the group will be attached.  */
+  asection *link_sec;
+  /* Next group.  */
+  struct map_stub *next;
+  /* Whether to emit a copy of register save/restore functions in this
+     group.  */
+  int needs_save_res;
 };
 
 struct ppc_stub_hash_entry {
@@ -3772,8 +3884,8 @@ struct ppc_stub_hash_entry {
 
   enum ppc_stub_type stub_type;
 
-  /* The stub section.  */
-  asection *stub_sec;
+  /* Group information.  */
+  struct map_stub *group;
 
   /* Offset within stub_sec of the beginning of this stub.  */
   bfd_vma stub_offset;
@@ -3787,10 +3899,6 @@ struct ppc_stub_hash_entry {
   struct ppc_link_hash_entry *h;
   struct plt_entry *plt_ent;
 
-  /* Where this stub is being called from, or, in the case of combined
-     stub sections, the first input section in the group.  */
-  asection *id_sec;
-
   /* Symbol st_other.  */
   unsigned char other;
 };
@@ -3854,6 +3962,10 @@ struct ppc_link_hash_entry
   /* Set if we twiddled this symbol to weak at some stage.  */
   unsigned int was_undefined:1;
 
+  /* Set if this is an out-of-line register save/restore function,
+     with non-standard calling convention.  */
+  unsigned int save_res:1;
+
   /* Contexts in which symbol is used in the GOT (or TOC).
      TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the
      corresponding relocs are encountered during check_relocs.
@@ -3891,34 +4003,37 @@ struct ppc_link_hash_table
   /* Various options and other info passed from the linker.  */
   struct ppc64_elf_params *params;
 
-  /* Array to keep track of which stub sections have been created, and
-     information on stub grouping.  */
-  struct map_stub {
-    /* This is the section to which stubs in the group will be attached.  */
-    asection *link_sec;
-    /* The stub section.  */
-    asection *stub_sec;
-    /* Along with elf_gp, specifies the TOC pointer used in this group.  */
+  /* The size of sec_info below.  */
+  unsigned int sec_info_arr_size;
+
+  /* Per-section array of extra section info.  Done this way rather
+     than as part of ppc64_elf_section_data so we have the info for
+     non-ppc64 sections.  */
+  struct
+  {
+    /* Along with elf_gp, specifies the TOC pointer used by this section.  */
     bfd_vma toc_off;
-  } *stub_group;
+
+    union
+    {
+      /* The section group that this section belongs to.  */
+      struct map_stub *group;
+      /* A temp section list pointer.  */
+      asection *list;
+    } u;
+  } *sec_info;
+
+  /* Linked list of groups.  */
+  struct map_stub *group;
 
   /* Temp used when calculating TOC pointers.  */
   bfd_vma toc_curr;
   bfd *toc_bfd;
   asection *toc_first_sec;
 
-  /* Highest input section id.  */
-  int top_id;
-
-  /* Highest output section index.  */
-  int top_index;
-
   /* Used when adding symbols.  */
   struct ppc_link_hash_entry *dot_syms;
 
-  /* List of input sections for each output section.  */
-  asection **input_list;
-
   /* Shortcuts to get to dynamic linker sections.  */
   asection *dynbss;
   asection *relbss;
@@ -3936,7 +4051,7 @@ struct ppc_link_hash_table
   bfd_size_type got_reli_size;
 
   /* Statistics.  */
-  unsigned long stub_count[ppc_stub_plt_call_r2save];
+  unsigned long stub_count[ppc_stub_global_entry];
 
   /* Number of stubs against global syms.  */
   unsigned long stub_globals;
@@ -4022,13 +4137,12 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       /* Initialize the local fields.  */
       eh = (struct ppc_stub_hash_entry *) entry;
       eh->stub_type = ppc_stub_none;
-      eh->stub_sec = NULL;
+      eh->group = NULL;
       eh->stub_offset = 0;
       eh->target_value = 0;
       eh->target_section = NULL;
       eh->h = NULL;
       eh->plt_ent = NULL;
-      eh->id_sec = NULL;
       eh->other = 0;
     }
 
@@ -4281,7 +4395,7 @@ create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
       || ! bfd_set_section_alignment (dynobj, htab->brlt, 3))
     return FALSE;
 
-  if (!info->shared)
+  if (!bfd_link_pic (info))
     return TRUE;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
@@ -4315,7 +4429,7 @@ ppc64_elf_init_stub_bfd (struct bfd_link_info *info,
   htab->elf.dynobj = params->stub_bfd;
   htab->params = params;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   return create_linkage_sections (htab->elf.dynobj, info);
@@ -4378,18 +4492,18 @@ ppc_get_stub_entry (const asection *input_section,
                    struct ppc_link_hash_table *htab)
 {
   struct ppc_stub_hash_entry *stub_entry;
-  const asection *id_sec;
+  struct map_stub *group;
 
   /* If this input section is part of a group of sections sharing one
      stub section, then use the id of the first section in the group.
      Stub names need to include a section id, as there may well be
      more than one stub used to reach say, printf, and we need to
      distinguish between them.  */
-  id_sec = htab->stub_group[input_section->id].link_sec;
+  group = htab->sec_info[input_section->id].u.group;
 
   if (h != NULL && h->u.stub_cache != NULL
       && h->u.stub_cache->h == h
-      && h->u.stub_cache->id_sec == id_sec)
+      && h->u.stub_cache->group == group)
     {
       stub_entry = h->u.stub_cache;
     }
@@ -4397,7 +4511,7 @@ ppc_get_stub_entry (const asection *input_section,
     {
       char *stub_name;
 
-      stub_name = ppc_stub_name (id_sec, sym_sec, h, rel);
+      stub_name = ppc_stub_name (group->link_sec, sym_sec, h, rel);
       if (stub_name == NULL)
        return NULL;
 
@@ -4421,35 +4535,32 @@ ppc_add_stub (const char *stub_name,
              struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
+  struct map_stub *group;
   asection *link_sec;
   asection *stub_sec;
   struct ppc_stub_hash_entry *stub_entry;
 
-  link_sec = htab->stub_group[section->id].link_sec;
-  stub_sec = htab->stub_group[section->id].stub_sec;
+  group = htab->sec_info[section->id].u.group;
+  link_sec = group->link_sec;
+  stub_sec = group->stub_sec;
   if (stub_sec == NULL)
     {
-      stub_sec = htab->stub_group[link_sec->id].stub_sec;
-      if (stub_sec == NULL)
-       {
-         size_t namelen;
-         bfd_size_type len;
-         char *s_name;
+      size_t namelen;
+      bfd_size_type len;
+      char *s_name;
 
-         namelen = strlen (link_sec->name);
-         len = namelen + sizeof (STUB_SUFFIX);
-         s_name = bfd_alloc (htab->params->stub_bfd, len);
-         if (s_name == NULL)
-           return NULL;
+      namelen = strlen (link_sec->name);
+      len = namelen + sizeof (STUB_SUFFIX);
+      s_name = bfd_alloc (htab->params->stub_bfd, len);
+      if (s_name == NULL)
+       return NULL;
 
-         memcpy (s_name, link_sec->name, namelen);
-         memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
-         stub_sec = (*htab->params->add_stub_section) (s_name, link_sec);
-         if (stub_sec == NULL)
-           return NULL;
-         htab->stub_group[link_sec->id].stub_sec = stub_sec;
-       }
-      htab->stub_group[section->id].stub_sec = stub_sec;
+      memcpy (s_name, link_sec->name, namelen);
+      memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
+      stub_sec = (*htab->params->add_stub_section) (s_name, link_sec);
+      if (stub_sec == NULL)
+       return NULL;
+      group->stub_sec = stub_sec;
     }
 
   /* Enter this entry into the linker stub hash table.  */
@@ -4462,9 +4573,8 @@ ppc_add_stub (const char *stub_name,
       return NULL;
     }
 
-  stub_entry->stub_sec = stub_sec;
+  stub_entry->group = group;
   stub_entry->stub_offset = 0;
-  stub_entry->id_sec = link_sec;
   return stub_entry;
 }
 
@@ -4521,11 +4631,11 @@ ppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
     return FALSE;
 
   htab->dynbss = bfd_get_linker_section (dynobj, ".dynbss");
-  if (!info->shared)
+  if (!bfd_link_pic (info))
     htab->relbss = bfd_get_linker_section (dynobj, ".rela.bss");
 
   if (!htab->elf.sgot || !htab->elf.splt || !htab->elf.srelplt || !htab->dynbss
-      || (!info->shared && !htab->relbss))
+      || (!bfd_link_pic (info) && !htab->relbss))
     abort ();
 
   return TRUE;
@@ -4781,22 +4891,43 @@ ppc64_elf_add_symbol_hook (bfd *ibfd,
                           const char **name,
                           flagword *flags ATTRIBUTE_UNUSED,
                           asection **sec,
-                          bfd_vma *value ATTRIBUTE_UNUSED)
+                          bfd_vma *value)
 {
-  if ((ibfd->flags & DYNAMIC) == 0
-      && ELF_ST_BIND (isym->st_info) == STB_GNU_UNIQUE)
-    elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
+  if ((ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC
+       || ELF_ST_BIND (isym->st_info) == STB_GNU_UNIQUE)
+      && (ibfd->flags & DYNAMIC) == 0
+      && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
+    elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any;
 
-  if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
+  if (*sec != NULL
+      && strcmp ((*sec)->name, ".opd") == 0)
     {
-      if ((ibfd->flags & DYNAMIC) == 0)
-       elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
+      asection *code_sec;
+
+      if (!(ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC
+           || ELF_ST_TYPE (isym->st_info) == STT_FUNC))
+       isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
+
+      /* If the symbol is a function defined in .opd, and the function
+        code is in a discarded group, let it appear to be undefined.  */
+      if (!bfd_link_relocatable (info)
+         && (*sec)->reloc_count != 0
+         && opd_entry_value (*sec, *value, &code_sec, NULL,
+                             FALSE) != (bfd_vma) -1
+         && discarded_section (code_sec))
+       {
+         *sec = bfd_und_section_ptr;
+         isym->st_shndx = SHN_UNDEF;
+       }
     }
-  else if (ELF_ST_TYPE (isym->st_info) == STT_FUNC)
-    ;
   else if (*sec != NULL
-          && strcmp ((*sec)->name, ".opd") == 0)
-    isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
+          && strcmp ((*sec)->name, ".toc") == 0
+          && ELF_ST_TYPE (isym->st_info) == STT_OBJECT)
+    {
+      struct ppc_link_hash_table *htab = ppc_hash_table (info);
+      if (htab != NULL)
+       htab->params->object_in_toc = 1;
+    }
 
   if ((STO_PPC64_LOCAL_MASK & isym->st_other) != 0)
     {
@@ -4894,7 +5025,7 @@ add_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info)
   fdh = lookup_fdh (eh, htab);
   if (fdh == NULL)
     {
-      if (!info->relocatable
+      if (!bfd_link_relocatable (info)
          && (eh->elf.root.type == bfd_link_hash_undefined
              || eh->elf.root.type == bfd_link_hash_undefweak)
          && eh->elf.ref_regular)
@@ -4938,81 +5069,77 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
   struct ppc_link_hash_entry **p, *eh;
+  asection *opd = bfd_get_section_by_name (ibfd, ".opd");
 
-  if (!is_ppc64_elf (info->output_bfd))
-    return TRUE;
-  htab = ppc_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  if (is_ppc64_elf (ibfd))
+  if (opd != NULL && opd->size != 0)
     {
-      asection *opd = bfd_get_section_by_name (ibfd, ".opd");
-
-      if (opd != NULL && opd->size != 0)
+      if (abiversion (ibfd) == 0)
+       set_abiversion (ibfd, 1);
+      else if (abiversion (ibfd) == 2)
        {
-         if (abiversion (ibfd) == 0)
-           set_abiversion (ibfd, 1);
-         else if (abiversion (ibfd) == 2)
-           {
-             info->callbacks->einfo (_("%P: %B .opd not allowed in ABI"
-                                       " version %d\n"),
-                                     ibfd, abiversion (ibfd));
-             bfd_set_error (bfd_error_bad_value);
-             return FALSE;
-           }
-
-         if ((ibfd->flags & DYNAMIC) == 0
-             && (opd->flags & SEC_RELOC) != 0
-             && opd->reloc_count != 0
-             && !bfd_is_abs_section (opd->output_section))
-           {
-             /* Garbage collection needs some extra help with .opd sections.
-                We don't want to necessarily keep everything referenced by
-                relocs in .opd, as that would keep all functions.  Instead,
-                if we reference an .opd symbol (a function descriptor), we
-                want to keep the function code symbol's section.  This is
-                easy for global symbols, but for local syms we need to keep
-                information about the associated function section.  */
-             bfd_size_type amt;
-             asection **opd_sym_map;
-
-             amt = opd->size * sizeof (*opd_sym_map) / 8;
-             opd_sym_map = bfd_zalloc (ibfd, amt);
-             if (opd_sym_map == NULL)
-               return FALSE;
-             ppc64_elf_section_data (opd)->u.opd.func_sec = opd_sym_map;
-             BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal);
-             ppc64_elf_section_data (opd)->sec_type = sec_opd;
-           }
+         info->callbacks->einfo (_("%P: %B .opd not allowed in ABI"
+                                   " version %d\n"),
+                                 ibfd, abiversion (ibfd));
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
        }
 
-      /* For input files without an explicit abiversion in e_flags
-        we should have flagged any with symbol st_other bits set
-        as ELFv1 and above flagged those with .opd as ELFv2.
-        Set the output abiversion if not yet set, and for any input
-        still ambiguous, take its abiversion from the output.
-        Differences in ABI are reported later.  */
-      if (abiversion (info->output_bfd) == 0)
-       set_abiversion (info->output_bfd, abiversion (ibfd));
-      else if (abiversion (ibfd) == 0)
-       set_abiversion (ibfd, abiversion (info->output_bfd));
-
-      p = &htab->dot_syms;
-      while ((eh = *p) != NULL)
+      if ((ibfd->flags & DYNAMIC) == 0
+         && (opd->flags & SEC_RELOC) != 0
+         && opd->reloc_count != 0
+         && !bfd_is_abs_section (opd->output_section))
        {
-         *p = NULL;
-         if (&eh->elf == htab->elf.hgot)
-           ;
-         else if (htab->elf.hgot == NULL
-                  && strcmp (eh->elf.root.root.string, ".TOC.") == 0)
-           htab->elf.hgot = &eh->elf;
-         else if (!add_symbol_adjust (eh, info))
+         /* Garbage collection needs some extra help with .opd sections.
+            We don't want to necessarily keep everything referenced by
+            relocs in .opd, as that would keep all functions.  Instead,
+            if we reference an .opd symbol (a function descriptor), we
+            want to keep the function code symbol's section.  This is
+            easy for global symbols, but for local syms we need to keep
+            information about the associated function section.  */
+         bfd_size_type amt;
+         asection **opd_sym_map;
+
+         amt = OPD_NDX (opd->size) * sizeof (*opd_sym_map);
+         opd_sym_map = bfd_zalloc (ibfd, amt);
+         if (opd_sym_map == NULL)
            return FALSE;
-         p = &eh->u.next_dot_sym;
+         ppc64_elf_section_data (opd)->u.opd.func_sec = opd_sym_map;
+         BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal);
+         ppc64_elf_section_data (opd)->sec_type = sec_opd;
        }
     }
 
+  if (!is_ppc64_elf (info->output_bfd))
+    return TRUE;
+  htab = ppc_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
+  /* For input files without an explicit abiversion in e_flags
+     we should have flagged any with symbol st_other bits set
+     as ELFv1 and above flagged those with .opd as ELFv2.
+     Set the output abiversion if not yet set, and for any input
+     still ambiguous, take its abiversion from the output.
+     Differences in ABI are reported later.  */
+  if (abiversion (info->output_bfd) == 0)
+    set_abiversion (info->output_bfd, abiversion (ibfd));
+  else if (abiversion (ibfd) == 0)
+    set_abiversion (ibfd, abiversion (info->output_bfd));
+
+  p = &htab->dot_syms;
+  while ((eh = *p) != NULL)
+    {
+      *p = NULL;
+      if (&eh->elf == htab->elf.hgot)
+       ;
+      else if (htab->elf.hgot == NULL
+              && strcmp (eh->elf.root.root.string, ".TOC.") == 0)
+       htab->elf.hgot = &eh->elf;
+      else if (!add_symbol_adjust (eh, info))
+       return FALSE;
+      p = &eh->u.next_dot_sym;
+    }
+
   /* Clear the list for non-ppc64 input files.  */
   p = &htab->dot_syms;
   while ((eh = *p) != NULL)
@@ -5175,7 +5302,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
   asection **opd_sym_map;
   struct elf_link_hash_entry *tga, *dottga;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   /* Don't do anything special with non-loaded, non-alloced sections.
@@ -5213,7 +5340,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       enum elf_ppc64_reloc_type r_type;
       int tls_type;
       struct _ppc64_elf_section_data *ppc64_sec;
-      struct plt_entry **ifunc;
+      struct plt_entry **ifunc, **plt_list;
 
       r_symndx = ELF64_R_SYM (rel->r_info);
       if (r_symndx < symtab_hdr->sh_info)
@@ -5256,28 +5383,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                return FALSE;
            }
        }
-      r_type = ELF64_R_TYPE (rel->r_info);
-      if (is_branch_reloc (r_type))
-       {
-         if (h != NULL && (h == tga || h == dottga))
-           {
-             if (rel != relocs
-                 && (ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSGD
-                     || ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSLD))
-               /* We have a new-style __tls_get_addr call with a marker
-                  reloc.  */
-               ;
-             else
-               /* Mark this section as having an old-style call.  */
-               sec->has_tls_get_addr_call = 1;
-           }
-
-         /* STT_GNU_IFUNC symbols must have a PLT entry.  */
-         if (ifunc != NULL
-             && !update_plt_info (abfd, ifunc, rel->r_addend))
-           return FALSE;
-       }
 
+      r_type = ELF64_R_TYPE (rel->r_info);
       switch (r_type)
        {
        case R_PPC64_TLSGD:
@@ -5304,7 +5411,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:
-         if (!info->executable)
+         if (bfd_link_pic (info))
            info->flags |= DF_STATIC_TLS;
          tls_type = TLS_TLS | TLS_TPREL;
          goto dogottls;
@@ -5377,7 +5484,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
          /* We may also need a plt entry if the symbol turns out to be
             an ifunc.  */
-         if (h != NULL && !info->shared && abiversion (abfd) != 1)
+         if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1)
            {
              if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
                return FALSE;
@@ -5389,27 +5496,29 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_PLT16_LO:
        case R_PPC64_PLT32:
        case R_PPC64_PLT64:
-         /* This symbol requires a procedure linkage table entry.  We
-            actually build the entry in adjust_dynamic_symbol,
-            because this might be a case of linking PIC code without
-            linking in any dynamic objects, in which case we don't
-            need to generate a procedure linkage table after all.  */
-         if (h == NULL)
-           {
-             /* It does not make sense to have a procedure linkage
-                table entry for a local symbol.  */
-             bfd_set_error (bfd_error_bad_value);
-             return FALSE;
-           }
-         else
+         /* This symbol requires a procedure linkage table entry.  */
+         plt_list = ifunc;
+         if (h != NULL)
            {
-             if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
-               return FALSE;
              h->needs_plt = 1;
              if (h->root.root.string[0] == '.'
                  && h->root.root.string[1] != '\0')
                ((struct ppc_link_hash_entry *) h)->is_func = 1;
+             plt_list = &h->plt.plist;
+           }
+         if (plt_list == NULL)
+           {
+             /* It does not make sense to have a procedure linkage
+                table entry for a non-ifunc local symbol.  */
+             info->callbacks->einfo
+               (_("%P: %H: %s reloc against local symbol\n"),
+                abfd, sec, rel->r_offset,
+                ppc64_elf_howto_table[r_type]->name);
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
            }
+         if (!update_plt_info (abfd, plt_list, rel->r_addend))
+           return FALSE;
          break;
 
          /* The following relocations don't need to propagate the
@@ -5440,11 +5549,12 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_REL16_LO:
        case R_PPC64_REL16_HI:
        case R_PPC64_REL16_HA:
+       case R_PPC64_REL16DX_HA:
          break;
 
          /* Not supported as a dynamic relocation.  */
        case R_PPC64_ADDR64_LOCAL:
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
              if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
                ppc_howto_init ();
@@ -5468,6 +5578,10 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          sec->has_toc_reloc = 1;
          break;
 
+         /* Marker reloc.  */
+       case R_PPC64_ENTRY:
+         break;
+
          /* This relocation describes the C++ object vtable hierarchy.
             Reconstruct it for later use during GC.  */
        case R_PPC64_GNU_VTINHERIT:
@@ -5517,24 +5631,46 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          /* Fall through.  */
 
        case R_PPC64_REL24:
-         if (h != NULL && ifunc == NULL)
+         plt_list = ifunc;
+         if (h != NULL)
            {
-             /* We may need a .plt entry if the function this reloc
-                refers to is in a shared lib.  */
-             if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
-               return FALSE;
              h->needs_plt = 1;
              if (h->root.root.string[0] == '.'
                  && h->root.root.string[1] != '\0')
                ((struct ppc_link_hash_entry *) h)->is_func = 1;
+
              if (h == tga || h == dottga)
-               sec->has_tls_reloc = 1;
+               {
+                 sec->has_tls_reloc = 1;
+                 if (rel != relocs
+                     && (ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSGD
+                         || ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSLD))
+                   /* We have a new-style __tls_get_addr call with
+                      a marker reloc.  */
+                   ;
+                 else
+                   /* Mark this section as having an old-style call.  */
+                   sec->has_tls_get_addr_call = 1;
+               }
+             plt_list = &h->plt.plist;
            }
+
+         /* 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))
+           return FALSE;
          break;
 
+       case R_PPC64_ADDR14:
+       case R_PPC64_ADDR14_BRNTAKEN:
+       case R_PPC64_ADDR14_BRTAKEN:
+       case R_PPC64_ADDR24:
+         goto dodyn;
+
        case R_PPC64_TPREL64:
          tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL;
-         if (!info->executable)
+         if (bfd_link_pic (info))
            info->flags |= DF_STATIC_TLS;
          goto dotlstoc;
 
@@ -5610,10 +5746,9 @@ 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:
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
-             if (!info->executable)
-               info->flags |= DF_STATIC_TLS;
+             info->flags |= DF_STATIC_TLS;
              goto dodyn;
            }
          break;
@@ -5644,7 +5779,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
                  s = bfd_section_from_elf_index (abfd, isym->st_shndx);
                  if (s != NULL && s != sec)
-                   opd_sym_map[rel->r_offset / 8] = s;
+                   opd_sym_map[OPD_NDX (rel->r_offset)] = s;
                }
            }
          /* Fall through.  */
@@ -5661,7 +5796,7 @@ 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:
-         if (h != NULL && !info->shared && abiversion (abfd) != 1
+         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
@@ -5675,16 +5810,12 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_REL30:
        case R_PPC64_REL32:
        case R_PPC64_REL64:
-       case R_PPC64_ADDR14:
-       case R_PPC64_ADDR14_BRNTAKEN:
-       case R_PPC64_ADDR14_BRTAKEN:
-       case R_PPC64_ADDR24:
        case R_PPC64_ADDR32:
        case R_PPC64_UADDR16:
        case R_PPC64_UADDR32:
        case R_PPC64_UADDR64:
        case R_PPC64_TOC:
-         if (h != NULL && !info->shared)
+         if (h != NULL && !bfd_link_pic (info))
            /* We may need a copy reloc.  */
            h->non_got_ref = 1;
 
@@ -5714,18 +5845,18 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
             dynamic library if we manage to avoid copy relocs for the
             symbol.  */
        dodyn:
-         if ((info->shared
+         if ((bfd_link_pic (info)
               && (must_be_dyn_reloc (info, r_type)
                   || (h != NULL
                       && (!SYMBOLIC_BIND (info, h)
                           || h->root.type == bfd_link_hash_defweak
                           || !h->def_regular))))
              || (ELIMINATE_COPY_RELOCS
-                 && !info->shared
+                 && !bfd_link_pic (info)
                  && h != NULL
                  && (h->root.type == bfd_link_hash_defweak
                      || !h->def_regular))
-             || (!info->shared
+             || (!bfd_link_pic (info)
                  && ifunc != NULL))
            {
              /* We must copy these reloc types into the output file.
@@ -5881,7 +6012,8 @@ ppc64_elf_print_private_bfd_data (bfd *abfd, void *ptr)
 }
 
 /* OFFSET in OPD_SEC specifies a function descriptor.  Return the address
-   of the code entry point, and its section.  */
+   of the code entry point, and its section, which must be in the same
+   object as OPD_SEC.  Returns (bfd_vma) -1 on error.  */
 
 static bfd_vma
 opd_entry_value (asection *opd_sec,
@@ -5908,6 +6040,10 @@ opd_entry_value (asection *opd_sec,
          ppc64_elf_tdata (opd_bfd)->opd.contents = contents;
        }
 
+      /* PR 17512: file: 64b9dfbb.  */
+      if (offset + 7 >= opd_sec->size || offset + 7 < offset)
+       return (bfd_vma) -1;
+
       val = bfd_get_64 (opd_bfd, contents + offset);
       if (code_sec != NULL)
        {
@@ -5943,10 +6079,12 @@ opd_entry_value (asection *opd_sec,
   relocs = ppc64_elf_tdata (opd_bfd)->opd.relocs;
   if (relocs == NULL)
     relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, TRUE);
+  /* PR 17512: file: df8e1fd6.  */
+  if (relocs == NULL)
+    return (bfd_vma) -1;
 
   /* Go find the opd reloc at the sym address.  */
   lo = relocs;
-  BFD_ASSERT (lo != NULL);
   hi = lo + opd_sec->reloc_count - 1; /* ignore last reloc */
   val = (bfd_vma) -1;
   while (lo < hi)
@@ -5964,32 +6102,10 @@ opd_entry_value (asection *opd_sec,
              && ELF64_R_TYPE ((look + 1)->r_info) == R_PPC64_TOC)
            {
              unsigned long symndx = ELF64_R_SYM (look->r_info);
-             asection *sec;
+             asection *sec = NULL;
 
-             if (symndx < symtab_hdr->sh_info
-                 || elf_sym_hashes (opd_bfd) == NULL)
-               {
-                 Elf_Internal_Sym *sym;
-
-                 sym = (Elf_Internal_Sym *) symtab_hdr->contents;
-                 if (sym == NULL)
-                   {
-                     size_t symcnt = symtab_hdr->sh_info;
-                     if (elf_sym_hashes (opd_bfd) == NULL)
-                       symcnt = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
-                     sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr, symcnt,
-                                                 0, NULL, NULL, NULL);
-                     if (sym == NULL)
-                       break;
-                     symtab_hdr->contents = (bfd_byte *) sym;
-                   }
-
-                 sym += symndx;
-                 val = sym->st_value;
-                 sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx);
-                 BFD_ASSERT ((sec->flags & SEC_MERGE) == 0);
-               }
-             else
+             if (symndx >= symtab_hdr->sh_info
+                 && elf_sym_hashes (opd_bfd) != NULL)
                {
                  struct elf_link_hash_entry **sym_hashes;
                  struct elf_link_hash_entry *rh;
@@ -5999,28 +6115,51 @@ opd_entry_value (asection *opd_sec,
                  if (rh != NULL)
                    {
                      rh = elf_follow_link (rh);
-                     BFD_ASSERT (rh->root.type == bfd_link_hash_defined
-                                 || rh->root.type == bfd_link_hash_defweak);
-                     val = rh->root.u.def.value;
-                     sec = rh->root.u.def.section;
+                     if (rh->root.type != bfd_link_hash_defined
+                         && rh->root.type != bfd_link_hash_defweak)
+                       break;
+                     if (rh->root.u.def.section->owner == opd_bfd)
+                       {
+                         val = rh->root.u.def.value;
+                         sec = rh->root.u.def.section;
+                       }
+                   }
+               }
+
+             if (sec == NULL)
+               {
+                 Elf_Internal_Sym *sym;
+
+                 if (symndx < symtab_hdr->sh_info)
+                   {
+                     sym = (Elf_Internal_Sym *) symtab_hdr->contents;
+                     if (sym == NULL)
+                       {
+                         size_t symcnt = symtab_hdr->sh_info;
+                         sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr,
+                                                     symcnt, 0,
+                                                     NULL, NULL, NULL);
+                         if (sym == NULL)
+                           break;
+                         symtab_hdr->contents = (bfd_byte *) sym;
+                       }
+                     sym += symndx;
                    }
                  else
                    {
-                     /* Handle the odd case where we can be called
-                        during bfd_elf_link_add_symbols before the
-                        symbol hashes have been fully populated.  */
-                     Elf_Internal_Sym *sym;
-
-                     sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr, 1,
-                                                 symndx, NULL, NULL, NULL);
+                     sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr,
+                                                 1, symndx,
+                                                 NULL, NULL, NULL);
                      if (sym == NULL)
                        break;
-
-                     val = sym->st_value;
-                     sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx);
-                     free (sym);
                    }
+                 sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx);
+                 if (sec == NULL)
+                   break;
+                 BFD_ASSERT ((sec->flags & SEC_MERGE) == 0);
+                 val = sym->st_value;
                }
+
              val += look->r_addend;
              if (code_off != NULL)
                *code_off = val;
@@ -6031,7 +6170,7 @@ opd_entry_value (asection *opd_sec,
                  else
                    *code_sec = sec;
                }
-             if (sec != NULL && sec->output_section != NULL)
+             if (sec->output_section != NULL)
                val += sec->output_section->vma + sec->output_offset;
            }
          break;
@@ -6061,7 +6200,23 @@ ppc64_elf_maybe_function_sym (const asymbol *sym, asection *sec,
 
   if (strcmp (sym->section->name, ".opd") == 0)
     {
-      if (opd_entry_value (sym->section, sym->value,
+      struct _opd_sec_data *opd = get_opd_info (sym->section);
+      bfd_vma symval = sym->value;
+
+      if (opd != NULL
+         && opd->adjust != NULL
+         && elf_section_data (sym->section)->relocs != NULL)
+       {
+         /* opd_entry_value will use cached relocs that have been
+            adjusted, but with raw symbols.  That means both local
+            and global symbols need adjusting.  */
+         long adjust = opd->adjust[OPD_NDX (symval)];
+         if (adjust == -1)
+           return 0;
+         symval += adjust;
+       }
+
+      if (opd_entry_value (sym->section, symval,
                           &sec, code_off, TRUE) == (bfd_vma) -1)
        return 0;
       /* An old ABI binary with dot-syms has a size of 24 on the .opd
@@ -6195,10 +6350,10 @@ ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf)
   if ((eh->elf.root.type == bfd_link_hash_defined
        || eh->elf.root.type == bfd_link_hash_defweak)
       && (eh->elf.ref_dynamic
-         || (eh->elf.def_regular
+         || ((eh->elf.def_regular || ELF_COMMON_DEF_P (&eh->elf))
              && ELF_ST_VISIBILITY (eh->elf.other) != STV_INTERNAL
              && ELF_ST_VISIBILITY (eh->elf.other) != STV_HIDDEN
-             && (!info->executable
+             && (!bfd_link_executable (info)
                  || info->export_dynamic
                  || (eh->elf.dynamic
                      && d != NULL
@@ -6308,7 +6463,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
        {
          rsec->gc_mark = 1;
 
-         rsec = opd->func_sec[(sym->st_value + rel->r_addend) / 8];
+         rsec = opd->func_sec[OPD_NDX (sym->st_value + rel->r_addend)];
        }
     }
 
@@ -6328,7 +6483,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
   struct got_entry **local_got_ents;
   const Elf_Internal_Rela *rel, *relend;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   if ((sec->flags & SEC_ALLOC) == 0)
@@ -6350,6 +6505,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
       unsigned long r_symndx;
       enum elf_ppc64_reloc_type r_type;
       struct elf_link_hash_entry *h = NULL;
+      struct plt_entry **plt_list;
       unsigned char tls_type = 0;
 
       r_symndx = ELF64_R_SYM (rel->r_info);
@@ -6373,39 +6529,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
              }
        }
 
-      if (is_branch_reloc (r_type))
-       {
-         struct plt_entry **ifunc = NULL;
-         if (h != NULL)
-           {
-             if (h->type == STT_GNU_IFUNC)
-               ifunc = &h->plt.plist;
-           }
-         else if (local_got_ents != NULL)
-           {
-             struct plt_entry **local_plt = (struct plt_entry **)
-               (local_got_ents + symtab_hdr->sh_info);
-             unsigned char *local_got_tls_masks = (unsigned char *)
-               (local_plt + symtab_hdr->sh_info);
-             if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
-               ifunc = local_plt + r_symndx;
-           }
-         if (ifunc != NULL)
-           {
-             struct plt_entry *ent;
-
-             for (ent = *ifunc; ent != NULL; ent = ent->next)
-               if (ent->addend == rel->r_addend)
-                 break;
-             if (ent == NULL)
-               abort ();
-             if (ent->plt.refcount > 0)
-               ent->plt.refcount -= 1;
-             continue;
-           }
-       }
-
-      switch (r_type)
+      switch (r_type)
        {
        case R_PPC64_GOT_TLSLD16:
        case R_PPC64_GOT_TLSLD16_LO:
@@ -6471,11 +6595,23 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_REL14_BRNTAKEN:
        case R_PPC64_REL14_BRTAKEN:
        case R_PPC64_REL24:
+         plt_list = NULL;
          if (h != NULL)
+           plt_list = &h->plt.plist;
+         else if (local_got_ents != NULL)
+           {
+             struct plt_entry **local_plt = (struct plt_entry **)
+               (local_got_ents + symtab_hdr->sh_info);
+             unsigned char *local_got_tls_masks = (unsigned char *)
+               (local_plt + symtab_hdr->sh_info);
+             if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
+               plt_list = local_plt + r_symndx;
+           }
+         if (plt_list)
            {
              struct plt_entry *ent;
 
-             for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+             for (ent = *plt_list; ent != NULL; ent = ent->next)
                if (ent->addend == rel->r_addend)
                  break;
              if (ent != NULL && ent->plt.refcount > 0)
@@ -6501,10 +6637,14 @@ struct sfpr_def_parms
   bfd_byte * (*write_tail) (bfd *, bfd_byte *, int);
 };
 
-/* Auto-generate _save*, _rest* functions in .sfpr.  */
+/* Auto-generate _save*, _rest* functions in .sfpr.
+   If STUB_SEC is non-null, define alias symbols in STUB_SEC
+   instead.  */
 
 static bfd_boolean
-sfpr_define (struct bfd_link_info *info, const struct sfpr_def_parms *parm)
+sfpr_define (struct bfd_link_info *info,
+            const struct sfpr_def_parms *parm,
+            asection *stub_sec)
 {
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
   unsigned int i;
@@ -6520,26 +6660,60 @@ sfpr_define (struct bfd_link_info *info, const struct sfpr_def_parms *parm)
 
   for (i = parm->lo; i <= parm->hi; i++)
     {
-      struct elf_link_hash_entry *h;
+      struct ppc_link_hash_entry *h;
 
       sym[len + 0] = i / 10 + '0';
       sym[len + 1] = i % 10 + '0';
-      h = elf_link_hash_lookup (&htab->elf, sym, FALSE, FALSE, TRUE);
-      if (h != NULL
-         && !h->def_regular)
+      h = (struct ppc_link_hash_entry *)
+       elf_link_hash_lookup (&htab->elf, sym, FALSE, FALSE, TRUE);
+      if (stub_sec != NULL)
        {
-         h->root.type = bfd_link_hash_defined;
-         h->root.u.def.section = htab->sfpr;
-         h->root.u.def.value = htab->sfpr->size;
-         h->type = STT_FUNC;
-         h->def_regular = 1;
-         _bfd_elf_link_hash_hide_symbol (info, h, TRUE);
-         writing = TRUE;
-         if (htab->sfpr->contents == NULL)
+         if (h != NULL
+             && h->elf.root.type == bfd_link_hash_defined
+             && h->elf.root.u.def.section == htab->sfpr)
            {
-             htab->sfpr->contents = bfd_alloc (htab->elf.dynobj, SFPR_MAX);
-             if (htab->sfpr->contents == NULL)
+             struct elf_link_hash_entry *s;
+             char buf[32];
+             sprintf (buf, "%08x.%s", stub_sec->id & 0xffffffff, sym);
+             s = elf_link_hash_lookup (&htab->elf, buf, TRUE, TRUE, FALSE);
+             if (s == NULL)
                return FALSE;
+             if (s->root.type == bfd_link_hash_new
+                 || (s->root.type = bfd_link_hash_defined
+                     && s->root.u.def.section == stub_sec))
+               {
+                 s->root.type = bfd_link_hash_defined;
+                 s->root.u.def.section = stub_sec;
+                 s->root.u.def.value = (stub_sec->size
+                                        + h->elf.root.u.def.value);
+                 s->ref_regular = 1;
+                 s->def_regular = 1;
+                 s->ref_regular_nonweak = 1;
+                 s->forced_local = 1;
+                 s->non_elf = 0;
+                 s->root.linker_def = 1;
+               }
+           }
+         continue;
+       }
+      if (h != NULL)
+       {
+         h->save_res = 1;
+         if (!h->elf.def_regular)
+           {
+             h->elf.root.type = bfd_link_hash_defined;
+             h->elf.root.u.def.section = htab->sfpr;
+             h->elf.root.u.def.value = htab->sfpr->size;
+             h->elf.type = STT_FUNC;
+             h->elf.def_regular = 1;
+             _bfd_elf_link_hash_hide_symbol (info, &h->elf, TRUE);
+             writing = TRUE;
+             if (htab->sfpr->contents == NULL)
+               {
+                 htab->sfpr->contents = bfd_alloc (htab->elf.dynobj, SFPR_MAX);
+                 if (htab->sfpr->contents == NULL)
+                   return FALSE;
+               }
            }
        }
       if (writing)
@@ -6778,7 +6952,7 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
 
   fdh = lookup_fdh (fh, htab);
   if (fdh == NULL
-      && !info->executable
+      && !bfd_link_executable (info)
       && (fh->elf.root.type == bfd_link_hash_undefined
          || fh->elf.root.type == bfd_link_hash_undefweak))
     {
@@ -6811,7 +6985,7 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
 
   if (fdh != NULL
       && !fdh->elf.forced_local
-      && (!info->executable
+      && (!bfd_link_executable (info)
          || fdh->elf.def_dynamic
          || fdh->elf.ref_dynamic
          || (fdh->elf.root.type == bfd_link_hash_undefweak
@@ -6850,6 +7024,22 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
   return TRUE;
 }
 
+static const struct sfpr_def_parms save_res_funcs[] =
+  {
+    { "_savegpr0_", 14, 31, savegpr0, savegpr0_tail },
+    { "_restgpr0_", 14, 29, restgpr0, restgpr0_tail },
+    { "_restgpr0_", 30, 31, restgpr0, restgpr0_tail },
+    { "_savegpr1_", 14, 31, savegpr1, savegpr1_tail },
+    { "_restgpr1_", 14, 31, restgpr1, restgpr1_tail },
+    { "_savefpr_", 14, 31, savefpr, savefpr0_tail },
+    { "_restfpr_", 14, 29, restfpr, restfpr0_tail },
+    { "_restfpr_", 30, 31, restfpr, restfpr0_tail },
+    { "._savef", 14, 31, savefpr, savefpr1_tail },
+    { "._restf", 14, 31, restfpr, restfpr1_tail },
+    { "_savevr_", 20, 31, savevr, savevr_tail },
+    { "_restvr_", 20, 31, restvr, restvr_tail }
+  };
+
 /* Called near the start of bfd_elf_size_dynamic_sections.  We use
    this hook to a) provide some gcc support functions, and b) transfer
    dynamic linking information gathered so far on function code symbol
@@ -6861,37 +7051,27 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
 {
   struct ppc_link_hash_table *htab;
   unsigned int i;
-  static const struct sfpr_def_parms funcs[] =
-    {
-      { "_savegpr0_", 14, 31, savegpr0, savegpr0_tail },
-      { "_restgpr0_", 14, 29, restgpr0, restgpr0_tail },
-      { "_restgpr0_", 30, 31, restgpr0, restgpr0_tail },
-      { "_savegpr1_", 14, 31, savegpr1, savegpr1_tail },
-      { "_restgpr1_", 14, 31, restgpr1, restgpr1_tail },
-      { "_savefpr_", 14, 31, savefpr, savefpr0_tail },
-      { "_restfpr_", 14, 29, restfpr, restfpr0_tail },
-      { "_restfpr_", 30, 31, restfpr, restfpr0_tail },
-      { "._savef", 14, 31, savefpr, savefpr1_tail },
-      { "._restf", 14, 31, restfpr, restfpr1_tail },
-      { "_savevr_", 20, 31, savevr, savevr_tail },
-      { "_restvr_", 20, 31, restvr, restvr_tail }
-    };
 
   htab = ppc_hash_table (info);
   if (htab == NULL)
     return FALSE;
 
-  if (!info->relocatable
+  if (!bfd_link_relocatable (info)
       && htab->elf.hgot != NULL)
     {
       _bfd_elf_link_hash_hide_symbol (info, htab->elf.hgot, TRUE);
       /* Make .TOC. defined so as to prevent it being made dynamic.
         The wrong value here is fixed later in ppc64_elf_set_toc.  */
+      if (!htab->elf.hgot->def_regular
+         || htab->elf.hgot->root.type != bfd_link_hash_defined)
+       {
+         htab->elf.hgot->root.type = bfd_link_hash_defined;
+         htab->elf.hgot->root.u.def.value = 0;
+         htab->elf.hgot->root.u.def.section = bfd_abs_section_ptr;
+         htab->elf.hgot->def_regular = 1;
+         htab->elf.hgot->root.linker_def = 1;
+       }
       htab->elf.hgot->type = STT_OBJECT;
-      htab->elf.hgot->root.type = bfd_link_hash_defined;
-      htab->elf.hgot->root.u.def.value = 0;
-      htab->elf.hgot->root.u.def.section = bfd_abs_section_ptr;
-      htab->elf.hgot->def_regular = 1;
       htab->elf.hgot->other = ((htab->elf.hgot->other & ~ELF_ST_VISIBILITY (-1))
                               | STV_HIDDEN);
     }
@@ -6903,8 +7083,8 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
   /* Provide any missing _save* and _rest* functions.  */
   htab->sfpr->size = 0;
   if (htab->params->save_restore_funcs)
-    for (i = 0; i < sizeof (funcs) / sizeof (funcs[0]); i++)
-      if (!sfpr_define (info, &funcs[i]))
+    for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
+      if (!sfpr_define (info, &save_res_funcs[i], NULL))
        return FALSE;
 
   elf_link_hash_traverse (&htab->elf, func_desc_adjust, info);
@@ -6966,13 +7146,27 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
          || (h->type != STT_GNU_IFUNC
              && (SYMBOL_CALLS_LOCAL (info, h)
                  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-                     && h->root.type == bfd_link_hash_undefweak))))
+                     && h->root.type == bfd_link_hash_undefweak)))
+         || ((struct ppc_link_hash_entry *) h)->save_res)
        {
          h->plt.plist = NULL;
          h->needs_plt = 0;
+         h->pointer_equality_needed = 0;
        }
       else if (abiversion (info->output_bfd) == 2)
        {
+         /* Taking a function's address in a read/write section
+            doesn't require us to define the function symbol in the
+            executable on a global entry stub.  A dynamic reloc can
+            be used instead.  */
+         if (h->pointer_equality_needed
+             && h->type != STT_GNU_IFUNC
+             && !readonly_dynrelocs (h))
+           {
+             h->pointer_equality_needed = 0;
+             h->non_got_ref = 0;
+           }
+
          /* After adjust_dynamic_symbol, non_got_ref set in the
             non-shared case means that we have allocated space in
             .dynbss for the symbol and thus dyn_relocs for this
@@ -6982,10 +7176,10 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
             relocations against this symbol to the PLT entry.  Allow
             dynamic relocs if the reference is weak, and the dynamic
             relocs will not cause text relocation.  */
-         if (!h->ref_regular_nonweak
-             && h->non_got_ref
-             && h->type != STT_GNU_IFUNC
-             && !readonly_dynrelocs (h))
+         else if (!h->ref_regular_nonweak
+                  && h->non_got_ref
+                  && h->type != STT_GNU_IFUNC
+                  && !readonly_dynrelocs (h))
            h->non_got_ref = 0;
 
          /* If making a plt entry, then we don't need copy relocs.  */
@@ -7013,7 +7207,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
      only references to the symbol are via the global offset table.
      For such cases we need not do anything here; the relocations will
      be handled correctly by relocate_section.  */
-  if (info->shared)
+  if (bfd_link_pic (info))
     return TRUE;
 
   /* If there are no references to this symbol that do not use the
@@ -7025,6 +7219,13 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   if (!h->def_dynamic || !h->ref_regular || h->def_regular)
     return TRUE;
 
+  /* If -z nocopyreloc was given, don't generate them either.  */
+  if (info->nocopyreloc)
+    {
+      h->non_got_ref = 0;
+      return TRUE;
+    }
+
   /* If we didn't find any dynamic relocs in read-only sections, then
      we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
   if (ELIMINATE_COPY_RELOCS && !readonly_dynrelocs (h))
@@ -7033,6 +7234,16 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       return TRUE;
     }
 
+  /* Protected variables do not work with .dynbss.  The copy in
+     .dynbss won't be used by the shared library with the protected
+     definition for the variable.  Text relocations are preferable
+     to an incorrect program.  */
+  if (h->protected_def)
+    {
+      h->non_got_ref = 0;
+      return TRUE;
+    }
+
   if (h->plt.plist != NULL)
     {
       /* We should never get here, but unfortunately there are versions
@@ -7071,7 +7282,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   s = htab->dynbss;
 
-  return _bfd_elf_adjust_dynamic_copy (h, s);
+  return _bfd_elf_adjust_dynamic_copy (info, h, s);
 }
 
 /* If given a function descriptor symbol, hide both the function code
@@ -7356,7 +7567,7 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
   opd = get_opd_info (sym_sec);
   if (opd != NULL && opd->adjust != NULL)
     {
-      long adjust = opd->adjust[eh->elf.root.u.def.value / 8];
+      long adjust = opd->adjust[OPD_NDX (eh->elf.root.u.def.value)];
       if (adjust == -1)
        {
          /* This entry has been deleted.  */
@@ -7415,7 +7626,7 @@ dec_dynrel_count (bfd_vma r_info,
     case R_PPC64_TPREL16_HIGHERA:
     case R_PPC64_TPREL16_HIGHEST:
     case R_PPC64_TPREL16_HIGHESTA:
-      if (!info->shared)
+      if (!bfd_link_pic (info))
        return TRUE;
 
     case R_PPC64_TPREL64:
@@ -7459,14 +7670,14 @@ dec_dynrel_count (bfd_vma r_info,
        return FALSE;
     }
 
-  if ((info->shared
+  if ((bfd_link_pic (info)
        && (must_be_dyn_reloc (info, r_type)
           || (h != NULL
               && (!SYMBOLIC_BIND (info, h)
                   || h->root.type == bfd_link_hash_defweak
                   || !h->def_regular))))
       || (ELIMINATE_COPY_RELOCS
-         && !info->shared
+         && !bfd_link_pic (info)
          && h != NULL
          && (h->root.type == bfd_link_hash_defweak
              || !h->def_regular)))
@@ -7563,9 +7774,8 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
       Elf_Internal_Rela *relstart, *rel, *relend;
       Elf_Internal_Shdr *symtab_hdr;
       Elf_Internal_Sym *local_syms;
-      bfd_vma offset;
       struct _opd_sec_data *opd;
-      bfd_boolean need_edit, add_aux_fields;
+      bfd_boolean need_edit, add_aux_fields, broken;
       bfd_size_type cnt_16b = 0;
 
       if (!is_ppc64_elf (ibfd))
@@ -7597,8 +7807,8 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
       /* First run through the relocs to check they are sane, and to
         determine whether we need to edit this opd section.  */
       need_edit = FALSE;
+      broken = FALSE;
       need_pad = sec;
-      offset = 0;
       relend = relstart + sec->reloc_count;
       for (rel = relstart; rel < relend; )
        {
@@ -7607,13 +7817,14 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
          asection *sym_sec;
          struct elf_link_hash_entry *h;
          Elf_Internal_Sym *sym;
+         bfd_vma offset;
 
-         /* .opd contains a regular array of 16 or 24 byte entries.  We're
+         /* .opd contains an array of 16 or 24 byte entries.  We're
             only interested in the reloc pointing to a function entry
             point.  */
-         if (rel->r_offset != offset
-             || rel + 1 >= relend
-             || (rel + 1)->r_offset != offset + 8)
+         offset = rel->r_offset;
+         if (rel + 1 == relend
+             || rel[1].r_offset != offset + 8)
            {
              /* If someone messes with .opd alignment then after a
                 "ld -r" we might have padding in the middle of .opd.
@@ -7623,7 +7834,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
            broken_opd:
              (*_bfd_error_handler)
                (_("%B: .opd is not a regular array of opd entries"), ibfd);
-             need_edit = FALSE;
+             broken = TRUE;
              break;
            }
 
@@ -7633,7 +7844,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
              (*_bfd_error_handler)
                (_("%B: unexpected reloc type %u in .opd section"),
                 ibfd, r_type);
-             need_edit = FALSE;
+             broken = TRUE;
              break;
            }
 
@@ -7654,7 +7865,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
              (*_bfd_error_handler)
                (_("%B: undefined sym `%s' in .opd section"),
                 ibfd, sym_name);
-             need_edit = FALSE;
+             broken = TRUE;
              break;
            }
 
@@ -7670,39 +7881,33 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
            need_edit = TRUE;
 
          rel += 2;
-         if (rel == relend
-             || (rel + 1 == relend && rel->r_offset == offset + 16))
+         if (rel + 1 == relend
+             || (rel + 2 < relend
+                 && ELF64_R_TYPE (rel[2].r_info) == R_PPC64_TOC))
+           ++rel;
+
+         if (rel == relend)
            {
              if (sec->size == offset + 24)
                {
                  need_pad = NULL;
                  break;
                }
-             if (rel == relend && sec->size == offset + 16)
+             if (sec->size == offset + 16)
                {
                  cnt_16b++;
                  break;
                }
              goto broken_opd;
            }
-
-         if (rel->r_offset == offset + 24)
-           offset += 24;
-         else if (rel->r_offset != offset + 16)
-           goto broken_opd;
          else if (rel + 1 < relend
                   && ELF64_R_TYPE (rel[0].r_info) == R_PPC64_ADDR64
                   && ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOC)
            {
-             offset += 16;
-             cnt_16b++;
-           }
-         else if (rel + 2 < relend
-                  && ELF64_R_TYPE (rel[1].r_info) == R_PPC64_ADDR64
-                  && ELF64_R_TYPE (rel[2].r_info) == R_PPC64_TOC)
-           {
-             offset += 24;
-             rel += 1;
+             if (rel[0].r_offset == offset + 16)
+               cnt_16b++;
+             else if (rel[0].r_offset != offset + 24)
+               goto broken_opd;
            }
          else
            goto broken_opd;
@@ -7710,18 +7915,16 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
 
       add_aux_fields = htab->params->non_overlapping_opd && cnt_16b > 0;
 
-      if (need_edit || add_aux_fields)
+      if (!broken && (need_edit || add_aux_fields))
        {
          Elf_Internal_Rela *write_rel;
          Elf_Internal_Shdr *rel_hdr;
          bfd_byte *rptr, *wptr;
          bfd_byte *new_contents;
-         bfd_boolean skip;
-         long opd_ent_size;
          bfd_size_type amt;
 
          new_contents = NULL;
-         amt = sec->size * sizeof (long) / 8;
+         amt = OPD_NDX (sec->size) * sizeof (long);
          opd = &ppc64_elf_section_data (sec)->u.opd;
          opd->adjust = bfd_zalloc (sec->owner, amt);
          if (opd->adjust == NULL)
@@ -7759,123 +7962,134 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
              new_contents = bfd_malloc (sec->size + cnt_16b * 8);
              if (new_contents == NULL)
                return FALSE;
-             need_pad = FALSE;
+             need_pad = NULL;
            }
          wptr = new_contents;
          rptr = sec->contents;
-
          write_rel = relstart;
-         skip = FALSE;
-         offset = 0;
-         opd_ent_size = 0;
-         for (rel = relstart; rel < relend; rel++)
+         for (rel = relstart; rel < relend; )
            {
              unsigned long r_symndx;
              asection *sym_sec;
              struct elf_link_hash_entry *h;
+             struct ppc_link_hash_entry *fdh = NULL;
              Elf_Internal_Sym *sym;
+             long opd_ent_size;
+             Elf_Internal_Rela *next_rel;
+             bfd_boolean skip;
 
              r_symndx = ELF64_R_SYM (rel->r_info);
              if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
                              r_symndx, ibfd))
                goto error_ret;
 
-             if (rel->r_offset == offset)
+             next_rel = rel + 2;
+             if (next_rel + 1 == relend
+                 || (next_rel + 2 < relend
+                     && ELF64_R_TYPE (next_rel[2].r_info) == R_PPC64_TOC))
+               ++next_rel;
+
+             /* See if the .opd entry is full 24 byte or
+                16 byte (with fd_aux entry overlapped with next
+                fd_func).  */
+             opd_ent_size = 24;
+             if (next_rel == relend)
                {
-                 struct ppc_link_hash_entry *fdh = NULL;
-
-                 /* See if the .opd entry is full 24 byte or
-                    16 byte (with fd_aux entry overlapped with next
-                    fd_func).  */
-                 opd_ent_size = 24;
-                 if ((rel + 2 == relend && sec->size == offset + 16)
-                     || (rel + 3 < relend
-                         && rel[2].r_offset == offset + 16
-                         && rel[3].r_offset == offset + 24
-                         && ELF64_R_TYPE (rel[2].r_info) == R_PPC64_ADDR64
-                         && ELF64_R_TYPE (rel[3].r_info) == R_PPC64_TOC))
+                 if (sec->size == rel->r_offset + 16)
                    opd_ent_size = 16;
+               }
+             else if (next_rel->r_offset == rel->r_offset + 16)
+               opd_ent_size = 16;
 
-                 if (h != NULL
-                     && h->root.root.string[0] == '.')
-                   {
-                     fdh = lookup_fdh ((struct ppc_link_hash_entry *) h, htab);
-                     if (fdh != NULL
-                         && fdh->elf.root.type != bfd_link_hash_defined
-                         && fdh->elf.root.type != bfd_link_hash_defweak)
-                       fdh = NULL;
-                   }
+             if (h != NULL
+                 && h->root.root.string[0] == '.')
+               {
+                 fdh = lookup_fdh ((struct ppc_link_hash_entry *) h, htab);
+                 if (fdh != NULL
+                     && fdh->elf.root.type != bfd_link_hash_defined
+                     && fdh->elf.root.type != bfd_link_hash_defweak)
+                   fdh = NULL;
+               }
 
-                 skip = (sym_sec->owner != ibfd
-                         || sym_sec->output_section == bfd_abs_section_ptr);
-                 if (skip)
+             skip = (sym_sec->owner != ibfd
+                     || sym_sec->output_section == bfd_abs_section_ptr);
+             if (skip)
+               {
+                 if (fdh != NULL && sym_sec->owner == ibfd)
                    {
-                     if (fdh != NULL && sym_sec->owner == ibfd)
-                       {
-                         /* Arrange for the function descriptor sym
-                            to be dropped.  */
-                         fdh->elf.root.u.def.value = 0;
-                         fdh->elf.root.u.def.section = sym_sec;
-                       }
-                     opd->adjust[rel->r_offset / 8] = -1;
+                     /* Arrange for the function descriptor sym
+                        to be dropped.  */
+                     fdh->elf.root.u.def.value = 0;
+                     fdh->elf.root.u.def.section = sym_sec;
                    }
-                 else
-                   {
-                     /* We'll be keeping this opd entry.  */
+                 opd->adjust[OPD_NDX (rel->r_offset)] = -1;
 
-                     if (fdh != NULL)
-                       {
-                         /* Redefine the function descriptor symbol to
-                            this location in the opd section.  It is
-                            necessary to update the value here rather
-                            than using an array of adjustments as we do
-                            for local symbols, because various places
-                            in the generic ELF code use the value
-                            stored in u.def.value.  */
-                         fdh->elf.root.u.def.value = wptr - new_contents;
-                         fdh->adjust_done = 1;
-                       }
+                 if (NO_OPD_RELOCS || bfd_link_relocatable (info))
+                   rel = next_rel;
+                 else
+                   while (1)
+                     {
+                       if (!dec_dynrel_count (rel->r_info, sec, info,
+                                              NULL, h, sym))
+                         goto error_ret;
 
-                     /* Local syms are a bit tricky.  We could
-                        tweak them as they can be cached, but
-                        we'd need to look through the local syms
-                        for the function descriptor sym which we
-                        don't have at the moment.  So keep an
-                        array of adjustments.  */
-                     opd->adjust[rel->r_offset / 8]
-                       = (wptr - new_contents) - (rptr - sec->contents);
-
-                     if (wptr != rptr)
-                       memcpy (wptr, rptr, opd_ent_size);
-                     wptr += opd_ent_size;
-                     if (add_aux_fields && opd_ent_size == 16)
-                       {
-                         memset (wptr, '\0', 8);
-                         wptr += 8;
-                       }
-                   }
-                 rptr += opd_ent_size;
-                 offset += opd_ent_size;
-               }
+                       if (++rel == next_rel)
+                         break;
 
-             if (skip)
-               {
-                 if (!NO_OPD_RELOCS
-                     && !info->relocatable
-                     && !dec_dynrel_count (rel->r_info, sec, info,
-                                           NULL, h, sym))
-                   goto error_ret;
+                       r_symndx = ELF64_R_SYM (rel->r_info);
+                       if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
+                                       r_symndx, ibfd))
+                         goto error_ret;
+                     }
                }
              else
                {
+                 /* We'll be keeping this opd entry.  */
+                 long adjust;
+
+                 if (fdh != NULL)
+                   {
+                     /* Redefine the function descriptor symbol to
+                        this location in the opd section.  It is
+                        necessary to update the value here rather
+                        than using an array of adjustments as we do
+                        for local symbols, because various places
+                        in the generic ELF code use the value
+                        stored in u.def.value.  */
+                     fdh->elf.root.u.def.value = wptr - new_contents;
+                     fdh->adjust_done = 1;
+                   }
+
+                 /* Local syms are a bit tricky.  We could
+                    tweak them as they can be cached, but
+                    we'd need to look through the local syms
+                    for the function descriptor sym which we
+                    don't have at the moment.  So keep an
+                    array of adjustments.  */
+                 adjust = (wptr - new_contents) - (rptr - sec->contents);
+                 opd->adjust[OPD_NDX (rel->r_offset)] = adjust;
+
+                 if (wptr != rptr)
+                   memcpy (wptr, rptr, opd_ent_size);
+                 wptr += opd_ent_size;
+                 if (add_aux_fields && opd_ent_size == 16)
+                   {
+                     memset (wptr, '\0', 8);
+                     wptr += 8;
+                   }
+
                  /* We need to adjust any reloc offsets to point to the
-                    new opd entries.  While we're at it, we may as well
-                    remove redundant relocs.  */
-                 rel->r_offset += opd->adjust[(offset - opd_ent_size) / 8];
-                 if (write_rel != rel)
-                   memcpy (write_rel, rel, sizeof (*rel));
-                 ++write_rel;
+                    new opd entries.  */
+                 for ( ; rel != next_rel; ++rel)
+                   {
+                     rel->r_offset += adjust;
+                     if (write_rel != rel)
+                       memcpy (write_rel, rel, sizeof (*rel));
+                     ++write_rel;
+                   }
                }
+
+             rptr += opd_ent_size;
            }
 
          sec->size = wptr - new_contents;
@@ -7910,7 +8124,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
 
   /* If we are doing a final link and the last .opd entry is just 16 byte
      long, add a 8 byte padding after it.  */
-  if (need_pad != NULL && !info->relocatable)
+  if (need_pad != NULL && !bfd_link_relocatable (info))
     {
       bfd_byte *p;
 
@@ -7973,7 +8187,7 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
   htab->tls_get_addr_fd = ((struct ppc_link_hash_entry *)
                           elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
                                                 FALSE, FALSE, TRUE));
-  if (!htab->params->no_tls_get_addr_opt)
+  if (htab->params->tls_get_addr_opt)
     {
       struct elf_link_hash_entry *opt, *opt_fd, *tga, *tga_fd;
 
@@ -8040,8 +8254,8 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
                }
            }
        }
-      else
-       htab->params->no_tls_get_addr_opt = TRUE;
+      else if (htab->params->tls_get_addr_opt < 0)
+       htab->params->tls_get_addr_opt = 0;
     }
   return _bfd_elf_tls_setup (info->output_bfd, info);
 }
@@ -8088,7 +8302,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
   unsigned char *toc_ref;
   int pass;
 
-  if (info->relocatable || !info->executable)
+  if (!bfd_link_executable (info))
     return TRUE;
 
   htab = ppc_hash_table (info);
@@ -8183,7 +8397,8 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                      if (h != NULL
                          && h->root.type == bfd_link_hash_undefweak)
                        ok_tprel = TRUE;
-                     else
+                     else if (sym_sec != NULL
+                              && sym_sec->output_section != NULL)
                        {
                          value += sym_sec->output_offset;
                          value += sym_sec->output_section->vma;
@@ -8295,7 +8510,10 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                      else
                        value = sym->st_value;
                      value += rel->r_addend;
-                     BFD_ASSERT (value < toc->size && value % 8 == 0);
+                     if (value % 8 != 0)
+                       continue;
+                     BFD_ASSERT (value < toc->size
+                                 && toc->output_offset % 8 == 0);
                      toc_ref_index = (value + toc->output_offset) / 8;
                      if (r_type == R_PPC64_TLS
                          || r_type == R_PPC64_TLSGD
@@ -8741,6 +8959,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                goto error_ret;
 
              if (sym_sec == NULL
+                 || sym_sec->output_section == NULL
                  || discarded_section (sym_sec))
                continue;
 
@@ -9279,7 +9498,7 @@ allocate_got (struct elf_link_hash_entry *h,
       htab->elf.irelplt->size += rentsize;
       htab->got_reli_size += rentsize;
     }
-  else if ((info->shared
+  else if ((bfd_link_pic (info)
            || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
           && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
               || h->root.type != bfd_link_hash_undefweak))
@@ -9332,7 +9551,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
   if ((htab->elf.dynamic_sections_created
        && h->dynindx != -1
-       && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
+       && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
       || h->type == STT_GNU_IFUNC)
     {
       struct plt_entry *pent;
@@ -9475,7 +9694,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
      space for relocs that have become local due to symbol visibility
      changes.  */
 
-  if (info->shared)
+  if (bfd_link_pic (info))
     {
       /* Relocs that use pc_count are those that appear on a call insn,
         or certain REL relocs (see must_be_dyn_reloc) that can be
@@ -9649,7 +9868,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (info->executable)
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
@@ -9741,7 +9960,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
                        htab->elf.irelplt->size += rel_size;
                        htab->got_reli_size += rel_size;
                      }
-                   else if (info->shared)
+                   else if (bfd_link_pic (info))
                      {
                        asection *srel = ppc64_elf_tdata (ibfd)->relgot;
                        srel->size += rel_size;
@@ -9779,7 +9998,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
   if (htab->glink != NULL)
     htab->glink->rawsize = htab->glink->size;
 
-  if (!htab->opd_abi && !info->shared)
+  if (!htab->opd_abi && !bfd_link_pic (info))
     elf_link_hash_traverse (&htab->elf, size_global_entry_stubs, info);
 
   first_tlsld = NULL;
@@ -9806,7 +10025,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
              ent->got.offset = s->size;
              ent->owner = ibfd;
              s->size += 16;
-             if (info->shared)
+             if (bfd_link_pic (info))
                {
                  asection *srel = ppc64_elf_tdata (ibfd)->relgot;
                  srel->size += sizeof (Elf64_External_Rela);
@@ -9936,7 +10155,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
 #define add_dynamic_entry(TAG, VAL) \
   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
-      if (info->executable)
+      if (bfd_link_executable (info))
        {
          if (!add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
@@ -9959,7 +10178,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
            return FALSE;
        }
 
-      tls_opt = (!htab->params->no_tls_get_addr_opt
+      tls_opt = (htab->params->tls_get_addr_opt
                 && htab->tls_get_addr_fd != NULL
                 && htab->tls_get_addr_fd->elf.plt.plist != NULL);
       if (tls_opt || !htab->opd_abi)
@@ -10133,7 +10352,10 @@ plt_stub_size (struct ppc_link_hash_table *htab,
       size += 4;
       if (htab->params->plt_static_chain)
        size += 4;
-      if (htab->params->plt_thread_safe)
+      if (htab->params->plt_thread_safe
+         && htab->elf.dynamic_sections_created
+         && stub_entry->h != NULL
+         && stub_entry->h->elf.dynindx != -1)
        size += 8;
       if (PPC_HA (off + 8 + 8 * htab->params->plt_static_chain) != PPC_HA (off))
        size += 4;
@@ -10141,7 +10363,7 @@ plt_stub_size (struct ppc_link_hash_table *htab,
   if (stub_entry->h != NULL
       && (stub_entry->h == htab->tls_get_addr_fd
          || stub_entry->h == htab->tls_get_addr)
-      && !htab->params->no_tls_get_addr_opt)
+      && htab->params->tls_get_addr_opt)
     size += 13 * 4;
   return size;
 }
@@ -10155,10 +10377,10 @@ plt_stub_pad (struct ppc_link_hash_table *htab,
 {
   int stub_align = 1 << htab->params->plt_stub_align;
   unsigned stub_size = plt_stub_size (htab, stub_entry, plt_off);
-  bfd_vma stub_off = stub_entry->stub_sec->size;
+  bfd_vma stub_off = stub_entry->group->stub_sec->size;
 
   if (((stub_off + stub_size - 1) & -stub_align) - (stub_off & -stub_align)
-      > (stub_size & -stub_align))
+      > ((stub_size - 1) & -stub_align))
     return stub_align - (stub_off & (stub_align - 1));
   return 0;
 }
@@ -10173,17 +10395,19 @@ build_plt_stub (struct ppc_link_hash_table *htab,
   bfd *obfd = htab->params->stub_bfd;
   bfd_boolean plt_load_toc = htab->opd_abi;
   bfd_boolean plt_static_chain = htab->params->plt_static_chain;
-  bfd_boolean plt_thread_safe = htab->params->plt_thread_safe;
+  bfd_boolean plt_thread_safe = (htab->params->plt_thread_safe
+                                && htab->elf.dynamic_sections_created
+                                && stub_entry->h != NULL
+                                && stub_entry->h->elf.dynindx != -1);
   bfd_boolean use_fake_dep = plt_thread_safe;
   bfd_vma cmp_branch_off = 0;
 
   if (!ALWAYS_USE_FAKE_DEP
       && plt_load_toc
       && plt_thread_safe
-      && !(stub_entry->h != NULL
-          && (stub_entry->h == htab->tls_get_addr_fd
-              || stub_entry->h == htab->tls_get_addr)
-          && !htab->params->no_tls_get_addr_opt))
+      && !((stub_entry->h == htab->tls_get_addr_fd
+           || stub_entry->h == htab->tls_get_addr)
+          && htab->params->tls_get_addr_opt))
     {
       bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
       bfd_vma pltindex = ((pltoff - PLT_INITIAL_ENTRY_SIZE (htab))
@@ -10196,7 +10420,7 @@ build_plt_stub (struct ppc_link_hash_table *htab,
       to = (glinkoff
            + htab->glink->output_offset
            + htab->glink->output_section->vma);
-      from = (p - stub_entry->stub_sec->contents
+      from = (p - stub_entry->group->stub_sec->contents
              + 4 * (ALWAYS_EMIT_R2SAVE
                     || stub_entry->stub_type == ppc_stub_plt_call_r2save)
              + 4 * (PPC_HA (offset) != 0)
@@ -10204,8 +10428,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
                     != PPC_HA (offset))
              + 4 * (plt_static_chain != 0)
              + 20
-             + stub_entry->stub_sec->output_offset
-             + stub_entry->stub_sec->output_section->vma);
+             + stub_entry->group->stub_sec->output_offset
+             + stub_entry->group->stub_sec->output_section->vma);
       cmp_branch_off = to - from;
       use_fake_dep = cmp_branch_off + (1 << 25) >= (1 << 26);
     }
@@ -10375,8 +10599,8 @@ build_tls_get_addr_stub (struct ppc_link_hash_table *htab,
   p = build_plt_stub (htab, stub_entry, p, offset, r);
   bfd_put_32 (obfd, BCTRL, p - 4);
 
-  bfd_put_32 (obfd, LD_R11_0R1 + STK_LINKER (htab), p),        p += 4;
   bfd_put_32 (obfd, LD_R2_0R1 + STK_TOC (htab), p),    p += 4;
+  bfd_put_32 (obfd, LD_R11_0R1 + STK_LINKER (htab), p),        p += 4;
   bfd_put_32 (obfd, MTLR_R11, p),              p += 4;
   bfd_put_32 (obfd, BLR, p),                   p += 4;
 
@@ -10418,7 +10642,7 @@ get_r2off (struct bfd_link_info *info,
           struct ppc_stub_hash_entry *stub_entry)
 {
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
-  bfd_vma r2off = htab->stub_group[stub_entry->target_section->id].toc_off;
+  bfd_vma r2off = htab->sec_info[stub_entry->target_section->id].toc_off;
 
   if (r2off == 0)
     {
@@ -10436,14 +10660,14 @@ get_r2off (struct bfd_link_info *info,
          info->callbacks->einfo (_("%P: cannot find opd entry toc for `%T'\n"),
                                  stub_entry->h->elf.root.root.string);
          bfd_set_error (bfd_error_bad_value);
-         return 0;
+         return (bfd_vma) -1;
        }
       if (!bfd_get_section_contents (opd->owner, opd, buf, opd_off + 8, 8))
-       return 0;
+       return (bfd_vma) -1;
       r2off = bfd_get_64 (opd->owner, buf);
       r2off -= elf_gp (info->output_bfd);
     }
-  r2off -= htab->stub_group[stub_entry->id_sec->id].toc_off;
+  r2off -= htab->sec_info[stub_entry->group->link_sec->id].toc_off;
   return r2off;
 }
 
@@ -10470,8 +10694,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
     return FALSE;
 
   /* Make a note of the offset within the stubs for this entry.  */
-  stub_entry->stub_offset = stub_entry->stub_sec->size;
-  loc = stub_entry->stub_sec->contents + stub_entry->stub_offset;
+  stub_entry->stub_offset = stub_entry->group->stub_sec->size;
+  loc = stub_entry->group->stub_sec->contents + stub_entry->stub_offset;
 
   htab->stub_count[stub_entry->stub_type - 1] += 1;
   switch (stub_entry->stub_type)
@@ -10487,31 +10711,36 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       /* And this is where we are coming from.  */
       off -= (stub_entry->stub_offset
-             + stub_entry->stub_sec->output_offset
-             + stub_entry->stub_sec->output_section->vma);
+             + stub_entry->group->stub_sec->output_offset
+             + stub_entry->group->stub_sec->output_section->vma);
 
       size = 4;
       if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
        {
          bfd_vma r2off = get_r2off (info, stub_entry);
 
-         if (r2off == 0)
+         if (r2off == (bfd_vma) -1)
            {
              htab->stub_error = TRUE;
              return FALSE;
            }
          bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc);
          loc += 4;
-         size = 12;
+         size = 8;
          if (PPC_HA (r2off) != 0)
            {
-             size = 16;
              bfd_put_32 (htab->params->stub_bfd,
                          ADDIS_R2_R2 | PPC_HA (r2off), loc);
              loc += 4;
+             size += 4;
+           }
+         if (PPC_LO (r2off) != 0)
+           {
+             bfd_put_32 (htab->params->stub_bfd,
+                         ADDI_R2_R2 | PPC_LO (r2off), loc);
+             loc += 4;
+             size += 4;
            }
-         bfd_put_32 (htab->params->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc);
-         loc += 4;
          off -= size - 4;
        }
       bfd_put_32 (htab->params->stub_bfd, B_DOT | (off & 0x3fffffc), loc);
@@ -10527,10 +10756,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       if (info->emitrelocations)
        {
-         r = get_relocs (stub_entry->stub_sec, 1);
+         r = get_relocs (stub_entry->group->stub_sec, 1);
          if (r == NULL)
            return FALSE;
-         r->r_offset = loc - stub_entry->stub_sec->contents;
+         r->r_offset = loc - stub_entry->group->stub_sec->contents;
          r->r_info = ELF64_R_INFO (0, R_PPC64_REL24);
          r->r_addend = dest;
          if (stub_entry->h != NULL)
@@ -10637,7 +10866,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       off = (dest
             - elf_gp (htab->brlt->output_section->owner)
-            - htab->stub_group[stub_entry->id_sec->id].toc_off);
+            - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
        {
@@ -10651,10 +10880,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       if (info->emitrelocations)
        {
-         r = get_relocs (stub_entry->stub_sec, 1 + (PPC_HA (off) != 0));
+         r = get_relocs (stub_entry->group->stub_sec, 1 + (PPC_HA (off) != 0));
          if (r == NULL)
            return FALSE;
-         r[0].r_offset = loc - stub_entry->stub_sec->contents;
+         r[0].r_offset = loc - stub_entry->group->stub_sec->contents;
          if (bfd_big_endian (info->output_bfd))
            r[0].r_offset += 2;
          if (stub_entry->stub_type == ppc_stub_plt_branch_r2off)
@@ -10692,7 +10921,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        {
          bfd_vma r2off = get_r2off (info, stub_entry);
 
-         if (r2off == 0 && htab->opd_abi)
+         if (r2off == (bfd_vma) -1)
            {
              htab->stub_error = TRUE;
              return FALSE;
@@ -10743,11 +10972,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          struct ppc_link_hash_entry *fh = ppc_follow_link (stub_entry->h->oh);
 
          /* If the old-ABI "dot-symbol" is undefined make it weak so
-            we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL.
-            FIXME: We used to define the symbol on one of the call
-            stubs instead, which is why we test symbol section id
-            against htab->top_id in various places.  Likely all
-            these checks could now disappear.  */
+            we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL.  */
          if (fh->elf.root.type == bfd_link_hash_undefined)
            fh->elf.root.type = bfd_link_hash_undefweak;
          /* Stop undo_symbol_twiddle changing it back to undefined.  */
@@ -10791,7 +11016,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       off = (dest
             - elf_gp (plt->output_section->owner)
-            - htab->stub_group[stub_entry->id_sec->id].toc_off);
+            - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
        {
@@ -10809,15 +11034,15 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        {
          unsigned pad = plt_stub_pad (htab, stub_entry, off);
 
-         stub_entry->stub_sec->size += pad;
-         stub_entry->stub_offset = stub_entry->stub_sec->size;
+         stub_entry->group->stub_sec->size += pad;
+         stub_entry->stub_offset = stub_entry->group->stub_sec->size;
          loc += pad;
        }
 
       r = NULL;
       if (info->emitrelocations)
        {
-         r = get_relocs (stub_entry->stub_sec,
+         r = get_relocs (stub_entry->group->stub_sec,
                          ((PPC_HA (off) != 0)
                           + (htab->opd_abi
                              ? 2 + (htab->params->plt_static_chain
@@ -10825,7 +11050,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
                              : 1)));
          if (r == NULL)
            return FALSE;
-         r[0].r_offset = loc - stub_entry->stub_sec->contents;
+         r[0].r_offset = loc - stub_entry->group->stub_sec->contents;
          if (bfd_big_endian (info->output_bfd))
            r[0].r_offset += 2;
          r[0].r_addend = dest;
@@ -10833,19 +11058,22 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (stub_entry->h != NULL
          && (stub_entry->h == htab->tls_get_addr_fd
              || stub_entry->h == htab->tls_get_addr)
-         && !htab->params->no_tls_get_addr_opt)
+         && htab->params->tls_get_addr_opt)
        p = build_tls_get_addr_stub (htab, stub_entry, loc, off, r);
       else
        p = build_plt_stub (htab, stub_entry, loc, off, r);
       size = p - loc;
       break;
 
+    case ppc_stub_save_res:
+      return TRUE;
+
     default:
       BFD_FAIL ();
       return FALSE;
     }
 
-  stub_entry->stub_sec->size += size;
+  stub_entry->group->stub_sec->size += size;
 
   if (htab->params->emit_stub_syms)
     {
@@ -10873,13 +11101,14 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (h->root.type == bfd_link_hash_new)
        {
          h->root.type = bfd_link_hash_defined;
-         h->root.u.def.section = stub_entry->stub_sec;
+         h->root.u.def.section = stub_entry->group->stub_sec;
          h->root.u.def.value = stub_entry->stub_offset;
          h->ref_regular = 1;
          h->def_regular = 1;
          h->ref_regular_nonweak = 1;
          h->forced_local = 1;
          h->non_elf = 0;
+         h->root.linker_def = 1;
        }
     }
 
@@ -10907,6 +11136,18 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   if (htab == NULL)
     return FALSE;
 
+  if (stub_entry->h != NULL
+      && stub_entry->h->save_res
+      && stub_entry->h->elf.root.type == bfd_link_hash_defined
+      && stub_entry->h->elf.root.u.def.section == htab->sfpr)
+    {
+      /* Don't make stubs to out-of-line register save/restore
+        functions.  Instead, emit copies of the functions.  */
+      stub_entry->group->needs_save_res = 1;
+      stub_entry->stub_type = ppc_stub_save_res;
+      return TRUE;
+    }
+
   if (stub_entry->stub_type == ppc_stub_plt_call
       || stub_entry->stub_type == ppc_stub_plt_call_r2save)
     {
@@ -10922,20 +11163,20 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       off += (plt->output_offset
              + plt->output_section->vma
              - elf_gp (plt->output_section->owner)
-             - htab->stub_group[stub_entry->id_sec->id].toc_off);
+             - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       size = plt_stub_size (htab, stub_entry, off);
       if (htab->params->plt_stub_align)
        size += plt_stub_pad (htab, stub_entry, off);
       if (info->emitrelocations)
        {
-         stub_entry->stub_sec->reloc_count
+         stub_entry->group->stub_sec->reloc_count
            += ((PPC_HA (off) != 0)
                + (htab->opd_abi
                   ? 2 + (htab->params->plt_static_chain
                          && PPC_HA (off + 16) == PPC_HA (off))
                   : 1));
-         stub_entry->stub_sec->flags |= SEC_RELOC;
+         stub_entry->group->stub_sec->flags |= SEC_RELOC;
        }
     }
   else
@@ -10948,9 +11189,9 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       off = (stub_entry->target_value
             + stub_entry->target_section->output_offset
             + stub_entry->target_section->output_section->vma);
-      off -= (stub_entry->stub_sec->size
-             + stub_entry->stub_sec->output_offset
-             + stub_entry->stub_sec->output_section->vma);
+      off -= (stub_entry->group->stub_sec->size
+             + stub_entry->group->stub_sec->output_offset
+             + stub_entry->group->stub_sec->output_section->vma);
 
       /* Reset the stub type from the plt variant in case we now
         can reach with a shorter stub.  */
@@ -10961,14 +11202,16 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
        {
          r2off = get_r2off (info, stub_entry);
-         if (r2off == 0 && htab->opd_abi)
+         if (r2off == (bfd_vma) -1)
            {
              htab->stub_error = TRUE;
              return FALSE;
            }
-         size = 12;
+         size = 8;
          if (PPC_HA (r2off) != 0)
-           size = 16;
+           size += 4;
+         if (PPC_LO (r2off) != 0)
+           size += 4;
          off -= size - 4;
        }
 
@@ -10978,7 +11221,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
         Do the same for -R objects without function descriptors.  */
       if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off
          || (stub_entry->stub_type == ppc_stub_long_branch_r2off
-             && r2off == 0))
+             && r2off == 0
+             && htab->sec_info[stub_entry->target_section->id].toc_off == 0))
        {
          struct ppc_branch_hash_entry *br_entry;
 
@@ -11013,12 +11257,13 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
                 + htab->brlt->output_offset
                 + htab->brlt->output_section->vma
                 - elf_gp (htab->brlt->output_section->owner)
-                - htab->stub_group[stub_entry->id_sec->id].toc_off);
+                - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
          if (info->emitrelocations)
            {
-             stub_entry->stub_sec->reloc_count += 1 + (PPC_HA (off) != 0);
-             stub_entry->stub_sec->flags |= SEC_RELOC;
+             stub_entry->group->stub_sec->reloc_count
+               += 1 + (PPC_HA (off) != 0);
+             stub_entry->group->stub_sec->flags |= SEC_RELOC;
            }
 
          if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
@@ -11041,12 +11286,12 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        }
       else if (info->emitrelocations)
        {
-         stub_entry->stub_sec->reloc_count += 1;
-         stub_entry->stub_sec->flags |= SEC_RELOC;
+         stub_entry->group->stub_sec->reloc_count += 1;
+         stub_entry->group->stub_sec->flags |= SEC_RELOC;
        }
     }
 
-  stub_entry->stub_sec->size += size;
+  stub_entry->group->stub_sec->size += size;
   return TRUE;
 }
 
@@ -11057,57 +11302,22 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 int
 ppc64_elf_setup_section_lists (struct bfd_link_info *info)
 {
-  bfd *input_bfd;
-  int top_id, top_index, id;
-  asection *section;
-  asection **input_list;
+  unsigned int id;
   bfd_size_type amt;
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
 
   if (htab == NULL)
     return -1;
 
-  /* Find the top input section id.  */
-  for (input_bfd = info->input_bfds, top_id = 3;
-       input_bfd != NULL;
-       input_bfd = input_bfd->link.next)
-    {
-      for (section = input_bfd->sections;
-          section != NULL;
-          section = section->next)
-       {
-         if (top_id < section->id)
-           top_id = section->id;
-       }
-    }
-
-  htab->top_id = top_id;
-  amt = sizeof (struct map_stub) * (top_id + 1);
-  htab->stub_group = bfd_zmalloc (amt);
-  if (htab->stub_group == NULL)
+  htab->sec_info_arr_size = bfd_get_next_section_id ();
+  amt = sizeof (*htab->sec_info) * (htab->sec_info_arr_size);
+  htab->sec_info = bfd_zmalloc (amt);
+  if (htab->sec_info == NULL)
     return -1;
 
   /* Set toc_off for com, und, abs and ind sections.  */
   for (id = 0; id < 3; id++)
-    htab->stub_group[id].toc_off = TOC_BASE_OFF;
-
-  /* We can't use output_bfd->section_count here to find the top output
-     section index as some sections may have been removed, and
-     strip_excluded_output_sections doesn't renumber the indices.  */
-  for (section = info->output_bfd->sections, top_index = 0;
-       section != NULL;
-       section = section->next)
-    {
-      if (top_index < section->index)
-       top_index = section->index;
-    }
-
-  htab->top_index = top_index;
-  amt = sizeof (asection *) * (top_index + 1);
-  input_list = bfd_zmalloc (amt);
-  htab->input_list = input_list;
-  if (input_list == NULL)
-    return -1;
+    htab->sec_info[id].toc_off = TOC_BASE_OFF;
 
   return 1;
 }
@@ -11158,6 +11368,7 @@ ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
          addr = (htab->toc_first_sec->output_offset
                  + htab->toc_first_sec->output_section->vma);
          htab->toc_curr = addr;
+         htab->toc_curr &= -TOC_BASE_ALIGN;
        }
 
       /* toc_curr is the base address of this toc group.  Set elf_gp
@@ -11350,7 +11561,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
                  htab->elf.irelplt->size += rel_size;
                  htab->got_reli_size += rel_size;
                }
-             else if (info->shared)
+             else if (bfd_link_pic (info))
                {
                  asection *srel = ppc64_elf_tdata (ibfd)->relgot;
                  srel->size += rel_size;
@@ -11375,7 +11586,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
          asection *s = ppc64_elf_tdata (ibfd)->got;
          ent->got.offset = s->size;
          s->size += 16;
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
              asection *srel = ppc64_elf_tdata (ibfd)->relgot;
              srel->size += sizeof (Elf64_External_Rela);
@@ -11538,7 +11749,7 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
                {
                  long adjust;
 
-                 adjust = opd->adjust[sym->st_value / 8];
+                 adjust = opd->adjust[OPD_NDX (sym_value)];
                  if (adjust == -1)
                    /* Assume deleted functions won't ever be called.  */
                    continue;
@@ -11655,15 +11866,13 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
     return FALSE;
 
   if ((isec->output_section->flags & SEC_CODE) != 0
-      && isec->output_section->index <= htab->top_index)
+      && isec->output_section->id < htab->sec_info_arr_size)
     {
-      asection **list = htab->input_list + isec->output_section->index;
-      /* Steal the link_sec pointer for our list.  */
-#define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec)
       /* This happens to make the list in reverse order,
         which is what we want.  */
-      PREV_SEC (isec) = *list;
-      *list = isec;
+      htab->sec_info[isec->id].u.list
+       = htab->sec_info[isec->output_section->id].u.list;
+      htab->sec_info[isec->output_section->id].u.list = isec;
     }
 
   if (htab->multi_toc_needed)
@@ -11687,7 +11896,7 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
        htab->toc_curr = elf_gp (isec->owner);
     }
 
-  htab->stub_group[isec->id].toc_off = htab->toc_curr;
+  htab->sec_info[isec->id].toc_off = htab->toc_curr;
   return TRUE;
 }
 
@@ -11709,8 +11918,8 @@ check_pasted_section (struct bfd_link_info *info, const char *name)
        if (i->has_toc_reloc)
          {
            if (toc_off == 0)
-             toc_off = htab->stub_group[i->id].toc_off;
-           else if (toc_off != htab->stub_group[i->id].toc_off)
+             toc_off = htab->sec_info[i->id].toc_off;
+           else if (toc_off != htab->sec_info[i->id].toc_off)
              return FALSE;
          }
 
@@ -11718,14 +11927,14 @@ check_pasted_section (struct bfd_link_info *info, const char *name)
        for (i = o->map_head.s; i != NULL; i = i->map_head.s)
          if (i->makes_toc_func_call)
            {
-             toc_off = htab->stub_group[i->id].toc_off;
+             toc_off = htab->sec_info[i->id].toc_off;
              break;
            }
 
       /* Make sure the whole pasted function uses the same toc offset.  */
       if (toc_off != 0)
        for (i = o->map_head.s; i != NULL; i = i->map_head.s)
-         htab->stub_group[i->id].toc_off = toc_off;
+         htab->sec_info[i->id].toc_off = toc_off;
     }
   return TRUE;
 }
@@ -11744,17 +11953,22 @@ ppc64_elf_check_init_fini (struct bfd_link_info *info)
    _init and _fini functions into multiple parts.  Putting a stub in
    the middle of a function is not a good idea.  */
 
-static void
-group_sections (struct ppc_link_hash_table *htab,
+static bfd_boolean
+group_sections (struct bfd_link_info *info,
                bfd_size_type stub_group_size,
                bfd_boolean stubs_always_before_branch)
 {
-  asection **list;
+  struct ppc_link_hash_table *htab;
+  asection *osec;
   bfd_size_type stub14_group_size;
   bfd_boolean suppress_size_errors;
 
+  htab = ppc_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   suppress_size_errors = FALSE;
-  stub14_group_size = stub_group_size;
+  stub14_group_size = stub_group_size >> 10;
   if (stub_group_size == 1)
     {
       /* Default values.  */
@@ -11771,10 +11985,14 @@ group_sections (struct ppc_link_hash_table *htab,
       suppress_size_errors = TRUE;
     }
 
-  list = htab->input_list + htab->top_index;
-  do
+  for (osec = info->output_bfd->sections; osec != NULL; osec = osec->next)
     {
-      asection *tail = *list;
+      asection *tail;
+
+      if (osec->id >= htab->sec_info_arr_size)
+       continue;
+
+      tail = htab->sec_info[osec->id].u.list;
       while (tail != NULL)
        {
          asection *curr;
@@ -11782,6 +12000,7 @@ group_sections (struct ppc_link_hash_table *htab,
          bfd_size_type total;
          bfd_boolean big_sec;
          bfd_vma curr_toc;
+         struct map_stub *group;
 
          curr = tail;
          total = tail->size;
@@ -11791,14 +12010,14 @@ group_sections (struct ppc_link_hash_table *htab,
          if (big_sec && !suppress_size_errors)
            (*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
                                     tail->owner, tail);
-         curr_toc = htab->stub_group[tail->id].toc_off;
+         curr_toc = htab->sec_info[tail->id].toc_off;
 
-         while ((prev = PREV_SEC (curr)) != NULL
+         while ((prev = htab->sec_info[curr->id].u.list) != NULL
                 && ((total += curr->output_offset - prev->output_offset)
                     < (ppc64_elf_section_data (prev) != NULL
                        && ppc64_elf_section_data (prev)->has_14bit_branch
                        ? stub14_group_size : stub_group_size))
-                && htab->stub_group[prev->id].toc_off == curr_toc)
+                && htab->sec_info[prev->id].toc_off == curr_toc)
            curr = prev;
 
          /* OK, the size from the start of CURR to the end is less
@@ -11811,11 +12030,19 @@ group_sections (struct ppc_link_hash_table *htab,
             only break if stubs added make the total size more than
             2^25, ie. for the default stub_group_size, if stubs total
             more than 2097152 bytes, or nearly 75000 plt call stubs.  */
+         group = bfd_alloc (curr->owner, sizeof (*group));
+         if (group == NULL)
+           return FALSE;
+         group->link_sec = curr;
+         group->stub_sec = NULL;
+         group->needs_save_res = 0;
+         group->next = htab->group;
+         htab->group = group;
          do
            {
-             prev = PREV_SEC (tail);
+             prev = htab->sec_info[tail->id].u.list;
              /* Set up this stub group.  */
-             htab->stub_group[tail->id].link_sec = curr;
+             htab->sec_info[tail->id].u.group = group;
            }
          while (tail != curr && (tail = prev) != NULL);
 
@@ -11832,19 +12059,17 @@ group_sections (struct ppc_link_hash_table *htab,
                         < (ppc64_elf_section_data (prev) != NULL
                            && ppc64_elf_section_data (prev)->has_14bit_branch
                            ? stub14_group_size : stub_group_size))
-                    && htab->stub_group[prev->id].toc_off == curr_toc)
+                    && htab->sec_info[prev->id].toc_off == curr_toc)
                {
                  tail = prev;
-                 prev = PREV_SEC (tail);
-                 htab->stub_group[tail->id].link_sec = curr;
+                 prev = htab->sec_info[tail->id].u.list;
+                 htab->sec_info[tail->id].u.group = group;
                }
            }
          tail = prev;
        }
     }
-  while (list-- != htab->input_list);
-  free (htab->input_list);
-#undef PREV_SEC
+  return TRUE;
 }
 
 static const unsigned char glink_eh_frame_cie[] =
@@ -11858,7 +12083,8 @@ static const unsigned char glink_eh_frame_cie[] =
   65,                                  /* RA reg.  */
   1,                                   /* Augmentation size.  */
   DW_EH_PE_pcrel | DW_EH_PE_sdata4,    /* FDE encoding.  */
-  DW_CFA_def_cfa, 1, 0                 /* def_cfa: r1 offset 0.  */
+  DW_CFA_def_cfa, 1, 0,                        /* def_cfa: r1 offset 0.  */
+  0, 0, 0, 0
 };
 
 /* Stripping output sections is normally done before dynamic section
@@ -11898,7 +12124,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
   if (htab == NULL)
     return FALSE;
 
-  if (htab->params->plt_thread_safe == -1 && !info->executable)
+  if (htab->params->plt_thread_safe == -1 && !bfd_link_executable (info))
     htab->params->plt_thread_safe = 1;
   if (!htab->opd_abi)
     htab->params->plt_thread_safe = 0;
@@ -11915,16 +12141,24 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
          /* libanl */
          "getaddrinfo_a",
          /* libgomp */
+         "GOMP_parallel",
          "GOMP_parallel_start",
+         "GOMP_parallel_loop_static",
          "GOMP_parallel_loop_static_start",
+         "GOMP_parallel_loop_dynamic",
          "GOMP_parallel_loop_dynamic_start",
+         "GOMP_parallel_loop_guided",
          "GOMP_parallel_loop_guided_start",
+         "GOMP_parallel_loop_runtime",
          "GOMP_parallel_loop_runtime_start",
+         "GOMP_parallel_sections",
          "GOMP_parallel_sections_start",
+         /* libgo */
+         "__go_go",
        };
       unsigned i;
 
-      for (i = 0; i < sizeof (thread_starter)/ sizeof (thread_starter[0]); i++)
+      for (i = 0; i < ARRAY_SIZE (thread_starter); i++)
        {
          struct elf_link_hash_entry *h;
          h = elf_link_hash_lookup (&htab->elf, thread_starter[i],
@@ -11940,12 +12174,14 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
   else
     stub_group_size = htab->params->group_size;
 
-  group_sections (htab, stub_group_size, stubs_always_before_branch);
+  if (!group_sections (info, stub_group_size, stubs_always_before_branch))
+    return FALSE;
 
   while (1)
     {
       bfd *input_bfd;
       unsigned int bfd_indx;
+      struct map_stub *group;
       asection *stub_sec;
 
       htab->stub_iteration += 1;
@@ -12047,7 +12283,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
                  if (hash == NULL)
                    {
                      sym_value = sym->st_value;
-                     ok_dest = TRUE;
+                     if (sym_sec != NULL
+                         && sym_sec->output_section != NULL)
+                       ok_dest = TRUE;
                    }
                  else if (hash->elf.root.type == bfd_link_hash_defined
                           || hash->elf.root.type == bfd_link_hash_defweak)
@@ -12105,7 +12343,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 
                      if (hash == NULL && opd->adjust != NULL)
                        {
-                         long adjust = opd->adjust[sym_value / 8];
+                         long adjust = opd->adjust[OPD_NDX (sym_value)];
                          if (adjust == -1)
                            continue;
                          code_value += adjust;
@@ -12143,8 +12381,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
                         fact a call needing a TOC adjustment.  */
                      if (code_sec != NULL
                          && code_sec->output_section != NULL
-                         && (htab->stub_group[code_sec->id].toc_off
-                             != htab->stub_group[section->id].toc_off)
+                         && (htab->sec_info[code_sec->id].toc_off
+                             != htab->sec_info[section->id].toc_off)
                          && (code_sec->has_toc_reloc
                              || code_sec->makes_toc_func_call))
                        stub_type = ppc_stub_long_branch_r2off;
@@ -12184,7 +12422,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
                    stub_type = ppc_stub_plt_call_r2save;
 
                  /* Support for grouping stub sections.  */
-                 id_sec = htab->stub_group[section->id].link_sec;
+                 id_sec = htab->sec_info[section->id].u.group->link_sec;
 
                  /* Get the name of this stub.  */
                  stub_name = ppc_stub_name (id_sec, sym_sec, hash, irela);
@@ -12273,6 +12511,10 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 
       bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info);
 
+      for (group = htab->group; group != NULL; group = group->next)
+       if (group->needs_save_res)
+         group->stub_sec->size += htab->sfpr->size;
+
       if (info->emitrelocations
          && htab->glink != NULL && htab->glink->size != 0)
        {
@@ -12290,7 +12532,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
               stub_sec != NULL;
               stub_sec = stub_sec->next)
            if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
-             size += 20;
+             size += 24;
          if (htab->glink != NULL && htab->glink->size != 0)
            size += 24;
          if (size != 0)
@@ -12310,7 +12552,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
          if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
            stub_sec->size = ((stub_sec->size
                               + (1 << htab->params->plt_stub_align) - 1)
-                             & (-1 << htab->params->plt_stub_align));
+                             & -(1 << htab->params->plt_stub_align));
 
       for (stub_sec = htab->params->stub_bfd->sections;
           stub_sec != NULL;
@@ -12330,6 +12572,89 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
       (*htab->params->layout_sections_again) ();
     }
 
+  if (htab->glink_eh_frame != NULL
+      && htab->glink_eh_frame->size != 0)
+    {
+      bfd_vma val;
+      bfd_byte *p, *last_fde;
+      size_t last_fde_len, size, align, pad;
+      asection *stub_sec;
+
+      p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
+      if (p == NULL)
+       return FALSE;
+      htab->glink_eh_frame->contents = p;
+      last_fde = p;
+
+      memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
+      /* CIE length (rewrite in case little-endian).  */
+      last_fde_len = sizeof (glink_eh_frame_cie) - 4;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
+      p += sizeof (glink_eh_frame_cie);
+
+      for (stub_sec = htab->params->stub_bfd->sections;
+          stub_sec != NULL;
+          stub_sec = stub_sec->next)
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+         {
+           last_fde = p;
+           last_fde_len = 20;
+           /* FDE length.  */
+           bfd_put_32 (htab->elf.dynobj, 20, p);
+           p += 4;
+           /* CIE pointer.  */
+           val = p - htab->glink_eh_frame->contents;
+           bfd_put_32 (htab->elf.dynobj, val, p);
+           p += 4;
+           /* Offset to stub section, written later.  */
+           p += 4;
+           /* stub section size.  */
+           bfd_put_32 (htab->elf.dynobj, stub_sec->size, p);
+           p += 4;
+           /* Augmentation.  */
+           p += 1;
+           /* Pad.  */
+           p += 7;
+         }
+      if (htab->glink != NULL && htab->glink->size != 0)
+       {
+         last_fde = p;
+         last_fde_len = 20;
+         /* FDE length.  */
+         bfd_put_32 (htab->elf.dynobj, 20, p);
+         p += 4;
+         /* CIE pointer.  */
+         val = p - htab->glink_eh_frame->contents;
+         bfd_put_32 (htab->elf.dynobj, val, p);
+         p += 4;
+         /* Offset to .glink, written later.  */
+         p += 4;
+         /* .glink size.  */
+         bfd_put_32 (htab->elf.dynobj, htab->glink->size - 8, p);
+         p += 4;
+         /* Augmentation.  */
+         p += 1;
+
+         *p++ = DW_CFA_advance_loc + 1;
+         *p++ = DW_CFA_register;
+         *p++ = 65;
+         *p++ = htab->opd_abi ? 12 : 0;
+         *p++ = DW_CFA_advance_loc + 4;
+         *p++ = DW_CFA_restore_extended;
+         *p++ = 65;
+       }
+      /* Subsume any padding into the last FDE if user .eh_frame
+        sections are aligned more than glink_eh_frame.  Otherwise any
+        zero padding will be seen as a terminator.  */
+      size = p - htab->glink_eh_frame->contents;
+      align = 1;
+      align <<= htab->glink_eh_frame->output_section->alignment_power;
+      align -= 1;
+      pad = ((size + align) & ~align) - size;
+      htab->glink_eh_frame->size = size + pad;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len + pad, last_fde);
+    }
+
   maybe_strip_output (info, htab->brlt);
   if (htab->glink_eh_frame != NULL)
     maybe_strip_output (info, htab->glink_eh_frame);
@@ -12344,7 +12669,35 @@ bfd_vma
 ppc64_elf_set_toc (struct bfd_link_info *info, bfd *obfd)
 {
   asection *s;
-  bfd_vma TOCstart;
+  bfd_vma TOCstart, adjust;
+
+  if (info != NULL)
+    {
+      struct elf_link_hash_entry *h;
+      struct elf_link_hash_table *htab = elf_hash_table (info);
+
+      if (is_elf_hash_table (htab)
+         && htab->hgot != NULL)
+       h = htab->hgot;
+      else
+       {
+         h = elf_link_hash_lookup (htab, ".TOC.", FALSE, FALSE, TRUE);
+         if (is_elf_hash_table (htab))
+           htab->hgot = h;
+       }
+      if (h != NULL
+         && h->root.type == bfd_link_hash_defined
+         && !h->root.linker_def
+         && (!is_elf_hash_table (htab)
+             || h->def_regular))
+       {
+         TOCstart = (h->root.u.def.value - TOC_BASE_OFF
+                     + h->root.u.def.section->output_offset
+                     + h->root.u.def.section->output_section->vma);
+         _bfd_set_gp_value (obfd, TOCstart);
+         return TOCstart;
+       }
+    }
 
   /* The TOC consists of sections .got, .toc, .tocbss, .plt in that
      order.  The TOC starts where the first of these sections starts.  */
@@ -12392,17 +12745,29 @@ ppc64_elf_set_toc (struct bfd_link_info *info, bfd *obfd)
   if (s != NULL)
     TOCstart = s->output_section->vma + s->output_offset;
 
+  /* Force alignment.  */
+  adjust = TOCstart & (TOC_BASE_ALIGN - 1);
+  TOCstart -= adjust;
   _bfd_set_gp_value (obfd, TOCstart);
 
-  if (info != NULL && s != NULL && is_ppc64_elf (obfd))
+  if (info != NULL && s != NULL)
     {
       struct ppc_link_hash_table *htab = ppc_hash_table (info);
 
-      if (htab != NULL
-         && htab->elf.hgot != NULL)
+      if (htab != NULL)
        {
-         htab->elf.hgot->root.u.def.value = TOC_BASE_OFF;
-         htab->elf.hgot->root.u.def.section = s;
+         if (htab->elf.hgot != NULL)
+           {
+             htab->elf.hgot->root.u.def.value = TOC_BASE_OFF - adjust;
+             htab->elf.hgot->root.u.def.section = s;
+           }
+       }
+      else
+       {
+         struct bfd_link_hash_entry *bh = NULL;
+         _bfd_generic_link_add_one_symbol (info, obfd, ".TOC.", BSF_GLOBAL,
+                                           s, TOC_BASE_OFF - adjust,
+                                           NULL, FALSE, FALSE, &bh);
        }
     }
   return TOCstart;
@@ -12459,6 +12824,33 @@ build_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
            htab->stub_error = TRUE;
          }
 
+       htab->stub_count[ppc_stub_global_entry - 1] += 1;
+       if (htab->params->emit_stub_syms)
+         {
+           size_t len = strlen (h->root.root.string);
+           char *name = bfd_malloc (sizeof "12345678.global_entry." + len);
+
+           if (name == NULL)
+             return FALSE;
+
+           sprintf (name, "%08x.global_entry.%s", s->id, h->root.root.string);
+           h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
+           if (h == NULL)
+             return FALSE;
+           if (h->root.type == bfd_link_hash_new)
+             {
+               h->root.type = bfd_link_hash_defined;
+               h->root.u.def.section = s;
+               h->root.u.def.value = p - s->contents;
+               h->ref_regular = 1;
+               h->def_regular = 1;
+               h->ref_regular_nonweak = 1;
+               h->forced_local = 1;
+               h->non_elf = 0;
+               h->root.linker_def = 1;
+             }
+         }
+
        if (PPC_HA (off) != 0)
          {
            bfd_put_32 (s->owner, ADDIS_R12_R12 | PPC_HA (off), p);
@@ -12483,6 +12875,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
                       char **stats)
 {
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
+  struct map_stub *group;
   asection *stub_sec;
   bfd_byte *p;
   int stub_sec_count = 0;
@@ -12529,6 +12922,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
              h->ref_regular_nonweak = 1;
              h->forced_local = 1;
              h->non_elf = 0;
+             h->root.linker_def = 1;
            }
        }
       plt0 = (htab->elf.splt->output_section->vma
@@ -12637,7 +13031,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
        elf_link_hash_traverse (&htab->elf, build_global_entry_stubs, info);
     }
 
-  if (htab->brlt->size != 0)
+  if (htab->brlt != NULL && htab->brlt->size != 0)
     {
       htab->brlt->contents = bfd_zalloc (htab->brlt->owner,
                                         htab->brlt->size);
@@ -12652,119 +13046,25 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
        return FALSE;
     }
 
-  if (htab->glink_eh_frame != NULL
-      && htab->glink_eh_frame->size != 0)
-    {
-      bfd_vma val;
-      bfd_byte *last_fde;
-      size_t last_fde_len, size, align, pad;
-
-      p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
-      if (p == NULL)
-       return FALSE;
-      htab->glink_eh_frame->contents = p;
-      last_fde = p;
-
-      htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
-
-      memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
-      /* CIE length (rewrite in case little-endian).  */
-      last_fde_len = sizeof (glink_eh_frame_cie) - 4;
-      bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
-      p += sizeof (glink_eh_frame_cie);
+  /* Build the stubs as directed by the stub hash table.  */
+  bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
 
-      for (stub_sec = htab->params->stub_bfd->sections;
-          stub_sec != NULL;
-          stub_sec = stub_sec->next)
-       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+  for (group = htab->group; group != NULL; group = group->next)
+    if (group->needs_save_res)
+      {
+       stub_sec = group->stub_sec;
+       memcpy (stub_sec->contents + stub_sec->size, htab->sfpr->contents,
+               htab->sfpr->size);
+       if (htab->params->emit_stub_syms)
          {
-           last_fde = p;
-           last_fde_len = 16;
-           /* FDE length.  */
-           bfd_put_32 (htab->elf.dynobj, 16, p);
-           p += 4;
-           /* CIE pointer.  */
-           val = p - htab->glink_eh_frame->contents;
-           bfd_put_32 (htab->elf.dynobj, val, p);
-           p += 4;
-           /* Offset to stub section.  */
-           val = (stub_sec->output_section->vma
-                  + stub_sec->output_offset);
-           val -= (htab->glink_eh_frame->output_section->vma
-                   + htab->glink_eh_frame->output_offset);
-           val -= p - htab->glink_eh_frame->contents;
-           if (val + 0x80000000 > 0xffffffff)
-             {
-               info->callbacks->einfo
-                 (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
-                  stub_sec->name);
+           unsigned int i;
+
+           for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
+             if (!sfpr_define (info, &save_res_funcs[i], stub_sec))
                return FALSE;
-             }
-           bfd_put_32 (htab->elf.dynobj, val, p);
-           p += 4;
-           /* stub section size.  */
-           bfd_put_32 (htab->elf.dynobj, stub_sec->rawsize, p);
-           p += 4;
-           /* Augmentation.  */
-           p += 1;
-           /* Pad.  */
-           p += 3;
          }
-      if (htab->glink != NULL && htab->glink->size != 0)
-       {
-         last_fde = p;
-         last_fde_len = 20;
-         /* FDE length.  */
-         bfd_put_32 (htab->elf.dynobj, 20, p);
-         p += 4;
-         /* CIE pointer.  */
-         val = p - htab->glink_eh_frame->contents;
-         bfd_put_32 (htab->elf.dynobj, val, p);
-         p += 4;
-         /* Offset to .glink.  */
-         val = (htab->glink->output_section->vma
-                + htab->glink->output_offset
-                + 8);
-         val -= (htab->glink_eh_frame->output_section->vma
-                 + htab->glink_eh_frame->output_offset);
-         val -= p - htab->glink_eh_frame->contents;
-         if (val + 0x80000000 > 0xffffffff)
-           {
-             info->callbacks->einfo
-               (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
-                htab->glink->name);
-             return FALSE;
-           }
-         bfd_put_32 (htab->elf.dynobj, val, p);
-         p += 4;
-         /* .glink size.  */
-         bfd_put_32 (htab->elf.dynobj, htab->glink->size - 8, p);
-         p += 4;
-         /* Augmentation.  */
-         p += 1;
-
-         *p++ = DW_CFA_advance_loc + 1;
-         *p++ = DW_CFA_register;
-         *p++ = 65;
-         *p++ = 12;
-         *p++ = DW_CFA_advance_loc + 4;
-         *p++ = DW_CFA_restore_extended;
-         *p++ = 65;
-       }
-      /* Subsume any padding into the last FDE if user .eh_frame
-        sections are aligned more than glink_eh_frame.  Otherwise any
-        zero padding will be seen as a terminator.  */
-      size = p - htab->glink_eh_frame->contents;
-      align = 1;
-      align <<= htab->glink_eh_frame->output_section->alignment_power;
-      align -= 1;
-      pad = ((size + align) & ~align) - size;
-      htab->glink_eh_frame->size = size + pad;
-      bfd_put_32 (htab->elf.dynobj, last_fde_len + pad, last_fde);
-    }
-
-  /* Build the stubs as directed by the stub hash table.  */
-  bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
+       stub_sec->size += htab->sfpr->size;
+      }
 
   if (htab->relbrlt != NULL)
     htab->relbrlt->reloc_count = 0;
@@ -12776,7 +13076,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
        stub_sec->size = ((stub_sec->size
                           + (1 << htab->params->plt_stub_align) - 1)
-                         & (-1 << htab->params->plt_stub_align));
+                         & -(1 << htab->params->plt_stub_align));
 
   for (stub_sec = htab->params->stub_bfd->sections;
        stub_sec != NULL;
@@ -12788,6 +13088,9 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
          break;
       }
 
+  /* Note that the glink_eh_frame check here is not only testing that
+     the generated size matched the calculated size but also that
+     bfd_elf_discard_info didn't make any changes to the section.  */
   if (stub_sec != NULL
       || (htab->glink_eh_frame != NULL
          && htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
@@ -12811,7 +13114,8 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
                         "  long branch  %lu\n"
                         "  long toc adj %lu\n"
                         "  plt call     %lu\n"
-                        "  plt call toc %lu"),
+                        "  plt call toc %lu\n"
+                        "  global entry %lu"),
               stub_sec_count,
               stub_sec_count == 1 ? "" : "s",
               htab->stub_count[ppc_stub_long_branch - 1],
@@ -12819,7 +13123,8 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
               htab->stub_count[ppc_stub_plt_branch - 1],
               htab->stub_count[ppc_stub_plt_branch_r2off - 1],
               htab->stub_count[ppc_stub_plt_call - 1],
-              htab->stub_count[ppc_stub_plt_call_r2save - 1]);
+              htab->stub_count[ppc_stub_plt_call_r2save - 1],
+              htab->stub_count[ppc_stub_global_entry - 1]);
     }
   return TRUE;
 }
@@ -12912,6 +13217,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   Elf_Internal_Rela *rel;
+  Elf_Internal_Rela *wrel;
   Elf_Internal_Rela *relend;
   Elf_Internal_Rela outrel;
   bfd_byte *loc;
@@ -12943,9 +13249,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
   sym_hashes = elf_sym_hashes (input_bfd);
   is_opd = ppc64_elf_section_data (input_section)->sec_type == sec_opd;
 
-  rel = relocs;
+  rel = wrel = relocs;
   relend = relocs + input_section->reloc_count;
-  for (; rel < relend; rel++)
+  for (; rel < relend; wrel++, rel++)
     {
       enum elf_ppc64_reloc_type r_type;
       bfd_vma addend;
@@ -12969,10 +13275,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       struct ppc_stub_hash_entry *stub_entry;
       bfd_vma max_br_offset;
       bfd_vma from;
-      const Elf_Internal_Rela orig_rel = *rel;
+      Elf_Internal_Rela orig_rel;
       reloc_howto_type *howto;
       struct reloc_howto_struct alt_howto;
 
+    again:
+      orig_rel = *rel;
+
       r_type = ELF64_R_TYPE (rel->r_info);
       r_symndx = ELF64_R_SYM (rel->r_info);
 
@@ -12980,10 +13289,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
         symbol of the previous ADDR64 reloc.  The symbol gives us the
         proper TOC base to use.  */
       if (rel->r_info == ELF64_R_INFO (0, R_PPC64_TOC)
-         && rel != relocs
-         && ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_ADDR64
+         && wrel != relocs
+         && ELF64_R_TYPE (wrel[-1].r_info) == R_PPC64_ADDR64
          && is_opd)
-       r_symndx = ELF64_R_SYM (rel[-1].r_info);
+       r_symndx = ELF64_R_SYM (wrel[-1].r_info);
 
       sym = NULL;
       sec = NULL;
@@ -13005,7 +13314,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          opd = get_opd_info (sec);
          if (opd != NULL && opd->adjust != NULL)
            {
-             long adjust = opd->adjust[(sym->st_value + rel->r_addend) / 8];
+             long adjust = opd->adjust[OPD_NDX (sym->st_value
+                                                + rel->r_addend)];
              if (adjust == -1)
                relocation = 0;
              else
@@ -13063,18 +13373,31 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       h = (struct ppc_link_hash_entry *) h_elf;
 
       if (sec != NULL && discarded_section (sec))
-       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-                                        rel, 1, relend,
-                                        ppc64_elf_howto_table[r_type], 0,
-                                        contents);
+       {
+         _bfd_clear_contents (ppc64_elf_howto_table[r_type],
+                              input_bfd, input_section,
+                              contents + rel->r_offset);
+         wrel->r_offset = rel->r_offset;
+         wrel->r_info = 0;
+         wrel->r_addend = 0;
+
+         /* For ld -r, remove relocations in debug sections against
+            sections defined in discarded sections.  Not done for
+            non-debug to preserve relocs in .eh_frame which the
+            eh_frame editing code expects to be present.  */
+         if (bfd_link_relocatable (info)
+             && (input_section->flags & SEC_DEBUGGING))
+           wrel--;
 
-      if (info->relocatable)
-       continue;
+         continue;
+       }
+
+      if (bfd_link_relocatable (info))
+       goto copy_reloc;
 
       if (h != NULL && &h->elf == htab->elf.hgot)
        {
-         relocation = (TOCstart
-                       + htab->stub_group[input_section->id].toc_off);
+         relocation = TOCstart + htab->sec_info[input_section->id].toc_off;
          sec = bfd_abs_section_ptr;
          unresolved_reloc = FALSE;
        }
@@ -13230,10 +13553,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              && (tls_mask & TLS_TPREL) == 0)
            {
            toctprel:
-             insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset);
+             insn = bfd_get_32 (output_bfd,
+                                contents + rel->r_offset - d_offset);
              insn &= 31 << 21;
              insn |= 0x3c0d0000;       /* addis 0,13,0 */
-             bfd_put_32 (output_bfd, insn, contents + rel->r_offset - d_offset);
+             bfd_put_32 (output_bfd, insn,
+                         contents + rel->r_offset - d_offset);
              r_type = R_PPC64_TPREL16_HA;
              if (toc_symndx != 0)
                {
@@ -13241,8 +13566,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  rel->r_addend = toc_addend;
                  /* We changed the symbol.  Start over in order to
                     get h, sym, sec etc. right.  */
-                 rel--;
-                 continue;
+                 goto again;
                }
              else
                rel->r_info = ELF64_R_INFO (r_symndx, r_type);
@@ -13268,8 +13592,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  rel->r_addend = toc_addend;
                  /* We changed the symbol.  Start over in order to
                     get h, sym, sec etc. right.  */
-                 rel--;
-                 continue;
+                 goto again;
                }
              else
                rel->r_info = ELF64_R_INFO (r_symndx, r_type);
@@ -13328,12 +13651,16 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                                              htab->tls_get_addr,
                                              htab->tls_get_addr_fd))
                offset = rel[1].r_offset;
+             /* We read the low GOT_TLS (or TOC16) insn because we
+                need to keep the destination reg.  It may be
+                something other than the usual r3, and moved to r3
+                before the call by intervening code.  */
+             insn1 = bfd_get_32 (output_bfd,
+                                 contents + rel->r_offset - d_offset);
              if ((tls_mask & tls_gd) != 0)
                {
                  /* IE */
-                 insn1 = bfd_get_32 (output_bfd,
-                                     contents + rel->r_offset - d_offset);
-                 insn1 &= (1 << 26) - (1 << 2);
+                 insn1 &= (0x1f << 21) | (0x1f << 16);
                  insn1 |= 58 << 26;    /* ld */
                  insn2 = 0x7c636a14;   /* add 3,3,13 */
                  if (offset != (bfd_vma) -1)
@@ -13348,7 +13675,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              else
                {
                  /* LE */
-                 insn1 = 0x3c6d0000;   /* addis 3,13,0 */
+                 insn1 &= 0x1f << 21;
+                 insn1 |= 0x3c0d0000;  /* addis r,13,0 */
                  insn2 = 0x38630000;   /* addi 3,3,0 */
                  if (tls_gd == 0)
                    {
@@ -13403,8 +13731,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                {
                  /* We changed the symbol.  Start over in order
                     to get h, sym, sec etc. right.  */
-                 rel--;
-                 continue;
+                 goto again;
                }
            }
          break;
@@ -13448,10 +13775,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                }
              bfd_put_32 (output_bfd, insn2, contents + offset);
              if ((tls_mask & TLS_TPRELGD) == 0 && toc_symndx != 0)
-               {
-                 rel--;
-                 continue;
-               }
+               goto again;
            }
          break;
 
@@ -13493,8 +13817,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  insn2 = NOP;
                }
              bfd_put_32 (output_bfd, insn2, contents + offset);
-             rel--;
-             continue;
+             goto again;
            }
          break;
 
@@ -13535,6 +13858,52 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            }
          break;
 
+       case R_PPC64_ENTRY:
+         relocation = TOCstart + htab->sec_info[input_section->id].toc_off;
+         if (!bfd_link_pic (info)
+             && !info->traditional_format
+             && relocation + 0x80008000 <= 0xffffffff)
+           {
+             unsigned int insn1, insn2;
+
+             insn1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
+             insn2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+             if ((insn1 & ~0xfffc) == LD_R2_0R12
+                 && insn2 == ADD_R2_R2_R12)
+               {
+                 bfd_put_32 (output_bfd,
+                             LIS_R2 + PPC_HA (relocation),
+                             contents + rel->r_offset);
+                 bfd_put_32 (output_bfd,
+                             ADDI_R2_R2 + PPC_LO (relocation),
+                             contents + rel->r_offset + 4);
+               }
+           }
+         else
+           {
+             relocation -= (rel->r_offset
+                            + input_section->output_offset
+                            + input_section->output_section->vma);
+             if (relocation + 0x80008000 <= 0xffffffff)
+               {
+                 unsigned int insn1, insn2;
+
+                 insn1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
+                 insn2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+                 if ((insn1 & ~0xfffc) == LD_R2_0R12
+                     && insn2 == ADD_R2_R2_R12)
+                   {
+                     bfd_put_32 (output_bfd,
+                                 ADDIS_R2_R12 + PPC_HA (relocation),
+                                 contents + rel->r_offset);
+                     bfd_put_32 (output_bfd,
+                                 ADDI_R2_R2 + PPC_LO (relocation),
+                                 contents + rel->r_offset + 4);
+                   }
+               }
+           }
+         break;
+
        case R_PPC64_REL16_HA:
          /* If we are generating a non-PIC executable, edit
             .  0:      addis 2,12,.TOC.-0b@ha
@@ -13543,7 +13912,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
             .          lis 2,.TOC.@ha
             .          addi 2,2,.TOC.@l
             if .TOC. is in range.  */
-         if (!info->shared
+         if (!bfd_link_pic (info)
+             && !info->traditional_format
+             && !htab->opd_abi
+             && rel->r_addend == d_offset
              && h != NULL && &h->elf == htab->elf.hgot
              && rel + 1 < relend
              && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO)
@@ -13555,15 +13927,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              bfd_vma offset = rel->r_offset - d_offset;
              insn1 = bfd_get_32 (output_bfd, contents + offset);
              insn2 = bfd_get_32 (output_bfd, contents + offset + 4);
-             if ((insn1 & 0xffff0000) == 0x3c4c0000 /* addis 2,12 */
-                 && (insn2 & 0xffff0000) == 0x38420000 /* addi 2,2 */)
+             if ((insn1 & 0xffff0000) == ADDIS_R2_R12
+                 && (insn2 & 0xffff0000) == ADDI_R2_R2)
                {
                  r_type = R_PPC64_ADDR16_HA;
                  rel->r_info = ELF64_R_INFO (r_symndx, r_type);
                  rel->r_addend -= d_offset;
                  rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_ADDR16_LO);
                  rel[1].r_addend -= d_offset + 4;
-                 bfd_put_32 (output_bfd, 0x3c400000, contents + offset);
+                 bfd_put_32 (output_bfd, LIS_R2, contents + offset);
                }
            }
          break;
@@ -13655,7 +14027,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                          if (h != NULL
                              && (h == htab->tls_get_addr_fd
                                  || h == htab->tls_get_addr)
-                             && !htab->params->no_tls_get_addr_opt)
+                             && htab->params->tls_get_addr_opt)
                            {
                              /* Special stub used, leave nop alone.  */
                            }
@@ -13711,10 +14083,17 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
              if (!can_plt_call)
                {
-                 info->callbacks->einfo
-                   (_("%P: %H: call to `%T' lacks nop, can't restore toc; "
-                      "recompile with -fPIC\n"),
-                    input_bfd, input_section, rel->r_offset, sym_name);
+                 if (stub_entry->stub_type == ppc_stub_plt_call
+                     || stub_entry->stub_type == ppc_stub_plt_call_r2save)
+                   info->callbacks->einfo
+                     (_("%P: %H: call to `%T' lacks nop, can't restore toc; "
+                        "recompile with -fPIC\n"),
+                      input_bfd, input_section, rel->r_offset, sym_name);
+                 else
+                   info->callbacks->einfo
+                     (_("%P: %H: call to `%T' lacks nop, can't restore toc; "
+                        "(-mcmodel=small toc adjust stub)\n"),
+                      input_bfd, input_section, rel->r_offset, sym_name);
 
                  bfd_set_error (bfd_error_bad_value);
                  ret = FALSE;
@@ -13768,9 +14147,18 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            {
              /* Munge up the value and addend so that we call the stub
                 rather than the procedure directly.  */
-             relocation = (stub_entry->stub_offset
-                           + stub_entry->stub_sec->output_offset
-                           + stub_entry->stub_sec->output_section->vma);
+             asection *stub_sec = stub_entry->group->stub_sec;
+
+             if (stub_entry->stub_type == ppc_stub_save_res)
+               relocation += (stub_sec->output_offset
+                              + stub_sec->output_section->vma
+                              + stub_sec->size - htab->sfpr->size
+                              - htab->sfpr->output_offset
+                              - htab->sfpr->output_section->vma);
+             else
+               relocation = (stub_entry->stub_offset
+                             + stub_sec->output_offset
+                             + stub_sec->output_section->vma);
              addend = 0;
              reloc_dest = DEST_STUB;
 
@@ -13819,7 +14207,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                   && addend == 0)
            {
              bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
-             continue;
+             goto copy_reloc;
            }
          break;
        }
@@ -13835,7 +14223,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
          bfd_set_error (bfd_error_bad_value);
          ret = FALSE;
-         continue;
+         goto copy_reloc;
 
        case R_PPC64_NONE:
        case R_PPC64_TLS:
@@ -13844,7 +14232,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_TOCSAVE:
        case R_PPC64_GNU_VTINHERIT:
        case R_PPC64_GNU_VTENTRY:
-         continue;
+       case R_PPC64_ENTRY:
+         goto copy_reloc;
 
          /* GOT16 relocations.  Like an ADDR16 using the symbol's
             address in the GOT as relocation value instead of the
@@ -13904,9 +14293,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                if (h != NULL)
                  {
                    bfd_boolean dyn = htab->elf.dynamic_sections_created;
-                   if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared,
+                   if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info),
                                                          &h->elf)
-                       || (info->shared
+                       || (bfd_link_pic (info)
                            && SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
                      /* This is actually a static link, or it is a
                         -Bsymbolic link and the symbol is defined
@@ -13965,7 +14354,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                         : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC);
                if (ifunc)
                  relgot = htab->elf.irelplt;
-               else if ((info->shared || indx != 0)
+               else if ((bfd_link_pic (info) || indx != 0)
                         && (h == NULL
                             || (tls_type == (TLS_TLS | TLS_LD)
                                 && !h->elf.def_dynamic)
@@ -14019,7 +14408,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                      {
                        outrel.r_addend += relocation;
                        if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL))
-                         outrel.r_addend -= htab->elf.tls_sec->vma;
+                         {
+                           if (htab->elf.tls_sec == NULL)
+                             outrel.r_addend = 0;
+                           else
+                             outrel.r_addend -= htab->elf.tls_sec->vma;
+                         }
                      }
                    loc = relgot->contents;
                    loc += (relgot->reloc_count++
@@ -14036,9 +14430,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                      relocation = 1;
                    else if (tls_type != 0)
                      {
-                       relocation -= htab->elf.tls_sec->vma + DTP_OFFSET;
-                       if (tls_type == (TLS_TLS | TLS_TPREL))
-                         relocation += DTP_OFFSET - TP_OFFSET;
+                       if (htab->elf.tls_sec == NULL)
+                         relocation = 0;
+                       else
+                         {
+                           relocation -= htab->elf.tls_sec->vma + DTP_OFFSET;
+                           if (tls_type == (TLS_TLS | TLS_TPREL))
+                             relocation += DTP_OFFSET - TP_OFFSET;
+                         }
 
                        if (tls_type == (TLS_TLS | TLS_GD))
                          {
@@ -14057,7 +14456,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              abort ();
 
            relocation = got->output_section->vma + got->output_offset + off;
-           addend = -(TOCstart + htab->stub_group[input_section->id].toc_off);
+           addend = -(TOCstart + htab->sec_info[input_section->id].toc_off);
          }
          break;
 
@@ -14068,41 +14467,54 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_PLT64:
          /* Relocation is to the entry for this symbol in the
             procedure linkage table.  */
+         {
+           struct plt_entry **plt_list = NULL;
+           if (h != NULL)
+             plt_list = &h->elf.plt.plist;
+           else if (local_got_ents != NULL)
+             {
+               struct plt_entry **local_plt = (struct plt_entry **)
+                 (local_got_ents + symtab_hdr->sh_info);
+               unsigned char *local_got_tls_masks = (unsigned char *)
+                 (local_plt + symtab_hdr->sh_info);
+               if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
+                 plt_list = local_plt + r_symndx;
+             }
+           if (plt_list)
+             {
+               struct plt_entry *ent;
 
-         /* Resolve a PLT reloc against a local symbol directly,
-            without using the procedure linkage table.  */
-         if (h == NULL)
-           break;
-
-         /* It's possible that we didn't make a PLT entry for this
-            symbol.  This happens when statically linking PIC code,
-            or when using -Bsymbolic.  Go find a match if there is a
-            PLT entry.  */
-         if (htab->elf.splt != NULL)
-           {
-             struct plt_entry *ent;
-             for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next)
-               if (ent->plt.offset != (bfd_vma) -1
-                   && ent->addend == orig_rel.r_addend)
-                 {
-                   relocation = (htab->elf.splt->output_section->vma
-                                 + htab->elf.splt->output_offset
-                                 + ent->plt.offset);
-                   unresolved_reloc = FALSE;
-                   break;
-                 }
-           }
+               for (ent = *plt_list; ent != NULL; ent = ent->next)
+                 if (ent->plt.offset != (bfd_vma) -1
+                     && ent->addend == orig_rel.r_addend)
+                   {
+                     asection *plt;
+
+                     plt = htab->elf.splt;
+                     if (!htab->elf.dynamic_sections_created
+                         || h == NULL
+                         || h->elf.dynindx == -1)
+                       plt = htab->elf.iplt;
+                     relocation = (plt->output_section->vma
+                                   + plt->output_offset
+                                   + ent->plt.offset);
+                     addend = 0;
+                     unresolved_reloc = FALSE;
+                     break;
+                   }
+             }
+         }
          break;
 
        case R_PPC64_TOC:
          /* Relocation value is TOC base.  */
          relocation = TOCstart;
          if (r_symndx == STN_UNDEF)
-           relocation += htab->stub_group[input_section->id].toc_off;
+           relocation += htab->sec_info[input_section->id].toc_off;
          else if (unresolved_reloc)
            ;
-         else if (sec != NULL && sec->id <= htab->top_id)
-           relocation += htab->stub_group[sec->id].toc_off;
+         else if (sec != NULL && sec->id < htab->sec_info_arr_size)
+           relocation += htab->sec_info[sec->id].toc_off;
          else
            unresolved_reloc = TRUE;
          goto dodyn;
@@ -14117,7 +14529,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_TOC16_DS:
        case R_PPC64_TOC16_LO_DS:
        case R_PPC64_TOC16_HA:
-         addend -= TOCstart + htab->stub_group[input_section->id].toc_off;
+         addend -= TOCstart + htab->sec_info[input_section->id].toc_off;
          break;
 
          /* Relocate against the beginning of the section.  */
@@ -14135,6 +14547,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_REL16_LO:
        case R_PPC64_REL16_HI:
        case R_PPC64_REL16_HA:
+       case R_PPC64_REL16DX_HA:
          break;
 
        case R_PPC64_REL14:
@@ -14171,8 +14584,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                bfd_put_32 (output_bfd, insn, p);
              break;
            }
-         addend -= htab->elf.tls_sec->vma + TP_OFFSET;
-         if (info->shared)
+         if (htab->elf.tls_sec != NULL)
+           addend -= htab->elf.tls_sec->vma + TP_OFFSET;
+         if (bfd_link_pic (info))
            /* The TPREL16 relocs shouldn't really be used in shared
               libs as they will result in DT_TEXTREL being set, but
               support them anyway.  */
@@ -14191,7 +14605,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_DTPREL16_HIGHERA:
        case R_PPC64_DTPREL16_HIGHEST:
        case R_PPC64_DTPREL16_HIGHESTA:
-         addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
+         if (htab->elf.tls_sec != NULL)
+           addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
          break;
 
        case R_PPC64_ADDR64_LOCAL:
@@ -14206,11 +14621,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          goto dodyn;
 
        case R_PPC64_TPREL64:
-         addend -= htab->elf.tls_sec->vma + TP_OFFSET;
+         if (htab->elf.tls_sec != NULL)
+           addend -= htab->elf.tls_sec->vma + TP_OFFSET;
          goto dodyn;
 
        case R_PPC64_DTPREL64:
-         addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
+         if (htab->elf.tls_sec != NULL)
+           addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
          /* Fall thru */
 
          /* Relocations that may need to be propagated if this is a
@@ -14246,19 +14663,19 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          if (NO_OPD_RELOCS && is_opd)
            break;
 
-         if ((info->shared
+         if ((bfd_link_pic (info)
               && (h == NULL
                   || ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
                   || h->elf.root.type != bfd_link_hash_undefweak)
               && (must_be_dyn_reloc (info, r_type)
                   || !SYMBOL_CALLS_LOCAL (info, &h->elf)))
              || (ELIMINATE_COPY_RELOCS
-                 && !info->shared
+                 && !bfd_link_pic (info)
                  && h != NULL
                  && h->elf.dynindx != -1
                  && !h->elf.non_got_ref
                  && !h->elf.def_regular)
-             || (!info->shared
+             || (!bfd_link_pic (info)
                  && (h != NULL
                      ? h->elf.type == STT_GNU_IFUNC
                      : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))
@@ -14466,7 +14883,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
          bfd_set_error (bfd_error_invalid_operation);
          ret = FALSE;
-         continue;
+         goto copy_reloc;
        }
 
       /* Multi-instruction sequences that access the TOC can be
@@ -14543,6 +14960,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          break;
 
        case R_PPC64_REL16_HA:
+       case R_PPC64_REL16DX_HA:
        case R_PPC64_ADDR16_HA:
        case R_PPC64_ADDR16_HIGHA:
        case R_PPC64_ADDR16_HIGHERA:
@@ -14598,16 +15016,20 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_DTPREL16_LO_DS:
          insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
          mask = 3;
-         /* If this reloc is against an lq insn, then the value must be
-            a multiple of 16.  This is somewhat of a hack, but the
-            "correct" way to do this by defining _DQ forms of all the
-            _DS relocs bloats all reloc switches in this file.  It
-            doesn't seem to make much sense to use any of these relocs
-            in data, so testing the insn should be safe.  */
-         if ((insn & (0x3f << 26)) == (56u << 26))
+         /* If this reloc is against an lq, lxv, or stxv insn, then
+            the value must be a multiple of 16.  This is somewhat of
+            a hack, but the "correct" way to do this by defining _DQ
+            forms of all the _DS relocs bloats all reloc switches in
+            this file.  It doesn't make much sense to use these
+            relocs in data, so testing the insn should be safe.  */
+         if ((insn & (0x3f << 26)) == (56u << 26)
+             || ((insn & (0x3f << 26)) == (61u << 26) && (insn & 3) == 1))
            mask = 15;
-         if (((relocation + addend) & mask) != 0)
+         relocation += addend;
+         addend = insn & (mask ^ 3);
+         if ((relocation & mask) != 0)
            {
+             relocation ^= relocation & mask;
              info->callbacks->einfo
                (_("%P: %H: error: %s not a multiple of %u\n"),
                 input_bfd, input_section, rel->r_offset,
@@ -14615,7 +15037,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                 mask + 1);
              bfd_set_error (bfd_error_bad_value);
              ret = FALSE;
-             continue;
+             goto copy_reloc;
            }
          break;
        }
@@ -14665,8 +15087,30 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            }
        }
 
-      r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
-                                   rel->r_offset, relocation, addend);
+      if (r_type == R_PPC64_REL16DX_HA)
+       {
+         /* Split field reloc isn't handled by _bfd_final_link_relocate.  */
+         if (rel->r_offset + 4 > input_section->size)
+           r = bfd_reloc_outofrange;
+         else
+           {
+             relocation += addend;
+             relocation -= (rel->r_offset
+                            + input_section->output_offset
+                            + input_section->output_section->vma);
+             relocation = (bfd_signed_vma) relocation >> 16;
+             insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+             insn &= ~0x1fffc1;
+             insn |= (relocation & 0xffc1) | ((relocation & 0x3e) << 15);
+             bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+             r = bfd_reloc_ok;
+             if (relocation + 0x8000 > 0xffff)
+               r = bfd_reloc_overflow;
+           }
+       }
+      else
+       r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
+                                     rel->r_offset, relocation, addend);
 
       if (r != bfd_reloc_ok)
        {
@@ -14687,26 +15131,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
          if (r == bfd_reloc_overflow)
            {
-             if (warned)
-               continue;
-             if (h != NULL
-                 && h->elf.root.type == bfd_link_hash_undefweak
-                 && howto->pc_relative)
+             /* On code like "if (foo) foo();" don't report overflow
+                on a branch to zero when foo is undefined.  */
+             if (!warned
+                 && (reloc_dest == DEST_STUB
+                     || !(h != NULL
+                          && (h->elf.root.type == bfd_link_hash_undefweak
+                              || h->elf.root.type == bfd_link_hash_undefined)
+                          && is_branch_reloc (r_type))))
                {
-                 /* Assume this is a call protected by other code that
-                    detects the symbol is undefined.  If this is the case,
-                    we can safely ignore the overflow.  If not, the
-                    program is hosed anyway, and a little warning isn't
-                    going to help.  */
-
-                 continue;
+                 if (!((*info->callbacks->reloc_overflow)
+                       (info, &h->elf.root, sym_name,
+                        reloc_name, orig_rel.r_addend,
+                        input_bfd, input_section, rel->r_offset)))
+                   return FALSE;
                }
-
-             if (!((*info->callbacks->reloc_overflow)
-                   (info, &h->elf.root, sym_name,
-                    reloc_name, orig_rel.r_addend,
-                    input_bfd, input_section, rel->r_offset)))
-               return FALSE;
            }
          else
            {
@@ -14719,6 +15158,29 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          if (more_info != NULL)
            free (more_info);
        }
+    copy_reloc:
+      if (wrel != rel)
+       *wrel = *rel;
+    }
+
+  if (wrel != rel)
+    {
+      Elf_Internal_Shdr *rel_hdr;
+      size_t deleted = rel - wrel;
+
+      rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section);
+      rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
+      if (rel_hdr->sh_size == 0)
+       {
+         /* It is too late to remove an empty reloc section.  Leave
+            one NONE reloc.
+            ??? What is wrong with an empty section???  */
+         rel_hdr->sh_size = rel_hdr->sh_entsize;
+         deleted -= 1;
+       }
+      rel_hdr = _bfd_elf_single_rel_hdr (input_section);
+      rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
+      input_section->reloc_count -= deleted;
     }
 
   /* If we're emitting relocations, then shortly after this function
@@ -14726,7 +15188,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
      adjusted.  Worse, reloc symbol indices will be for the output
      file rather than the input.  Save a copy of the relocs for
      opd_entry_value.  */
-  if (is_opd && (info->emitrelocations || info->relocatable))
+  if (is_opd && (info->emitrelocations || bfd_link_relocatable (info)))
     {
       bfd_size_type amt;
       amt = input_section->reloc_count * sizeof (Elf_Internal_Rela);
@@ -14761,10 +15223,10 @@ ppc64_elf_output_symbol_hook (struct bfd_link_info *info,
     return 1;
 
   value = elfsym->st_value - input_sec->output_offset;
-  if (!info->relocatable)
+  if (!bfd_link_relocatable (info))
     value -= input_sec->output_section->vma;
 
-  adjust = opd->adjust[value / 8];
+  adjust = opd->adjust[OPD_NDX (value)];
   if (adjust == -1)
     return 2;
 
@@ -15052,13 +15514,81 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
                                       NULL))
     return FALSE;
 
-
   if (htab->glink_eh_frame != NULL
-      && htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
-      && !_bfd_elf_write_section_eh_frame (output_bfd, info,
-                                          htab->glink_eh_frame,
-                                          htab->glink_eh_frame->contents))
-    return FALSE;
+      && htab->glink_eh_frame->size != 0)
+    {
+      bfd_vma val;
+      bfd_byte *p;
+      asection *stub_sec;
+
+      p = htab->glink_eh_frame->contents + sizeof (glink_eh_frame_cie);
+      for (stub_sec = htab->params->stub_bfd->sections;
+          stub_sec != NULL;
+          stub_sec = stub_sec->next)
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+         {
+           /* FDE length.  */
+           p += 4;
+           /* CIE pointer.  */
+           p += 4;
+           /* Offset to stub section.  */
+           val = (stub_sec->output_section->vma
+                  + stub_sec->output_offset);
+           val -= (htab->glink_eh_frame->output_section->vma
+                   + htab->glink_eh_frame->output_offset
+                   + (p - htab->glink_eh_frame->contents));
+           if (val + 0x80000000 > 0xffffffff)
+             {
+               info->callbacks->einfo
+                 (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+                  stub_sec->name);
+               return FALSE;
+             }
+           bfd_put_32 (dynobj, val, p);
+           p += 4;
+           /* stub section size.  */
+           p += 4;
+           /* Augmentation.  */
+           p += 1;
+           /* Pad.  */
+           p += 7;
+         }
+      if (htab->glink != NULL && htab->glink->size != 0)
+       {
+         /* FDE length.  */
+         p += 4;
+         /* CIE pointer.  */
+         p += 4;
+         /* Offset to .glink.  */
+         val = (htab->glink->output_section->vma
+                + htab->glink->output_offset
+                + 8);
+         val -= (htab->glink_eh_frame->output_section->vma
+                 + htab->glink_eh_frame->output_offset
+                 + (p - htab->glink_eh_frame->contents));
+         if (val + 0x80000000 > 0xffffffff)
+           {
+             info->callbacks->einfo
+               (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+                htab->glink->name);
+             return FALSE;
+           }
+         bfd_put_32 (dynobj, val, p);
+         p += 4;
+         /* .glink size.  */
+         p += 4;
+         /* Augmentation.  */
+         p += 1;
+         /* Ops.  */
+         p += 7;
+       }
+
+      if (htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
+         && !_bfd_elf_write_section_eh_frame (output_bfd, info,
+                                              htab->glink_eh_frame,
+                                              htab->glink_eh_frame->contents))
+       return FALSE;
+    }
 
   /* We need to handle writing out multiple GOT sections ourselves,
      since we didn't add them to DYNOBJ.  We know dynobj is the first