PowerPC indirect calls to __tls_get_addr
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index 5f3c79f81118e29b7f27154ecb2f53b5bf9a2c5f..4226120f537dd64093186733ee2443e2947b6801 100644 (file)
@@ -1,5 +1,5 @@
 /* PowerPC64-specific support for 64-bit ELF.
-   Copyright (C) 1999-2017 Free Software Foundation, Inc.
+   Copyright (C) 1999-2018 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.
@@ -101,10 +101,10 @@ static bfd_vma opd_entry_value
 #define elf_backend_notice_as_needed         ppc64_elf_notice_as_needed
 #define elf_backend_archive_symbol_lookup     ppc64_elf_archive_symbol_lookup
 #define elf_backend_check_relocs             ppc64_elf_check_relocs
+#define elf_backend_relocs_compatible        _bfd_elf_relocs_compatible
 #define elf_backend_gc_keep                  ppc64_elf_gc_keep
 #define elf_backend_gc_mark_dynamic_ref       ppc64_elf_gc_mark_dynamic_ref
 #define elf_backend_gc_mark_hook             ppc64_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook            ppc64_elf_gc_sweep_hook
 #define elf_backend_adjust_dynamic_symbol     ppc64_elf_adjust_dynamic_symbol
 #define elf_backend_hide_symbol                      ppc64_elf_hide_symbol
 #define elf_backend_maybe_function_sym       ppc64_elf_maybe_function_sym
@@ -161,34 +161,35 @@ static bfd_vma opd_entry_value
 #define LD_R11_0R11    0xe96b0000      /* ld    %r11,xxx+16@l(%r11) */
 #define BCTR           0x4e800420      /* bctr                      */
 
-#define ADDI_R11_R11   0x396b0000      /* addi %r11,%r11,off@l  */
-#define ADDIS_R2_R2    0x3c420000      /* addis %r2,%r2,off@ha  */
-#define ADDI_R2_R2     0x38420000      /* addi  %r2,%r2,off@l   */
+#define ADDI_R11_R11   0x396b0000      /* addi %r11,%r11,off@l  */
+#define ADDIS_R2_R2    0x3c420000      /* addis %r2,%r2,off@ha  */
+#define ADDI_R2_R2     0x38420000      /* addi  %r2,%r2,off@l   */
 
-#define XOR_R2_R12_R12 0x7d826278      /* xor   %r2,%r12,%r12   */
-#define ADD_R11_R11_R2 0x7d6b1214      /* add   %r11,%r11,%r2   */
-#define XOR_R11_R12_R12        0x7d8b6278      /* xor   %r11,%r12,%r12  */
-#define ADD_R2_R2_R11  0x7c425a14      /* add   %r2,%r2,%r11    */
-#define CMPLDI_R2_0    0x28220000      /* cmpldi %r2,0          */
-#define BNECTR         0x4ca20420      /* bnectr+               */
-#define BNECTR_P4      0x4ce20420      /* bnectr+               */
+#define XOR_R2_R12_R12 0x7d826278      /* xor   %r2,%r12,%r12   */
+#define ADD_R11_R11_R2 0x7d6b1214      /* add   %r11,%r11,%r2   */
+#define XOR_R11_R12_R12        0x7d8b6278      /* xor   %r11,%r12,%r12  */
+#define ADD_R2_R2_R11  0x7c425a14      /* add   %r2,%r2,%r11    */
+#define CMPLDI_R2_0    0x28220000      /* cmpldi %r2,0          */
+#define BNECTR         0x4ca20420      /* bnectr+               */
+#define BNECTR_P4      0x4ce20420      /* bnectr+               */
 
 #define LD_R12_0R2     0xe9820000      /* ld    %r12,xxx+0(%r2) */
 #define LD_R11_0R2     0xe9620000      /* ld    %r11,xxx+0(%r2) */
-#define LD_R2_0R2      0xe8420000      /* ld    %r2,xxx+0(%r2)  */
+#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 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 LIS_R2         0x3c400000      /* lis %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) */
+#define LD_R12_0R12    0xe98c0000      /* ld    %r12,xxx@l(%r12) */
 
-/* glink call stub instructions.  We enter with the index in R0.  */
-#define GLINK_CALL_STUB_SIZE (16*4)
+/* __glink_PLTresolve stub instructions.  We enter with the index in R0.  */
+#define GLINK_PLTRESOLVE_SIZE(htab)                    \
+  (8u + (htab->opd_abi ? 11 * 4 : 14 * 4))
                                        /* 0:                           */
                                        /*  .quad plt0-1f               */
                                        /* __glink:                     */
@@ -269,7 +270,8 @@ set_abiversion (bfd *abfd, int ver)
 /* Relocation HOWTO's.  */
 static reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC64_max];
 
-static reloc_howto_type ppc64_elf_howto_raw[] = {
+static reloc_howto_type ppc64_elf_howto_raw[] =
+{
   /* This reloc does nothing.  */
   HOWTO (R_PPC64_NONE,         /* type */
         0,                     /* rightshift */
@@ -2230,7 +2232,7 @@ ppc_howto_init (void)
 }
 
 static reloc_howto_type *
-ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ppc64_elf_reloc_type_lookup (bfd *abfd,
                             bfd_reloc_code_real_type code)
 {
   enum elf_ppc64_reloc_type r = R_PPC64_NONE;
@@ -2242,6 +2244,9 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   switch (code)
     {
     default:
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, (int) code);
+      bfd_set_error (bfd_error_bad_value);
       return NULL;
 
     case BFD_RELOC_NONE:                       r = R_PPC64_NONE;
@@ -2494,12 +2499,13 @@ ppc64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
        && strcasecmp (ppc64_elf_howto_raw[i].name, r_name) == 0)
       return &ppc64_elf_howto_raw[i];
 
+  
   return NULL;
 }
 
 /* Set the howto pointer for a PowerPC ELF reloc.  */
 
-static void
+static bfd_boolean
 ppc64_elf_info_to_howto (bfd *abfd, arelent *cache_ptr,
                         Elf_Internal_Rela *dst)
 {
@@ -2513,11 +2519,22 @@ ppc64_elf_info_to_howto (bfd *abfd, arelent *cache_ptr,
   if (type >= ARRAY_SIZE (ppc64_elf_howto_table))
     {
       /* xgettext:c-format */
-      _bfd_error_handler (_("%B: invalid relocation type %d"),
-                         abfd, (int) type);
-      type = R_PPC64_NONE;
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                         abfd, type);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
     }
   cache_ptr->howto = ppc64_elf_howto_table[type];
+  if (cache_ptr->howto == NULL || cache_ptr->howto->name == NULL)
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                         abfd, type);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+  
+  return TRUE;
 }
 
 /* Handle the R_PPC64_ADDR16_HA and similar relocs.  */
@@ -3025,13 +3042,13 @@ ppc64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
 
 static const struct bfd_elf_special_section ppc64_elf_special_sections[]=
 {
-  { STRING_COMMA_LEN (".plt"),    0, SHT_NOBITS,   0 },
-  { STRING_COMMA_LEN (".sbss"),  -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".plt"),   0, SHT_NOBITS,   0 },
+  { STRING_COMMA_LEN (".sbss"),         -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
   { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".toc"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".toc1"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".toc"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".toc1"),          0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { STRING_COMMA_LEN (".tocbss"), 0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
-  { NULL,                     0,  0, 0,            0 }
+  { NULL,                    0,  0, 0,            0 }
 };
 
 enum _ppc64_sec_type {
@@ -3252,10 +3269,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
                                asymbol **ret)
 {
   asymbol *s;
-  long i;
-  long count;
+  size_t i, j, count;
   char *names;
-  long symcount, codesecsym, codesecsymend, secsymend, opdsymend;
+  size_t symcount, codesecsym, codesecsymend, secsymend, opdsymend;
   asection *opd = NULL;
   bfd_boolean relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
   asymbol **syms;
@@ -3270,77 +3286,93 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
        return 0;
     }
 
-  symcount = static_count;
-  if (!relocatable)
-    symcount += dyn_count;
-  if (symcount == 0)
-    return 0;
-
-  syms = bfd_malloc ((symcount + 1) * sizeof (*syms));
-  if (syms == NULL)
-    return -1;
-
-  if (!relocatable && static_count != 0 && dyn_count != 0)
+  syms = NULL;
+  codesecsym = 0;
+  codesecsymend = 0;
+  secsymend = 0;
+  opdsymend = 0;
+  symcount = 0;
+  if (opd != NULL)
     {
-      /* Use both symbol tables.  */
-      memcpy (syms, static_syms, static_count * sizeof (*syms));
-      memcpy (syms + static_count, dyn_syms, (dyn_count + 1) * sizeof (*syms));
-    }
-  else if (!relocatable && static_count == 0)
-    memcpy (syms, dyn_syms, (symcount + 1) * sizeof (*syms));
-  else
-    memcpy (syms, static_syms, (symcount + 1) * sizeof (*syms));
+      symcount = static_count;
+      if (!relocatable)
+       symcount += dyn_count;
+      if (symcount == 0)
+       return 0;
 
-  synthetic_relocatable = relocatable;
-  synthetic_opd = opd;
-  qsort (syms, symcount, sizeof (*syms), compare_symbols);
+      syms = bfd_malloc ((symcount + 1) * sizeof (*syms));
+      if (syms == NULL)
+       return -1;
 
-  if (!relocatable && symcount > 1)
-    {
-      long j;
-      /* Trim duplicate syms, since we may have merged the normal and
-        dynamic symbols.  Actually, we only care about syms that have
-        different values, so trim any with the same value.  */
-      for (i = 1, j = 1; i < symcount; ++i)
-       if (syms[i - 1]->value + syms[i - 1]->section->vma
-           != syms[i]->value + syms[i]->section->vma)
+      if (!relocatable && static_count != 0 && dyn_count != 0)
+       {
+         /* Use both symbol tables.  */
+         memcpy (syms, static_syms, static_count * sizeof (*syms));
+         memcpy (syms + static_count, dyn_syms,
+                 (dyn_count + 1) * sizeof (*syms));
+       }
+      else if (!relocatable && static_count == 0)
+       memcpy (syms, dyn_syms, (symcount + 1) * sizeof (*syms));
+      else
+       memcpy (syms, static_syms, (symcount + 1) * sizeof (*syms));
+
+      /* Trim uninteresting symbols.  Interesting symbols are section,
+        function, and notype symbols.  */
+      for (i = 0, j = 0; i < symcount; ++i)
+       if ((syms[i]->flags & (BSF_FILE | BSF_OBJECT | BSF_THREAD_LOCAL
+                              | BSF_RELC | BSF_SRELC)) == 0)
          syms[j++] = syms[i];
       symcount = j;
-    }
 
-  i = 0;
-  /* Note that here and in compare_symbols we can't compare opd and
-     sym->section directly.  With separate debug info files, the
-     symbols will be extracted from the debug file while abfd passed
-     to this function is the real binary.  */
-  if (opd != NULL && strcmp (syms[i]->section->name, ".opd") == 0)
-    ++i;
-  codesecsym = i;
-
-  for (; i < symcount; ++i)
-    if (((syms[i]->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
-        != (SEC_CODE | SEC_ALLOC))
-       || (syms[i]->flags & BSF_SECTION_SYM) == 0)
-      break;
-  codesecsymend = i;
-
-  for (; i < symcount; ++i)
-    if ((syms[i]->flags & BSF_SECTION_SYM) == 0)
-      break;
-  secsymend = i;
+      synthetic_relocatable = relocatable;
+      synthetic_opd = opd;
+      qsort (syms, symcount, sizeof (*syms), compare_symbols);
+
+      if (!relocatable && symcount > 1)
+       {
+         /* Trim duplicate syms, since we may have merged the normal and
+            dynamic symbols.  Actually, we only care about syms that have
+            different values, so trim any with the same value.  */
+         for (i = 1, j = 1; i < symcount; ++i)
+           if (syms[i - 1]->value + syms[i - 1]->section->vma
+               != syms[i]->value + syms[i]->section->vma)
+             syms[j++] = syms[i];
+         symcount = j;
+       }
+
+      i = 0;
+      /* Note that here and in compare_symbols we can't compare opd and
+        sym->section directly.  With separate debug info files, the
+        symbols will be extracted from the debug file while abfd passed
+        to this function is the real binary.  */
+      if (strcmp (syms[i]->section->name, ".opd") == 0)
+       ++i;
+      codesecsym = i;
+
+      for (; i < symcount; ++i)
+       if (((syms[i]->section->flags & (SEC_CODE | SEC_ALLOC
+                                        | SEC_THREAD_LOCAL))
+            != (SEC_CODE | SEC_ALLOC))
+           || (syms[i]->flags & BSF_SECTION_SYM) == 0)
+         break;
+      codesecsymend = i;
 
-  if (opd != NULL)
-    for (; i < symcount; ++i)
-      if (strcmp (syms[i]->section->name, ".opd") != 0)
-       break;
-  opdsymend = i;
+      for (; i < symcount; ++i)
+       if ((syms[i]->flags & BSF_SECTION_SYM) == 0)
+         break;
+      secsymend = i;
 
-  for (; i < symcount; ++i)
-    if ((syms[i]->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
-       != (SEC_CODE | SEC_ALLOC))
-      break;
-  symcount = i;
+      for (; i < symcount; ++i)
+       if (strcmp (syms[i]->section->name, ".opd") != 0)
+         break;
+      opdsymend = i;
 
+      for (; i < symcount; ++i)
+       if ((syms[i]->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
+           != (SEC_CODE | SEC_ALLOC))
+         break;
+      symcount = i;
+    }
   count = 0;
 
   if (relocatable)
@@ -3348,7 +3380,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
       bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
       arelent *r;
       size_t size;
-      long relcount;
+      size_t relcount;
 
       if (opdsymend == secsymend)
        goto done;
@@ -3447,7 +3479,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
       bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
       bfd_byte *contents = NULL;
       size_t size;
-      long plt_count = 0;
+      size_t plt_count = 0;
       bfd_vma glink_vma = 0, resolv_vma = 0;
       asection *dynamic, *glink = NULL, *relplt = NULL;
       arelent *p;
@@ -3506,9 +3538,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
 
              if (dyn.d_tag == DT_PPC64_GLINK)
                {
-                 /* The first glink stub starts at offset 32; see
-                    comment in ppc64_elf_finish_dynamic_sections. */
-                 glink_vma = dyn.d_un.d_val + GLINK_CALL_STUB_SIZE - 8 * 4;
+                 /* The first glink stub starts at DT_PPC64_GLINK plus 32.
+                    See comment in ppc64_elf_finish_dynamic_sections. */
+                 glink_vma = dyn.d_un.d_val + 8 * 4;
                  /* The .glink section usually does not survive the final
                     link; search for the section (usually .text) where the
                     glink stubs now reside.  */
@@ -3584,7 +3616,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
          ent = bfd_get_64 (abfd, contents + syms[i]->value);
          if (!sym_exists_at (syms, opdsymend, symcount, -1, ent))
            {
-             long lo, hi;
+             size_t lo, hi;
              size_t len;
              asection *sec = abfd->sections;
 
@@ -3593,7 +3625,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
              hi = codesecsymend;
              while (lo < hi)
                {
-                 long mid = (lo + hi) >> 1;
+                 size_t mid = (lo + hi) >> 1;
                  if (syms[mid]->section->vma < ent)
                    lo = mid + 1;
                  else if (syms[mid]->section->vma > ent)
@@ -3785,9 +3817,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
    calls may use the function descriptor symbol, ie. "bl foo".  This
    behaves exactly as "bl .foo".  */
 
-/* Of those relocs that might be copied as dynamic relocs, this function
-   selects those that must be copied when linking a shared library,
-   even when the symbol is local.  */
+/* Of those relocs that might be copied as dynamic relocs, this
+   function selects those that must be copied when linking a shared
+   library or PIE, even when the symbol is local.  */
 
 static int
 must_be_dyn_reloc (struct bfd_link_info *info,
@@ -3796,6 +3828,10 @@ must_be_dyn_reloc (struct bfd_link_info *info,
   switch (r_type)
     {
     default:
+      /* Only relative relocs can be resolved when the object load
+        address isn't fixed.  DTPREL64 is excluded because the
+        dynamic linker needs to differentiate global dynamic from
+        local dynamic __tls_index pairs when PPC64_OPT_TLS is set.  */
       return 1;
 
     case R_PPC64_REL32:
@@ -3816,17 +3852,12 @@ must_be_dyn_reloc (struct bfd_link_info *info,
     case R_PPC64_TPREL16_HIGHEST:
     case R_PPC64_TPREL16_HIGHESTA:
     case R_PPC64_TPREL64:
-      return !bfd_link_executable (info);
+      /* These relocations are relative but in a shared library the
+        linker doesn't know the thread pointer base.  */
+      return bfd_link_dll (info);
     }
 }
 
-/* Whether an undefined weak symbol should resolve to its link-time
-   value, even in PIC or PIE objects.  */
-#define UNDEFWEAK_NO_DYNAMIC_RELOC(INFO, H)            \
-  ((H)->root.type == bfd_link_hash_undefweak           \
-   && (ELF_ST_VISIBILITY ((H)->other) != STV_DEFAULT   \
-       || (INFO)->dynamic_undefined_weak == 0))
-
 /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
    copying dynamic variables from a shared lib into an app's dynbss
    section, and instead use a dynamic relocation to point into the
@@ -3993,9 +4024,6 @@ struct ppc_link_hash_entry
   /* Track dynamic relocs copied for this symbol.  */
   struct elf_dyn_relocs *dyn_relocs;
 
-  /* Chain of aliases referring to a weakdef.  */
-  struct ppc_link_hash_entry *weakref;
-
   /* Link between function code and descriptor symbols.  */
   struct ppc_link_hash_entry *oh;
 
@@ -4018,22 +4046,29 @@ struct ppc_link_hash_entry
   unsigned int non_zero_localentry: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.
-     tls_optimize clears TLS_GD .. TLS_TPREL when optimizing to
-     indicate the corresponding GOT entry type is not needed.
-     tls_optimize may also set TLS_TPRELGD when a GD reloc turns into
-     a TPREL one.  We use a separate flag rather than setting TPREL
-     just for convenience in distinguishing the two cases.  */
-#define TLS_GD          1      /* GD reloc. */
-#define TLS_LD          2      /* LD reloc. */
-#define TLS_TPREL       4      /* TPREL reloc, => IE. */
-#define TLS_DTPREL      8      /* DTPREL reloc, => LD. */
-#define TLS_TLS                16      /* Any TLS reloc.  */
-#define TLS_EXPLICIT   32      /* Marks TOC section TLS relocs. */
+     Bits are or'd into the mask as the corresponding relocs are
+     encountered during check_relocs, with TLS_TLS being set when any
+     of the other TLS bits are set.  tls_optimize clears bits when
+     optimizing to indicate the corresponding GOT entry type is not
+     needed.  If set, TLS_TLS is never cleared.  tls_optimize may also
+     set TLS_TPRELGD when a GD reloc turns into a TPREL one.  We use a
+     separate flag rather than setting TPREL just for convenience in
+     distinguishing the two cases.
+     These flags are also kept for local symbols.  */
+#define TLS_TLS                 1      /* Any TLS reloc.  */
+#define TLS_GD          2      /* GD reloc. */
+#define TLS_LD          4      /* LD reloc. */
+#define TLS_TPREL       8      /* TPREL reloc, => IE. */
+#define TLS_DTPREL     16      /* DTPREL reloc, => LD. */
+#define TLS_MARK       32      /* __tls_get_addr call marked. */
 #define TLS_TPRELGD    64      /* TPREL reloc resulting from GD->IE. */
-#define PLT_IFUNC      128     /* STT_GNU_IFUNC.  */
+#define TLS_EXPLICIT   128     /* Marks TOC section TLS relocs. */
   unsigned char tls_mask;
+
+  /* The above field is also used to mark function symbols.  In which
+     case TLS_TLS will be 0.  */
+#define PLT_IFUNC       2      /* STT_GNU_IFUNC.  */
+#define NON_GOT        256     /* local symbol plt, not stored.  */
 };
 
 /* ppc64 ELF linker hash table.  */
@@ -4087,6 +4122,7 @@ struct ppc_link_hash_table
 
   /* Shortcuts to get to dynamic linker sections.  */
   asection *glink;
+  asection *global_entry;
   asection *sfpr;
   asection *brlt;
   asection *relbrlt;
@@ -4114,6 +4150,9 @@ struct ppc_link_hash_table
   unsigned int second_toc_pass:1;
   unsigned int do_toc_opt:1;
 
+  /* Set if tls optimization is enabled.  */
+  unsigned int do_tls_opt:1;
+
   /* Set on error.  */
   unsigned int stub_error:1;
 
@@ -4423,6 +4462,14 @@ create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
       || ! bfd_set_section_alignment (dynobj, htab->glink, 3))
     return FALSE;
 
+  /* The part of .glink used by global entry stubs, separate so that
+     it can be aligned appropriately without affecting htab->glink.  */
+  htab->global_entry = bfd_make_section_anyway_with_flags (dynobj, ".glink",
+                                                          flags);
+  if (htab->global_entry == NULL
+      || ! bfd_set_section_alignment (dynobj, htab->global_entry, 2))
+    return FALSE;
+
   if (!info->no_ld_generated_unwind_info)
     {
       flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
@@ -4629,8 +4676,8 @@ ppc_add_stub (const char *stub_name,
   if (stub_entry == NULL)
     {
       /* xgettext:c-format */
-      info->callbacks->einfo (_("%P: %B: cannot create stub entry %s\n"),
-                             section->owner, stub_name);
+      _bfd_error_handler (_("%pB: cannot create stub entry %s"),
+                         section->owner, stub_name);
       return NULL;
     }
 
@@ -4753,18 +4800,11 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
   if (eind->oh != NULL)
     edir->oh = ppc_follow_link (eind->oh);
 
-  /* If called to transfer flags for a weakdef during processing
-     of elf_adjust_dynamic_symbol, don't copy NON_GOT_REF.
-     We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
-  if (!(ELIMINATE_COPY_RELOCS
-       && eind->elf.root.type != bfd_link_hash_indirect
-       && edir->elf.dynamic_adjusted))
-    edir->elf.non_got_ref |= eind->elf.non_got_ref;
-
   if (edir->elf.versioned != versioned_hidden)
     edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
   edir->elf.ref_regular |= eind->elf.ref_regular;
   edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
+  edir->elf.non_got_ref |= eind->elf.non_got_ref;
   edir->elf.needs_plt |= eind->elf.needs_plt;
   edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
 
@@ -4773,39 +4813,9 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
      in order to simplify readonly_dynrelocs and save a field in the
      symbol hash entry, but that means dyn_relocs can't be used in any
      tests about a specific symbol, or affect other symbol flags which
-     are then tested.
-     Chain weakdefs so we can get from the weakdef back to an alias.
-     The list is circular so that we don't need to use u.weakdef as
-     well as this list to look at all aliases.  */
+     are then tested.  */
   if (eind->elf.root.type != bfd_link_hash_indirect)
-    {
-      struct ppc_link_hash_entry *cur, *add, *next;
-
-      add = eind;
-      do
-       {
-         cur = edir->weakref;
-         if (cur != NULL)
-           {
-             do
-               {
-                 /* We can be called twice for the same symbols.
-                    Don't make multiple loops.  */
-                 if (cur == add)
-                   return;
-                 cur = cur->weakref;
-               } while (cur != edir);
-           }
-         next = add->weakref;
-         if (cur != add)
-           {
-             add->weakref = edir->weakref != NULL ? edir->weakref : edir;
-             edir->weakref = add;
-           }
-         add = next;
-       } while (add != NULL && add != eind);
-      return;
-    }
+    return;
 
   /* Copy over any dynamic relocs we may have on the indirect sym.  */
   if (eind->dyn_relocs != NULL)
@@ -4997,8 +5007,8 @@ ppc64_elf_add_symbol_hook (bfd *ibfd,
        set_abiversion (ibfd, 2);
       else if (abiversion (ibfd) == 1)
        {
-         info->callbacks->einfo (_("%P: symbol '%s' has invalid st_other"
-                                   " for ABI version 1\n"), name);
+         _bfd_error_handler (_("symbol '%s' has invalid st_other"
+                               " for ABI version 1"), *name);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
@@ -5065,7 +5075,7 @@ ppc64_elf_archive_symbol_lookup (bfd *abfd,
   len = strlen (name);
   dot_name = bfd_alloc (abfd, len + 2);
   if (dot_name == NULL)
-    return (struct elf_link_hash_entry *) 0 - 1;
+    return (struct elf_link_hash_entry *) -1;
   dot_name[0] = '.';
   memcpy (dot_name + 1, name, len + 1);
   h = _bfd_elf_archive_symbol_lookup (abfd, info, dot_name);
@@ -5164,59 +5174,97 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info)
 
   if (opd != NULL && opd->size != 0)
     {
+      BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal);
+      ppc64_elf_section_data (opd)->sec_type = sec_opd;
+
       if (abiversion (ibfd) == 0)
        set_abiversion (ibfd, 1);
       else if (abiversion (ibfd) >= 2)
        {
          /* xgettext:c-format */
-         info->callbacks->einfo (_("%P: %B .opd not allowed in ABI"
-                                   " version %d\n"),
-                                 ibfd, abiversion (ibfd));
+         _bfd_error_handler (_("%pB .opd not allowed in ABI version %d"),
+                             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_NDX (opd->size) * sizeof (*opd_sym_map);
-         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;
-       }
+  if (is_ppc64_elf (info->output_bfd))
+    {
+      /* 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));
     }
 
-  if (!is_ppc64_elf (info->output_bfd))
-    return TRUE;
   htab = ppc_hash_table (info);
   if (htab == NULL)
-    return FALSE;
+    return TRUE;
+
+  if (opd != NULL && opd->size != 0
+      && (ibfd->flags & DYNAMIC) == 0
+      && (opd->flags & SEC_RELOC) != 0
+      && opd->reloc_count != 0
+      && !bfd_is_abs_section (opd->output_section)
+      && info->gc_sections)
+    {
+      /* 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;
+      Elf_Internal_Shdr *symtab_hdr;
+      Elf_Internal_Rela *relocs, *rel_end, *rel;
+
+      amt = OPD_NDX (opd->size) * sizeof (*opd_sym_map);
+      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;
+      relocs = _bfd_elf_link_read_relocs (ibfd, opd, NULL, NULL,
+                                         info->keep_memory);
+      if (relocs == NULL)
+       return FALSE;
+      symtab_hdr = &elf_symtab_hdr (ibfd);
+      rel_end = relocs + opd->reloc_count - 1;
+      for (rel = relocs; rel < rel_end; rel++)
+       {
+         enum elf_ppc64_reloc_type r_type = ELF64_R_TYPE (rel->r_info);
+         unsigned long r_symndx = ELF64_R_SYM (rel->r_info);
 
-  /* 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));
+         if (r_type == R_PPC64_ADDR64
+             && ELF64_R_TYPE ((rel + 1)->r_info) == R_PPC64_TOC
+             && r_symndx < symtab_hdr->sh_info)
+           {
+             Elf_Internal_Sym *isym;
+             asection *s;
+
+             isym = bfd_sym_from_r_symndx (&htab->sym_cache, ibfd, r_symndx);
+             if (isym == NULL)
+               {
+                 if (elf_section_data (opd)->relocs != relocs)
+                   free (relocs);
+                 return FALSE;
+               }
+
+             s = bfd_section_from_elf_index (ibfd, isym->st_shndx);
+             if (s != NULL && s != opd)
+               opd_sym_map[OPD_NDX (rel->r_offset)] = s;
+           }
+       }
+      if (elf_section_data (opd)->relocs != relocs)
+       free (relocs);
+    }
 
   p = &htab->dot_syms;
   while ((eh = *p) != NULL)
@@ -5296,7 +5344,7 @@ update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
       elf_local_got_ents (abfd) = local_got_ents;
     }
 
-  if ((tls_type & (PLT_IFUNC | TLS_EXPLICIT)) == 0)
+  if ((tls_type & (NON_GOT | TLS_EXPLICIT)) == 0)
     {
       struct got_entry *ent;
 
@@ -5324,7 +5372,7 @@ update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
 
   local_plt = (struct plt_entry **) (local_got_ents + symtab_hdr->sh_info);
   local_got_tls_masks = (unsigned char *) (local_plt + symtab_hdr->sh_info);
-  local_got_tls_masks[r_symndx] |= tls_type;
+  local_got_tls_masks[r_symndx] |= tls_type & 0xff;
 
   return local_plt + r_symndx;
 }
@@ -5379,8 +5427,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   asection *sreloc;
-  asection **opd_sym_map;
   struct elf_link_hash_entry *tga, *dottga;
+  bfd_boolean is_opd;
 
   if (bfd_link_relocatable (info))
     return TRUE;
@@ -5407,11 +5455,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
   symtab_hdr = &elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
   sreloc = NULL;
-  opd_sym_map = NULL;
-  if (ppc64_elf_section_data (sec) != NULL
-      && ppc64_elf_section_data (sec)->sec_type == sec_opd)
-    opd_sym_map = ppc64_elf_section_data (sec)->u.opd.func_sec;
-
+  is_opd = ppc64_elf_section_data (sec)->sec_type == sec_opd;
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
     {
@@ -5427,17 +5471,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        h = NULL;
       else
        {
-         struct ppc_link_hash_entry *eh;
-
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          h = elf_follow_link (h);
-         eh = (struct ppc_link_hash_entry *) h;
-
-         /* PR15323, ref flags aren't set for references in the same
-            object.  */
-         h->root.non_ir_ref_regular = 1;
-         if (eh->is_func && eh->oh != NULL)
-           eh->oh->elf.root.non_ir_ref_regular = 1;
 
          if (h == htab->elf.hgot)
            sec->has_toc_reloc = 1;
@@ -5463,7 +5498,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
              ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx,
-                                            rel->r_addend, PLT_IFUNC);
+                                            rel->r_addend,
+                                            NON_GOT | PLT_IFUNC);
              if (ifunc == NULL)
                return FALSE;
            }
@@ -5476,6 +5512,14 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_TLSLD:
          /* These special tls relocs tie a call to __tls_get_addr with
             its parameter symbol.  */
+         if (h != NULL)
+           ((struct ppc_link_hash_entry *) h)->tls_mask |= TLS_TLS | TLS_MARK;
+         else
+           if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
+                                       rel->r_addend,
+                                       NON_GOT | TLS_TLS | TLS_MARK))
+             return FALSE;
+         sec->has_tls_reloc = 1;
          break;
 
        case R_PPC64_GOT_TLSLD16:
@@ -5496,7 +5540,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 (bfd_link_pic (info))
+         if (bfd_link_dll (info))
            info->flags |= DF_STATIC_TLS;
          tls_type = TLS_TLS | TLS_TPREL;
          goto dogottls;
@@ -5646,7 +5690,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                ppc_howto_init ();
              /* xgettext:c-format */
              info->callbacks->einfo (_("%H: %s reloc unsupported "
-                                       "in shared libraries and PIEs.\n"),
+                                       "in shared libraries and PIEs\n"),
                                      abfd, sec, rel->r_offset,
                                      ppc64_elf_howto_table[r_type]->name);
              bfd_set_error (bfd_error_bad_value);
@@ -5758,7 +5802,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
        case R_PPC64_TPREL64:
          tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL;
-         if (bfd_link_pic (info))
+         if (bfd_link_dll (info))
            info->flags |= DF_STATIC_TLS;
          goto dotlstoc;
 
@@ -5834,34 +5878,17 @@ 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 (bfd_link_pic (info))
-           {
-             info->flags |= DF_STATIC_TLS;
-             goto dodyn;
-           }
-         break;
+         if (bfd_link_dll (info))
+           info->flags |= DF_STATIC_TLS;
+         goto dodyn;
 
        case R_PPC64_ADDR64:
-         if (opd_sym_map != NULL
+         if (is_opd
              && rel + 1 < rel_end
              && ELF64_R_TYPE ((rel + 1)->r_info) == R_PPC64_TOC)
            {
              if (h != NULL)
                ((struct ppc_link_hash_entry *) h)->is_func = 1;
-             else
-               {
-                 asection *s;
-                 Elf_Internal_Sym *isym;
-
-                 isym = bfd_sym_from_r_symndx (&htab->sym_cache,
-                                               abfd, r_symndx);
-                 if (isym == NULL)
-                   return FALSE;
-
-                 s = bfd_section_from_elf_index (abfd, isym->st_shndx);
-                 if (s != NULL && s != sec)
-                   opd_sym_map[OPD_NDX (rel->r_offset)] = s;
-               }
            }
          /* Fall through.  */
 
@@ -5901,7 +5928,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            h->non_got_ref = 1;
 
          /* Don't propagate .opd relocs.  */
-         if (NO_OPD_RELOCS && opd_sym_map != NULL)
+         if (NO_OPD_RELOCS && is_opd)
            break;
 
          /* If we are creating a shared library, and this is a reloc
@@ -6052,7 +6079,7 @@ ppc64_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
     {
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B uses unknown e_flags 0x%lx"), ibfd, iflags);
+       (_("%pB uses unknown e_flags 0x%lx"), ibfd, iflags);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
@@ -6060,7 +6087,7 @@ ppc64_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
     {
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: ABI version %ld is not compatible with ABI version %ld output"),
+       (_("%pB: ABI version %ld is not compatible with ABI version %ld output"),
         ibfd, iflags, oflags);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
@@ -6467,7 +6494,7 @@ 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.ref_dynamic && !eh->elf.forced_local)
          || ((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
@@ -6547,8 +6574,8 @@ ppc64_elf_gc_mark_hook (asection *sec,
                     a call reloc.  Mark the function descriptor too
                     against garbage collection.  */
                  fdh->elf.mark = 1;
-                 if (fdh->elf.u.weakdef != NULL)
-                   fdh->elf.u.weakdef->mark = 1;
+                 if (fdh->elf.is_weakalias)
+                   weakdef (&fdh->elf)->mark = 1;
                  eh = fdh;
                }
 
@@ -6597,181 +6624,6 @@ ppc64_elf_gc_mark_hook (asection *sec,
   return rsec;
 }
 
-/* Update the .got, .plt. and dynamic reloc reference counts for the
-   section being removed.  */
-
-static bfd_boolean
-ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
-                        asection *sec, const Elf_Internal_Rela *relocs)
-{
-  struct ppc_link_hash_table *htab;
-  Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **sym_hashes;
-  struct got_entry **local_got_ents;
-  const Elf_Internal_Rela *rel, *relend;
-
-  if (bfd_link_relocatable (info))
-    return TRUE;
-
-  if ((sec->flags & SEC_ALLOC) == 0)
-    return TRUE;
-
-  elf_section_data (sec)->local_dynrel = NULL;
-
-  htab = ppc_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  symtab_hdr = &elf_symtab_hdr (abfd);
-  sym_hashes = elf_sym_hashes (abfd);
-  local_got_ents = elf_local_got_ents (abfd);
-
-  relend = relocs + sec->reloc_count;
-  for (rel = relocs; rel < relend; rel++)
-    {
-      unsigned long r_symndx;
-      enum elf_ppc64_reloc_type r_type;
-      struct elf_link_hash_entry *h = NULL;
-      struct plt_entry **plt_list = NULL;
-      unsigned char tls_type = 0;
-
-      r_symndx = ELF64_R_SYM (rel->r_info);
-      r_type = ELF64_R_TYPE (rel->r_info);
-      if (r_symndx >= symtab_hdr->sh_info)
-       {
-         struct ppc_link_hash_entry *eh;
-         struct elf_dyn_relocs **pp;
-         struct elf_dyn_relocs *p;
-
-         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-         h = elf_follow_link (h);
-         eh = (struct ppc_link_hash_entry *) h;
-
-         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
-           if (p->sec == sec)
-             {
-               /* Everything must go for SEC.  */
-               *pp = p->next;
-               break;
-             }
-       }
-
-      switch (r_type)
-       {
-       case R_PPC64_GOT_TLSLD16:
-       case R_PPC64_GOT_TLSLD16_LO:
-       case R_PPC64_GOT_TLSLD16_HI:
-       case R_PPC64_GOT_TLSLD16_HA:
-         tls_type = TLS_TLS | TLS_LD;
-         goto dogot;
-
-       case R_PPC64_GOT_TLSGD16:
-       case R_PPC64_GOT_TLSGD16_LO:
-       case R_PPC64_GOT_TLSGD16_HI:
-       case R_PPC64_GOT_TLSGD16_HA:
-         tls_type = TLS_TLS | TLS_GD;
-         goto dogot;
-
-       case R_PPC64_GOT_TPREL16_DS:
-       case R_PPC64_GOT_TPREL16_LO_DS:
-       case R_PPC64_GOT_TPREL16_HI:
-       case R_PPC64_GOT_TPREL16_HA:
-         tls_type = TLS_TLS | TLS_TPREL;
-         goto dogot;
-
-       case R_PPC64_GOT_DTPREL16_DS:
-       case R_PPC64_GOT_DTPREL16_LO_DS:
-       case R_PPC64_GOT_DTPREL16_HI:
-       case R_PPC64_GOT_DTPREL16_HA:
-         tls_type = TLS_TLS | TLS_DTPREL;
-         goto dogot;
-
-       case R_PPC64_GOT16:
-       case R_PPC64_GOT16_DS:
-       case R_PPC64_GOT16_HA:
-       case R_PPC64_GOT16_HI:
-       case R_PPC64_GOT16_LO:
-       case R_PPC64_GOT16_LO_DS:
-       dogot:
-         {
-           struct got_entry *ent;
-
-           if (h != NULL)
-             ent = h->got.glist;
-           else
-             ent = local_got_ents[r_symndx];
-
-           for (; ent != NULL; ent = ent->next)
-             if (ent->addend == rel->r_addend
-                 && ent->owner == abfd
-                 && ent->tls_type == tls_type)
-               break;
-           if (ent == NULL)
-             abort ();
-           if (ent->got.refcount > 0)
-             ent->got.refcount -= 1;
-         }
-         if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1)
-           plt_list = &h->plt.plist;
-         break;
-
-       case R_PPC64_PLT16_HA:
-       case R_PPC64_PLT16_HI:
-       case R_PPC64_PLT16_LO:
-       case R_PPC64_PLT32:
-       case R_PPC64_PLT64:
-       case R_PPC64_REL14:
-       case R_PPC64_REL14_BRNTAKEN:
-       case R_PPC64_REL14_BRTAKEN:
-       case R_PPC64_REL24:
-         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;
-           }
-         break;
-
-       case R_PPC64_ADDR64:
-       case R_PPC64_ADDR16:
-       case R_PPC64_ADDR16_DS:
-       case R_PPC64_ADDR16_HA:
-       case R_PPC64_ADDR16_HI:
-       case R_PPC64_ADDR16_HIGH:
-       case R_PPC64_ADDR16_HIGHA:
-       case R_PPC64_ADDR16_HIGHER:
-       case R_PPC64_ADDR16_HIGHERA:
-       case R_PPC64_ADDR16_HIGHEST:
-       case R_PPC64_ADDR16_HIGHESTA:
-       case R_PPC64_ADDR16_LO:
-       case R_PPC64_ADDR16_LO_DS:
-         if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1
-             && rel->r_addend == 0)
-           plt_list = &h->plt.plist;
-         break;
-
-       default:
-         break;
-       }
-      if (plt_list != NULL)
-       {
-         struct plt_entry *ent;
-
-         for (ent = *plt_list; ent != NULL; ent = ent->next)
-           if (ent->addend == rel->r_addend)
-             break;
-         if (ent != NULL && ent->plt.refcount > 0)
-           ent->plt.refcount -= 1;
-       }
-    }
-  return TRUE;
-}
-
 /* The maximum size of .sfpr.  */
 #define SFPR_MAX (218*4)
 
@@ -6830,7 +6682,7 @@ sfpr_define (struct bfd_link_info *info,
                {
                  s->root.type = bfd_link_hash_defined;
                  s->root.u.def.section = stub_sec;
-                 s->root.u.def.value = (stub_sec->size
+                 s->root.u.def.value = (stub_sec->size - htab->sfpr->size
                                         + h->elf.root.u.def.value);
                  s->ref_regular = 1;
                  s->def_regular = 1;
@@ -7230,10 +7082,9 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
   return TRUE;
 }
 
-/* Return true if we have dynamic relocs against H that apply to
-   read-only sections.  */
+/* Find dynamic relocs for H that apply to read-only sections.  */
 
-static bfd_boolean
+static asection *
 readonly_dynrelocs (struct elf_link_hash_entry *h)
 {
   struct ppc_link_hash_entry *eh;
@@ -7245,13 +7096,14 @@ readonly_dynrelocs (struct elf_link_hash_entry *h)
       asection *s = p->sec->output_section;
 
       if (s != NULL && (s->flags & SEC_READONLY) != 0)
-       return TRUE;
+       return p->sec;
     }
-  return FALSE;
+  return NULL;
 }
 
 /* Return true if we have dynamic relocs against H or any of its weak
-   aliases, that apply to read-only sections.  */
+   aliases, that apply to read-only sections.  Cannot be used after
+   size_dynamic_sections.  */
 
 static bfd_boolean
 alias_readonly_dynrelocs (struct elf_link_hash_entry *h)
@@ -7263,7 +7115,7 @@ alias_readonly_dynrelocs (struct elf_link_hash_entry *h)
     {
       if (readonly_dynrelocs (&eh->elf))
        return TRUE;
-      eh = eh->weakref;
+      eh = (struct ppc_link_hash_entry *) eh->elf.u.alias;
     } while (eh != NULL && &eh->elf != h);
 
   return FALSE;
@@ -7324,6 +7176,23 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       || h->type == STT_GNU_IFUNC
       || h->needs_plt)
     {
+      bfd_boolean local = (((struct ppc_link_hash_entry *) h)->save_res
+                          || SYMBOL_CALLS_LOCAL (info, h)
+                          || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+      /* Discard dyn_relocs when non-pic if we've decided that a
+        function symbol is local and not an ifunc.  We keep dynamic
+        relocs for ifuncs when local rather than always emitting a
+        plt call stub for them and defining the symbol on the call
+        stub.  We can't do that for ELFv1 anyway (a function symbol
+        is defined on a descriptor, not code) and it can be faster at
+        run-time due to not needing to bounce through a stub.  The
+        dyn_relocs for ifuncs will be applied even in a static
+        executable.  */
+      if (!bfd_link_pic (info)
+         && h->type != STT_GNU_IFUNC
+         && local)
+       ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
+
       /* Clear procedure linkage table information for any symbol that
         won't need a .plt entry.  */
       struct plt_entry *ent;
@@ -7331,10 +7200,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
        if (ent->plt.refcount > 0)
          break;
       if (ent == NULL
-         || (h->type != STT_GNU_IFUNC
-             && (SYMBOL_CALLS_LOCAL (info, h)
-                 || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
-         || ((struct ppc_link_hash_entry *) h)->save_res)
+         || (h->type != STT_GNU_IFUNC && local))
        {
          h->plt.plist = NULL;
          h->needs_plt = 0;
@@ -7349,17 +7215,32 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
             relocs is that calling via a global entry stub costs a
             few more instructions, and pointer_equality_needed causes
             extra work in ld.so when resolving these symbols.  */
-         if (global_entry_stub (h)
-             && !alias_readonly_dynrelocs (h))
+         if (global_entry_stub (h))
            {
-             h->pointer_equality_needed = 0;
-             /* After adjust_dynamic_symbol, non_got_ref set in
-                the non-pic case means that dyn_relocs for this
-                symbol should be discarded.  */
-             h->non_got_ref = 0;
+             if (!readonly_dynrelocs (h))
+               {
+                 h->pointer_equality_needed = 0;
+                 /* If we haven't seen a branch reloc then we don't need
+                    a plt entry.  */
+                 if (!h->needs_plt)
+                   h->plt.plist = NULL;
+               }
+             else if (!bfd_link_pic (info))
+               /* We are going to be defining the function symbol on the
+                  plt stub, so no dyn_relocs needed when non-pic.  */
+               ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
            }
 
-         /* If making a plt entry, then we don't need copy relocs.  */
+         /* ELFv2 function symbols can't have copy relocs.  */
+         return TRUE;
+       }
+      else if (!h->needs_plt
+              && !readonly_dynrelocs (h))
+       {
+         /* If we haven't seen a branch reloc then we don't need a
+            plt entry.  */
+         h->plt.plist = NULL;
+         h->pointer_equality_needed = 0;
          return TRUE;
        }
     }
@@ -7369,14 +7250,15 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->u.weakdef != NULL)
-    {
-      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
-                 || h->u.weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->u.weakdef->root.u.def.section;
-      h->root.u.def.value = h->u.weakdef->root.u.def.value;
-      if (ELIMINATE_COPY_RELOCS)
-       h->non_got_ref = h->u.weakdef->non_got_ref;
+  if (h->is_weakalias)
+    {
+      struct elf_link_hash_entry *def = weakdef (h);
+      BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+      h->root.u.def.section = def->root.u.def.section;
+      h->root.u.def.value = def->root.u.def.value;
+      if (def->root.u.def.section == htab->elf.sdynbss
+         || def->root.u.def.section == htab->elf.sdynrelro)
+       ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
       return TRUE;
     }
 
@@ -7398,7 +7280,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       /* If -z nocopyreloc was given, don't generate them either.  */
       || info->nocopyreloc
 
-      /* If we didn't find any dynamic relocs in read-only sections, then
+      /* If we don't find any dynamic relocs in read-only sections, then
         we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
       || (ELIMINATE_COPY_RELOCS && !alias_readonly_dynrelocs (h))
 
@@ -7407,10 +7289,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
         definition for the variable.  Text relocations are preferable
         to an incorrect program.  */
       || h->protected_def)
-    {
-      h->non_got_ref = 0;
-      return TRUE;
-    }
+    return TRUE;
 
   if (h->plt.plist != NULL)
     {
@@ -7420,7 +7299,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
         sections.  Allow them to proceed, but warn that this might
         break at runtime.  */
       info->callbacks->einfo
-       (_("%P: copy reloc against `%T' requires lazy plt linking; "
+       (_("%P: copy reloc against `%pT' requires lazy plt linking; "
           "avoid setting LD_BIND_NOW=1 or upgrade gcc\n"),
         h->root.root.string);
     }
@@ -7437,11 +7316,6 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
      determine the address it must put in the global offset table, so
      both the dynamic object and the regular object will refer to the
      same memory location for the variable.  */
-
-  /* We must generate a R_PPC64_COPY reloc to tell the dynamic linker
-     to copy the initial value out of the dynamic object and into the
-     runtime process image.  We need to remember the offset into the
-     .rela.bss section we are going to use.  */
   if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
     {
       s = htab->elf.sdynrelro;
@@ -7454,10 +7328,15 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
     }
   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
+      /* We must generate a R_PPC64_COPY reloc to tell the dynamic
+        linker to copy the initial value out of the dynamic object
+        and into the runtime process image.  */
       srel->size += sizeof (Elf64_External_Rela);
       h->needs_copy = 1;
     }
 
+  /* We no longer want dyn_relocs.  */
+  ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
   return _bfd_elf_adjust_dynamic_copy (info, h, s);
 }
 
@@ -7635,7 +7514,9 @@ get_tls_mask (unsigned char **tls_maskp,
   if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd))
     return 0;
 
-  if ((*tls_maskp != NULL && **tls_maskp != 0)
+  if ((*tls_maskp != NULL
+       && (**tls_maskp & TLS_TLS) != 0
+       && **tls_maskp != (TLS_TLS | TLS_MARK))
       || sec == NULL
       || ppc64_elf_section_data (sec) == NULL
       || ppc64_elf_section_data (sec)->sec_type != sec_toc)
@@ -7687,7 +7568,7 @@ tocsave_find (struct ppc_link_hash_table *htab,
   if (ent.sec == NULL || ent.sec->output_section == NULL)
     {
       _bfd_error_handler
-       (_("%B: undefined symbol on R_PPC64_TOCSAVE relocation"), ibfd);
+       (_("%pB: undefined symbol on R_PPC64_TOCSAVE relocation"), ibfd);
       return NULL;
     }
 
@@ -7798,9 +7679,6 @@ dec_dynrel_count (bfd_vma r_info,
     case R_PPC64_TPREL16_HIGHERA:
     case R_PPC64_TPREL16_HIGHEST:
     case R_PPC64_TPREL16_HIGHESTA:
-      if (!bfd_link_pic (info))
-       return TRUE;
-
     case R_PPC64_TPREL64:
     case R_PPC64_DTPMOD64:
     case R_PPC64_DTPREL64:
@@ -7917,8 +7795,8 @@ dec_dynrel_count (bfd_vma r_info,
     }
 
   /* xgettext:c-format */
-  info->callbacks->einfo (_("%P: dynreloc miscount for %B, section %A\n"),
-                         sec->owner, sec);
+  _bfd_error_handler (_("dynreloc miscount for %pB, section %pA"),
+                     sec->owner, sec);
   bfd_set_error (bfd_error_bad_value);
   return FALSE;
 }
@@ -8006,7 +7884,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
                 optimization for them!  */
            broken_opd:
              _bfd_error_handler
-               (_("%B: .opd is not a regular array of opd entries"), ibfd);
+               (_("%pB: .opd is not a regular array of opd entries"), ibfd);
              broken = TRUE;
              break;
            }
@@ -8016,7 +7894,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: unexpected reloc type %u in .opd section"),
+               (_("%pB: unexpected reloc type %u in .opd section"),
                 ibfd, r_type);
              broken = TRUE;
              break;
@@ -8038,7 +7916,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
 
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: undefined sym `%s' in .opd section"),
+               (_("%pB: undefined sym `%s' in .opd section"),
                 ibfd, sym_name);
              broken = TRUE;
              break;
@@ -8104,7 +7982,6 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
          opd->adjust = bfd_zalloc (sec->owner, amt);
          if (opd->adjust == NULL)
            return FALSE;
-         ppc64_elf_section_data (sec)->sec_type = sec_opd;
 
          /* This seems a waste of time as input .opd sections are all
             zeros as generated by gcc, but I suppose there's no reason
@@ -8372,6 +8249,12 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
      --plt-localentry can cause trouble.  */
   if (htab->params->plt_localentry0 < 0)
     htab->params->plt_localentry0 = 0;
+  if (htab->params->plt_localentry0
+      && elf_link_hash_lookup (&htab->elf, "GLIBC_2.26",
+                              FALSE, FALSE, FALSE) == NULL)
+    _bfd_error_handler
+      (_("warning: --plt-localentry is especially dangerous without "
+        "ld.so support to detect ABI violations"));
 
   htab->tls_get_addr = ((struct ppc_link_hash_entry *)
                        elf_link_hash_lookup (&htab->elf, ".__tls_get_addr",
@@ -8800,7 +8683,8 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                                goto err_free_rel;
                              if (toc_tls != NULL)
                                {
-                                 if ((*toc_tls & (TLS_GD | TLS_LD)) != 0)
+                                 if ((*toc_tls & TLS_TLS) != 0
+                                     && ((*toc_tls & (TLS_GD | TLS_LD)) != 0))
                                    found_tls_get_addr_arg = 1;
                                  if (retval > 1)
                                    toc_ref[toc_ref_index] = 1;
@@ -8809,9 +8693,6 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                          continue;
                        }
 
-                     if (expecting_tls_get_addr != 1)
-                       continue;
-
                      /* Uh oh, we didn't find the expected call.  We
                         could just mark this symbol to exclude it
                         from tls optimization but it's safer to skip
@@ -8824,6 +8705,20 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                      goto err_free_rel;
                    }
 
+                 /* If we don't have old-style __tls_get_addr calls
+                    without TLSGD/TLSLD marker relocs, and we haven't
+                    found a new-style __tls_get_addr call with a
+                    marker for this symbol, then we either have a
+                    broken object file or an -mlongcall style
+                    indirect call to __tls_get_addr without a marker.
+                    Disable optimization in this case.  */
+                 if ((tls_clear & (TLS_GD | TLS_LD)) != 0
+                     && (tls_set & TLS_EXPLICIT) == 0
+                     && !sec->has_tls_get_addr_call
+                     && ((*tls_mask & (TLS_TLS | TLS_MARK))
+                         != (TLS_TLS | TLS_MARK)))
+                   continue;
+
                  if (expecting_tls_get_addr && htab->tls_get_addr != NULL)
                    {
                      struct plt_entry *ent;
@@ -8919,6 +8814,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
 
   if (toc_ref != NULL)
     free (toc_ref);
+  htab->do_tls_opt = 1;
   return TRUE;
 }
 
@@ -9328,7 +9224,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                          info->callbacks->einfo
                            /* xgettext:c-format */
                            (_("%H: toc optimization is not supported for"
-                              " %s instruction.\n"),
+                              " %s instruction\n"),
                             ibfd, sec, rel->r_offset & ~3, str);
                        }
                    }
@@ -9706,7 +9602,10 @@ allocate_got (struct elf_link_hash_entry *h,
       htab->elf.irelplt->size += rentsize;
       htab->got_reli_size += rentsize;
     }
-  else if ((bfd_link_pic (info)
+  else if (((bfd_link_pic (info)
+            && !((gent->tls_type & TLS_TPREL) != 0
+                 && bfd_link_executable (info)
+                 && SYMBOL_REFERENCES_LOCAL (info, h)))
            || (htab->elf.dynamic_sections_created
                && h->dynindx != -1
                && !SYMBOL_REFERENCES_LOCAL (info, h)))
@@ -9737,17 +9636,18 @@ merge_got_entries (struct got_entry **pent)
          }
 }
 
-/* If H is undefined weak, make it dynamic if that makes sense.  */
+/* If H is undefined, make it dynamic if that makes sense.  */
 
 static bfd_boolean
-ensure_undefweak_dynamic (struct bfd_link_info *info,
-                         struct elf_link_hash_entry *h)
+ensure_undef_dynamic (struct bfd_link_info *info,
+                     struct elf_link_hash_entry *h)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
 
   if (htab->dynamic_sections_created
-      && info->dynamic_undefined_weak != 0
-      && h->root.type == bfd_link_hash_undefweak
+      && ((info->dynamic_undefined_weak != 0
+          && h->root.type == bfd_link_hash_undefweak)
+         || h->root.type == bfd_link_hash_undefined)
       && h->dynindx == -1
       && !h->forced_local
       && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
@@ -9778,7 +9678,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   eh = (struct ppc_link_hash_entry *) h;
   /* Run through the TLS GD got entries first if we're changing them
      to TPREL.  */
-  if ((eh->tls_mask & TLS_TPRELGD) != 0)
+  if ((eh->tls_mask & (TLS_TLS | TLS_TPRELGD)) == (TLS_TLS | TLS_TPRELGD))
     for (gent = h->got.glist; gent != NULL; gent = gent->next)
       if (gent->got.refcount > 0
          && (gent->tls_type & TLS_GD) != 0)
@@ -9826,9 +9726,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   for (gent = h->got.glist; gent != NULL; gent = gent->next)
     if (!gent->is_indirect)
       {
-       /* Make sure this symbol is output as a dynamic symbol.
-          Undefined weak syms won't yet be marked as dynamic.  */
-       if (!ensure_undefweak_dynamic (info, h))
+       /* Make sure this symbol is output as a dynamic symbol.  */
+       if (!ensure_undef_dynamic (info, h))
          return FALSE;
 
        if (!is_ppc64_elf (gent->owner))
@@ -9843,6 +9742,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       && h->type != STT_GNU_IFUNC)
     eh->dyn_relocs = NULL;
 
+  /* Discard relocs on undefined symbols that must be local.  */
+  else if (h->root.type == bfd_link_hash_undefined
+          && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+    eh->dyn_relocs = NULL;
+
   /* Also discard relocs on undefined weak syms with non-default
      visibility, or when dynamic_undefined_weak says so.  */
   else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
@@ -9882,46 +9786,22 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
          if (eh->dyn_relocs != NULL)
            {
-             /* Make sure this symbol is output as a dynamic symbol.
-                Undefined weak syms won't yet be marked as dynamic.  */
-             if (!ensure_undefweak_dynamic (info, h))
+             /* Make sure this symbol is output as a dynamic symbol.  */
+             if (!ensure_undef_dynamic (info, h))
                return FALSE;
            }
        }
-      else if (h->type == STT_GNU_IFUNC)
-       {
-         /* A plt entry is always created when making direct calls to
-            an ifunc, even when building a static executable, but
-            that doesn't cover all cases.  We may have only an ifunc
-            initialised function pointer for a given ifunc symbol.
-
-            For ELFv2, dynamic relocations are not required when
-            generating a global entry PLT stub.  */
-         if (abiversion (info->output_bfd) >= 2)
-           {
-             if (global_entry_stub (h))
-               eh->dyn_relocs = NULL;
-           }
-
-         /* For ELFv1 we have function descriptors.  Descriptors need
-            to be treated like PLT entries and thus have dynamic
-            relocations.  One exception is when the function
-            descriptor is copied into .dynbss (which should only
-            happen with ancient versions of gcc).  */
-         else if (h->needs_copy)
-           eh->dyn_relocs = NULL;
-       }
-      else if (ELIMINATE_COPY_RELOCS)
+      else if (ELIMINATE_COPY_RELOCS && h->type != STT_GNU_IFUNC)
        {
          /* For the non-pic case, discard space for relocs against
             symbols which turn out to need copy relocs or are not
             dynamic.  */
-         if (!h->non_got_ref
-             && !h->def_regular)
+         if (h->dynamic_adjusted
+             && !h->def_regular
+             && !ELF_COMMON_DEF_P (h))
            {
-             /* Make sure this symbol is output as a dynamic symbol.
-                Undefined weak syms won't yet be marked as dynamic.  */
-             if (!ensure_undefweak_dynamic (info, h))
+             /* Make sure this symbol is output as a dynamic symbol.  */
+             if (!ensure_undef_dynamic (info, h))
                return FALSE;
 
              if (h->dynindx == -1)
@@ -9974,11 +9854,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                /* Make room for the .glink code.  */
                s = htab->glink;
                if (s->size == 0)
-                 s->size += GLINK_CALL_STUB_SIZE;
+                 s->size += GLINK_PLTRESOLVE_SIZE (htab);
                if (htab->opd_abi)
                  {
                    /* We need bigger stubs past index 32767.  */
-                   if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
+                   if (s->size >= GLINK_PLTRESOLVE_SIZE (htab) + 32768*2*4)
                      s->size += 4;
                    s->size += 2*4;
                  }
@@ -10008,6 +9888,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   return TRUE;
 }
 
+#define PPC_LO(v) ((v) & 0xffff)
+#define PPC_HI(v) (((v) >> 16) & 0xffff)
+#define PPC_HA(v) PPC_HI ((v) + 0x8000)
+
 /* Called via elf_link_hash_traverse from ppc64_elf_size_dynamic_sections
    to set up space for global entry stubs.  These are put in glink,
    after the branch table.  */
@@ -10018,7 +9902,7 @@ size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
   struct bfd_link_info *info;
   struct ppc_link_hash_table *htab;
   struct plt_entry *pent;
-  asection *s;
+  asection *s, *plt;
 
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
@@ -10034,7 +9918,8 @@ size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
   if (htab == NULL)
     return FALSE;
 
-  s = htab->glink;
+  s = htab->global_entry;
+  plt = htab->elf.splt;
   for (pent = h->plt.plist; pent != NULL; pent = pent->next)
     if (pent->plt.offset != (bfd_vma) -1
        && pent->addend == 0)
@@ -10043,11 +9928,39 @@ size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
           and we are not generating a shared library or pie, then we
           need to define the symbol in the executable on a call stub.
           This is to avoid text relocations.  */
-       s->size = (s->size + 15) & -16;
+       bfd_vma off, stub_align, stub_off, stub_size;
+       unsigned int align_power;
+
+       stub_size = 16;
+       stub_off = s->size;
+       if (htab->params->plt_stub_align >= 0)
+         align_power = htab->params->plt_stub_align;
+       else
+         align_power = -htab->params->plt_stub_align;
+       /* Setting section alignment is delayed until we know it is
+          non-empty.  Otherwise the .text output section will be
+          aligned at least to plt_stub_align even when no global
+          entry stubs are needed.  */
+       if (s->alignment_power < align_power)
+         s->alignment_power = align_power;
+       stub_align = (bfd_vma) 1 << align_power;
+       if (htab->params->plt_stub_align >= 0
+           || ((((stub_off + stub_size - 1) & -stub_align)
+                - (stub_off & -stub_align))
+               > ((stub_size - 1) & -stub_align)))
+         stub_off = (stub_off + stub_align - 1) & -stub_align;
+       off = pent->plt.offset + plt->output_offset + plt->output_section->vma;
+       off -= stub_off + s->output_offset + s->output_section->vma;
+       /* Note that for --plt-stub-align negative we have a possible
+          dependency between stub offset and size.  Break that
+          dependency by assuming the max stub size when calculating
+          the stub offset.  */
+       if (PPC_HA (off) == 0)
+         stub_size -= 4;
        h->root.type = bfd_link_hash_defined;
        h->root.u.def.section = s;
-       h->root.u.def.value = s->size;
-       s->size += 16;
+       h->root.u.def.value = stub_off;
+       s->size = stub_off + stub_size;
        break;
       }
   return TRUE;
@@ -10057,14 +9970,22 @@ size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
    read-only sections.  */
 
 static bfd_boolean
-maybe_set_textrel (struct elf_link_hash_entry *h, void *info)
+maybe_set_textrel (struct elf_link_hash_entry *h, void *inf)
 {
+  asection *sec;
+
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (readonly_dynrelocs (h))
+  sec = readonly_dynrelocs (h);
+  if (sec != NULL)
     {
-      ((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
+      struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+      info->flags |= DF_TEXTREL;
+      info->callbacks->minfo
+       (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"),
+        sec->owner, h->root.root.string, sec);
 
       /* Not an error, just cut short the traversal.  */
       return FALSE;
@@ -10183,12 +10104,14 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
                        rel_size *= 2;
                      }
                    s->size += ent_size;
-                   if ((*lgot_masks & PLT_IFUNC) != 0)
+                   if ((*lgot_masks & (TLS_TLS | PLT_IFUNC)) == PLT_IFUNC)
                      {
                        htab->elf.irelplt->size += rel_size;
                        htab->got_reli_size += rel_size;
                      }
-                   else if (bfd_link_pic (info))
+                   else if (bfd_link_pic (info)
+                            && !((ent->tls_type & TLS_TPREL) != 0
+                                 && bfd_link_executable (info)))
                      {
                        asection *srel = ppc64_elf_tdata (ibfd)->relgot;
                        srel->size += rel_size;
@@ -10222,9 +10145,6 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
-  /* Stash the end of glink branch table.  */
-  if (htab->glink != NULL)
-    htab->glink->rawsize = htab->glink->size;
 
   if (!htab->opd_abi && !bfd_link_pic (info))
     elf_link_hash_traverse (&htab->elf, size_global_entry_stubs, info);
@@ -10279,6 +10199,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
               || s == htab->elf.splt
               || s == htab->elf.iplt
               || s == htab->glink
+              || s == htab->global_entry
               || s == htab->elf.sdynbss
               || s == htab->elf.sdynrelro)
        {
@@ -10324,6 +10245,10 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
          continue;
        }
 
+      if (bfd_is_abs_section (s->output_section))
+       _bfd_error_handler (_("warning: discarding dynamic section %s"),
+                           s->name);
+
       if ((s->flags & SEC_HAS_CONTENTS) == 0)
        continue;
 
@@ -10560,10 +10485,6 @@ ppc_type_of_stub (asection *input_sec,
 #define ALWAYS_USE_FAKE_DEP 0
 #define ALWAYS_EMIT_R2SAVE 0
 
-#define PPC_LO(v) ((v) & 0xffff)
-#define PPC_HI(v) (((v) >> 16) & 0xffff)
-#define PPC_HA(v) PPC_HI ((v) + 0x8000)
-
 static inline unsigned int
 plt_stub_size (struct ppc_link_hash_table *htab,
               struct ppc_stub_hash_entry *stub_entry,
@@ -10602,17 +10523,30 @@ plt_stub_size (struct ppc_link_hash_table *htab,
   return size;
 }
 
-/* If this stub would cross fewer 2**plt_stub_align boundaries if we align,
-   then return the padding needed to do so.  */
+/* Depending on the sign of plt_stub_align:
+   If positive, return the padding to align to a 2**plt_stub_align
+   boundary.
+   If negative, if this stub would cross fewer 2**plt_stub_align
+   boundaries if we align, then return the padding needed to do so.  */
+
 static inline unsigned int
 plt_stub_pad (struct ppc_link_hash_table *htab,
              struct ppc_stub_hash_entry *stub_entry,
              bfd_vma plt_off)
 {
-  int stub_align = 1 << htab->params->plt_stub_align;
+  int stub_align;
   unsigned stub_size = plt_stub_size (htab, stub_entry, plt_off);
   bfd_vma stub_off = stub_entry->group->stub_sec->size;
 
+  if (htab->params->plt_stub_align >= 0)
+    {
+      stub_align = 1 << htab->params->plt_stub_align;
+      if ((stub_off & (stub_align - 1)) != 0)
+       return stub_align - (stub_off & (stub_align - 1));
+      return 0;
+    }
+
+  stub_align = 1 << -htab->params->plt_stub_align;
   if (((stub_off + stub_size - 1) & -stub_align) - (stub_off & -stub_align)
       > ((stub_size - 1) & -stub_align))
     return stub_align - (stub_off & (stub_align - 1));
@@ -10646,7 +10580,7 @@ build_plt_stub (struct ppc_link_hash_table *htab,
       bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
       bfd_vma pltindex = ((pltoff - PLT_INITIAL_ENTRY_SIZE (htab))
                          / PLT_ENTRY_SIZE (htab));
-      bfd_vma glinkoff = GLINK_CALL_STUB_SIZE + pltindex * 8;
+      bfd_vma glinkoff = GLINK_PLTRESOLVE_SIZE (htab) + pltindex * 8;
       bfd_vma to, from;
 
       if (pltindex > 32768)
@@ -10897,7 +10831,7 @@ get_r2off (struct bfd_link_info *info,
       if (strcmp (opd->name, ".opd") != 0
          || opd->reloc_count != 0)
        {
-         info->callbacks->einfo (_("%P: cannot find opd entry toc for `%T'\n"),
+         info->callbacks->einfo (_("%P: cannot find opd entry toc for `%pT'\n"),
                                  stub_entry->h->elf.root.root.string);
          bfd_set_error (bfd_error_bad_value);
          return (bfd_vma) -1;
@@ -10921,7 +10855,6 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   bfd_byte *loc;
   bfd_byte *p;
   bfd_vma dest, off;
-  int size;
   Elf_Internal_Rela *r;
   asection *plt;
 
@@ -10954,7 +10887,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
              + stub_entry->group->stub_sec->output_offset
              + stub_entry->group->stub_sec->output_section->vma);
 
-      size = 4;
+      p = loc;
       if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
        {
          bfd_vma r2off = get_r2off (info, stub_entry);
@@ -10964,31 +10897,29 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
              htab->stub_error = TRUE;
              return FALSE;
            }
-         bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc);
-         loc += 4;
-         size = 8;
+         bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), p);
+         p += 4;
          if (PPC_HA (r2off) != 0)
            {
              bfd_put_32 (htab->params->stub_bfd,
-                         ADDIS_R2_R2 | PPC_HA (r2off), loc);
-             loc += 4;
-             size += 4;
+                         ADDIS_R2_R2 | PPC_HA (r2off), p);
+             p += 4;
            }
          if (PPC_LO (r2off) != 0)
            {
              bfd_put_32 (htab->params->stub_bfd,
-                         ADDI_R2_R2 | PPC_LO (r2off), loc);
-             loc += 4;
-             size += 4;
+                         ADDI_R2_R2 | PPC_LO (r2off), p);
+             p += 4;
            }
-         off -= size - 4;
+         off -= p - loc;
        }
-      bfd_put_32 (htab->params->stub_bfd, B_DOT | (off & 0x3fffffc), loc);
+      bfd_put_32 (htab->params->stub_bfd, B_DOT | (off & 0x3fffffc), p);
+      p += 4;
 
       if (off + (1 << 25) >= (bfd_vma) (1 << 26))
        {
-         info->callbacks->einfo
-           (_("%P: long branch stub `%s' offset overflow\n"),
+         _bfd_error_handler
+           (_("long branch stub `%s' offset overflow"),
             stub_entry->root.string);
          htab->stub_error = TRUE;
          return FALSE;
@@ -10999,7 +10930,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          r = get_relocs (stub_entry->group->stub_sec, 1);
          if (r == NULL)
            return FALSE;
-         r->r_offset = loc - stub_entry->group->stub_sec->contents;
+         r->r_offset = p - 4 - 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)
@@ -11047,8 +10978,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
                                         FALSE, FALSE);
       if (br_entry == NULL)
        {
-         info->callbacks->einfo (_("%P: can't find branch stub `%s'\n"),
-                                 stub_entry->root.string);
+         _bfd_error_handler (_("can't find branch stub `%s'"),
+                             stub_entry->root.string);
          htab->stub_error = TRUE;
          return FALSE;
        }
@@ -11105,13 +11036,13 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
              + htab->brlt->output_section->vma);
 
       off = (dest
-            - elf_gp (htab->brlt->output_section->owner)
+            - elf_gp (info->output_bfd)
             - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
        {
          info->callbacks->einfo
-           (_("%P: linkage table error against `%T'\n"),
+           (_("%P: linkage table error against `%pT'\n"),
             stub_entry->root.string);
          bfd_set_error (bfd_error_bad_value);
          htab->stub_error = TRUE;
@@ -11139,23 +11070,20 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
            }
        }
 
+      p = loc;
       if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
        {
          if (PPC_HA (off) != 0)
            {
-             size = 16;
              bfd_put_32 (htab->params->stub_bfd,
-                         ADDIS_R12_R2 | PPC_HA (off), loc);
-             loc += 4;
+                         ADDIS_R12_R2 | PPC_HA (off), p);
+             p += 4;
              bfd_put_32 (htab->params->stub_bfd,
-                         LD_R12_0R12 | PPC_LO (off), loc);
+                         LD_R12_0R12 | PPC_LO (off), p);
            }
          else
-           {
-             size = 12;
-             bfd_put_32 (htab->params->stub_bfd,
-                         LD_R12_0R2 | PPC_LO (off), loc);
-           }
+           bfd_put_32 (htab->params->stub_bfd,
+                       LD_R12_0R2 | PPC_LO (off), p);
        }
       else
        {
@@ -11167,40 +11095,37 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
              return FALSE;
            }
 
-         bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc);
-         loc += 4;
-         size = 16;
+         bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), p);
+         p += 4;
          if (PPC_HA (off) != 0)
            {
-             size += 4;
              bfd_put_32 (htab->params->stub_bfd,
-                         ADDIS_R12_R2 | PPC_HA (off), loc);
-             loc += 4;
+                         ADDIS_R12_R2 | PPC_HA (off), p);
+             p += 4;
              bfd_put_32 (htab->params->stub_bfd,
-                         LD_R12_0R12 | PPC_LO (off), loc);
+                         LD_R12_0R12 | PPC_LO (off), p);
            }
          else
-           bfd_put_32 (htab->params->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc);
+           bfd_put_32 (htab->params->stub_bfd, LD_R12_0R2 | PPC_LO (off), p);
 
          if (PPC_HA (r2off) != 0)
            {
-             size += 4;
-             loc += 4;
+             p += 4;
              bfd_put_32 (htab->params->stub_bfd,
-                         ADDIS_R2_R2 | PPC_HA (r2off), loc);
+                         ADDIS_R2_R2 | PPC_HA (r2off), p);
            }
          if (PPC_LO (r2off) != 0)
            {
-             size += 4;
-             loc += 4;
+             p += 4;
              bfd_put_32 (htab->params->stub_bfd,
-                         ADDI_R2_R2 | PPC_LO (r2off), loc);
+                         ADDI_R2_R2 | PPC_LO (r2off), p);
            }
        }
-      loc += 4;
-      bfd_put_32 (htab->params->stub_bfd, MTCTR_R12, loc);
-      loc += 4;
-      bfd_put_32 (htab->params->stub_bfd, BCTR, loc);
+      p += 4;
+      bfd_put_32 (htab->params->stub_bfd, MTCTR_R12, p);
+      p += 4;
+      bfd_put_32 (htab->params->stub_bfd, BCTR, p);
+      p += 4;
       break;
 
     case ppc_stub_plt_call:
@@ -11256,14 +11181,14 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        }
 
       off = (dest
-            - elf_gp (plt->output_section->owner)
+            - elf_gp (info->output_bfd)
             - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
        {
          info->callbacks->einfo
            /* xgettext:c-format */
-           (_("%P: linkage table error against `%T'\n"),
+           (_("%P: linkage table error against `%pT'\n"),
             stub_entry->h != NULL
             ? stub_entry->h->elf.root.root.string
             : "<local sym>");
@@ -11304,7 +11229,6 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        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:
@@ -11315,7 +11239,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       return FALSE;
     }
 
-  stub_entry->group->stub_sec->size += size;
+  stub_entry->group->stub_sec->size += p - loc;
 
   if (htab->params->emit_stub_syms)
     {
@@ -11404,7 +11328,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        plt = htab->elf.iplt;
       off += (plt->output_offset
              + plt->output_section->vma
-             - elf_gp (plt->output_section->owner)
+             - elf_gp (info->output_bfd)
              - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       size = plt_stub_size (htab, stub_entry, off);
@@ -11468,7 +11392,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
 
-      /* If the branch offset if too big, use a ppc_stub_plt_branch.
+      /* If the branch offset is too big, use a ppc_stub_plt_branch.
         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
@@ -11482,8 +11406,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
                                             TRUE, FALSE);
          if (br_entry == NULL)
            {
-             info->callbacks->einfo (_("%P: can't build branch stub `%s'\n"),
-                                     stub_entry->root.string);
+             _bfd_error_handler (_("can't build branch stub `%s'"),
+                                 stub_entry->root.string);
              htab->stub_error = TRUE;
              return FALSE;
            }
@@ -11507,7 +11431,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          off = (br_entry->offset
                 + htab->brlt->output_offset
                 + htab->brlt->output_section->vma
-                - elf_gp (htab->brlt->output_section->owner)
+                - elf_gp (info->output_bfd)
                 - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
          if (info->emitrelocations)
@@ -11627,7 +11551,7 @@ ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
         output toc base plus 0x8000.  Making the input elf_gp an
         offset allows us to move the toc as a whole without
         recalculating input elf_gp.  */
-      off = htab->toc_curr - elf_gp (isec->output_section->owner);
+      off = htab->toc_curr - elf_gp (info->output_bfd);
       off += TOC_BASE_OFF;
 
       /* Die if someone uses a linker script that doesn't keep input
@@ -11656,7 +11580,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);
-  off = addr - elf_gp (isec->output_section->owner) + TOC_BASE_OFF;
+  off = addr - elf_gp (info->output_bfd) + TOC_BASE_OFF;
   elf_gp (isec->owner) = off;
 
   return TRUE;
@@ -11807,12 +11731,14 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
                  rel_size *= 2;
                }
              s->size += ent_size;
-             if ((*lgot_masks & PLT_IFUNC) != 0)
+             if ((*lgot_masks & (TLS_TLS | PLT_IFUNC)) == PLT_IFUNC)
                {
                  htab->elf.irelplt->size += rel_size;
                  htab->got_reli_size += rel_size;
                }
-             else if (bfd_link_pic (info))
+             else if (bfd_link_pic (info)
+                      && !((ent->tls_type & TLS_TPREL) != 0
+                           && bfd_link_executable (info)))
                {
                  asection *srel = ppc64_elf_tdata (ibfd)->relgot;
                  srel->size += rel_size;
@@ -12255,7 +12181,7 @@ group_sections (struct bfd_link_info *info,
          big_sec = total > group_size;
          if (big_sec && !suppress_size_errors)
            /* xgettext:c-format */
-           _bfd_error_handler (_("%B section %A exceeds stub group size"),
+           _bfd_error_handler (_("%pB section %pA exceeds stub group size"),
                                tail->owner, tail);
          curr_toc = htab->sec_info[tail->id].toc_off;
 
@@ -12680,7 +12606,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
                      if (!get_tls_mask (&tls_mask, NULL, NULL, &local_syms,
                                         irela - 1, input_bfd))
                        goto error_ret_free_internal;
-                     if (*tls_mask != 0)
+                     if ((*tls_mask & TLS_TLS) != 0)
                        continue;
                    }
 
@@ -12788,6 +12714,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
            stub_sec->flags &= ~SEC_RELOC;
          }
 
+      if (htab->stub_iteration <= STUB_SHRINK_ITER
+         || htab->brlt->rawsize < htab->brlt->size)
+       htab->brlt->rawsize = htab->brlt->size;
       htab->brlt->size = 0;
       htab->brlt->reloc_count = 0;
       htab->brlt->flags &= ~SEC_RELOC;
@@ -12809,7 +12738,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 
       if (htab->glink_eh_frame != NULL
          && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
-         && htab->glink_eh_frame->output_section->size != 0)
+         && htab->glink_eh_frame->output_section->size > 8)
        {
          size_t size = 0, align = 4;
 
@@ -12829,9 +12758,11 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
       if (htab->params->plt_stub_align != 0)
        for (group = htab->group; group != NULL; group = group->next)
          if (group->stub_sec != NULL)
-           group->stub_sec->size = ((group->stub_sec->size
-                                     + (1 << htab->params->plt_stub_align) - 1)
-                                    & -(1 << htab->params->plt_stub_align));
+           {
+             int align = abs (htab->params->plt_stub_align);
+             group->stub_sec->size
+               = (group->stub_sec->size + (1 << align) - 1) & -(1 << align);
+           }
 
       for (group = htab->group; group != NULL; group = group->next)
        if (group->stub_sec != NULL
@@ -12841,6 +12772,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
          break;
 
       if (group == NULL
+         && (htab->brlt->rawsize == htab->brlt->size
+             || (htab->stub_iteration > STUB_SHRINK_ITER
+                 && htab->brlt->rawsize > htab->brlt->size))
          && (htab->glink_eh_frame == NULL
              || htab->glink_eh_frame->rawsize == htab->glink_eh_frame->size))
        break;
@@ -13105,7 +13039,7 @@ build_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
   if (htab == NULL)
     return FALSE;
 
-  s = htab->glink;
+  s = htab->global_entry;
   for (pent = h->plt.plist; pent != NULL; pent = pent->next)
     if (pent->plt.offset != (bfd_vma) -1
        && pent->addend == 0)
@@ -13125,7 +13059,7 @@ build_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
        if (off + 0x80008000 > 0xffffffff || (off & 3) != 0)
          {
            info->callbacks->einfo
-             (_("%P: linkage table error against `%T'\n"),
+             (_("%P: linkage table error against `%pT'\n"),
               h->root.root.string);
            bfd_set_error (bfd_error_bad_value);
            htab->stub_error = TRUE;
@@ -13298,15 +13232,11 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
        }
       bfd_put_32 (htab->glink->owner, BCTR, p);
       p += 4;
-      while (p - htab->glink->contents < GLINK_CALL_STUB_SIZE)
-       {
-         bfd_put_32 (htab->glink->owner, NOP, p);
-         p += 4;
-       }
+      BFD_ASSERT (p == htab->glink->contents + GLINK_PLTRESOLVE_SIZE (htab));
 
       /* Build the .glink lazy link call stubs.  */
       indx = 0;
-      while (p < htab->glink->contents + htab->glink->rawsize)
+      while (p < htab->glink->contents + htab->glink->size)
        {
          if (htab->opd_abi)
            {
@@ -13329,12 +13259,12 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
          indx++;
          p += 4;
        }
-
-      /* Build .glink global entry stubs.  */
-      if (htab->glink->size > htab->glink->rawsize)
-       elf_link_hash_traverse (&htab->elf, build_global_entry_stubs, info);
     }
 
+  /* Build .glink global entry stubs.  */
+  if (htab->global_entry != NULL && htab->global_entry->size != 0)
+    elf_link_hash_traverse (&htab->elf, build_global_entry_stubs, info);
+
   if (htab->brlt != NULL && htab->brlt->size != 0)
     {
       htab->brlt->contents = bfd_zalloc (htab->brlt->owner,
@@ -13353,12 +13283,27 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
   /* Build the stubs as directed by the stub hash table.  */
   bfd_hash_traverse (&htab->stub_hash_table, ppc_build_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 (htab->relbrlt != NULL)
+    htab->relbrlt->reloc_count = 0;
+
+  if (htab->params->plt_stub_align != 0)
+    for (group = htab->group; group != NULL; group = group->next)
+      if ((stub_sec = group->stub_sec) != NULL)
+       {
+         int align = abs (htab->params->plt_stub_align);
+         stub_sec->size = (stub_sec->size + (1 << align) - 1) & -(1 << align);
+       }
+
   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);
+       memcpy (stub_sec->contents + stub_sec->size - htab->sfpr->size,
+               htab->sfpr->contents, htab->sfpr->size);
        if (htab->params->emit_stub_syms)
          {
            unsigned int i;
@@ -13367,19 +13312,8 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
              if (!sfpr_define (info, &save_res_funcs[i], stub_sec))
                return FALSE;
          }
-       stub_sec->size += htab->sfpr->size;
       }
 
-  if (htab->relbrlt != NULL)
-    htab->relbrlt->reloc_count = 0;
-
-  if (htab->params->plt_stub_align != 0)
-    for (group = htab->group; group != NULL; group = group->next)
-      if ((stub_sec = group->stub_sec) != NULL)
-       stub_sec->size = ((stub_sec->size
-                          + (1 << htab->params->plt_stub_align) - 1)
-                         & -(1 << htab->params->plt_stub_align));
-
   for (group = htab->group; group != NULL; group = group->next)
     if ((stub_sec = group->stub_sec) != NULL)
       {
@@ -13390,15 +13324,10 @@ 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 (group != NULL
-      || (htab->glink_eh_frame != NULL
-         && htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
+  if (group != NULL)
     {
       htab->stub_error = TRUE;
-      info->callbacks->einfo (_("%P: stubs don't match calculated size\n"));
+      _bfd_error_handler (_("stubs don't match calculated size"));
     }
 
   if (htab->stub_error)
@@ -13406,20 +13335,23 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
 
   if (stats != NULL)
     {
+      size_t len;
       *stats = bfd_malloc (500);
       if (*stats == NULL)
        return FALSE;
 
-      sprintf (*stats, _("linker stubs in %u group%s\n"
-                        "  branch       %lu\n"
-                        "  toc adjust   %lu\n"
-                        "  long branch  %lu\n"
-                        "  long toc adj %lu\n"
-                        "  plt call     %lu\n"
-                        "  plt call toc %lu\n"
-                        "  global entry %lu"),
-              stub_sec_count,
-              stub_sec_count == 1 ? "" : "s",
+      len = sprintf (*stats,
+                    ngettext ("linker stubs in %u group\n",
+                              "linker stubs in %u groups\n",
+                              stub_sec_count),
+                    stub_sec_count);
+      sprintf (*stats + len, _("  branch       %lu\n"
+                              "  toc adjust   %lu\n"
+                              "  long branch  %lu\n"
+                              "  long toc adj %lu\n"
+                              "  plt call     %lu\n"
+                              "  plt call toc %lu\n"
+                              "  global entry %lu"),
               htab->stub_count[ppc_stub_long_branch - 1],
               htab->stub_count[ppc_stub_long_branch_r2off - 1],
               htab->stub_count[ppc_stub_plt_branch - 1],
@@ -13657,7 +13589,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          wrel->r_addend = 0;
 
          /* For ld -r, remove relocations in debug sections against
-            sections defined in discarded sections.  Not done for
+            symbols 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)
@@ -13694,7 +13626,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            (local_plt + symtab_hdr->sh_info);
          tls_mask = lgot_masks[r_symndx];
        }
-      if (tls_mask == 0
+      if (((tls_mask & TLS_TLS) == 0 || tls_mask == (TLS_TLS | TLS_MARK))
          && (r_type == R_PPC64_TLS
              || r_type == R_PPC64_TLSGD
              || r_type == R_PPC64_TLSLD))
@@ -13722,7 +13654,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  || (sym_type == STT_SECTION
                      && (sec->flags & SEC_THREAD_LOCAL) != 0))))
        {
-         if (tls_mask != 0
+         if ((tls_mask & TLS_TLS) != 0
              && (r_type == R_PPC64_TLS
                  || r_type == R_PPC64_TLSGD
                  || r_type == R_PPC64_TLSLD))
@@ -13732,9 +13664,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            info->callbacks->einfo
              (!IS_PPC64_TLS_RELOC (r_type)
               /* xgettext:c-format */
-              ? _("%H: %s used with TLS symbol `%T'\n")
+              ? _("%H: %s used with TLS symbol `%pT'\n")
               /* xgettext:c-format */
-              : _("%H: %s used with non-TLS symbol `%T'\n"),
+              : _("%H: %s used with non-TLS symbol `%pT'\n"),
               input_bfd, input_section, rel->r_offset,
               ppc64_elf_howto_table[r_type]->name,
               sym_name);
@@ -13788,7 +13720,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                if (r_type == R_PPC64_TOC16_DS
                    || r_type == R_PPC64_TOC16_LO_DS)
                  {
-                   if (tls_mask != 0
+                   if ((tls_mask & TLS_TLS) != 0
                        && (tls_mask & (TLS_DTPREL | TLS_TPREL)) == 0)
                      goto toctprel;
                  }
@@ -13799,12 +13731,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                    if (retval == 2)
                      {
                        tls_gd = TLS_TPRELGD;
-                       if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
+                       if ((tls_mask & TLS_TLS) != 0
+                           && (tls_mask & TLS_GD) == 0)
                          goto tls_ldgd_opt;
                      }
                    else if (retval == 3)
                      {
-                       if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
+                       if ((tls_mask & TLS_TLS) != 0
+                           && (tls_mask & TLS_LD) == 0)
                          goto tls_ldgd_opt;
                      }
                  }
@@ -13814,7 +13748,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC64_GOT_TPREL16_HI:
        case R_PPC64_GOT_TPREL16_HA:
-         if (tls_mask != 0
+         if ((tls_mask & TLS_TLS) != 0
              && (tls_mask & TLS_TPREL) == 0)
            {
              rel->r_offset -= d_offset;
@@ -13826,7 +13760,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC64_GOT_TPREL16_DS:
        case R_PPC64_GOT_TPREL16_LO_DS:
-         if (tls_mask != 0
+         if ((tls_mask & TLS_TLS) != 0
              && (tls_mask & TLS_TPREL) == 0)
            {
            toctprel:
@@ -13851,7 +13785,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          break;
 
        case R_PPC64_TLS:
-         if (tls_mask != 0
+         if ((tls_mask & TLS_TLS) != 0
              && (tls_mask & TLS_TPREL) == 0)
            {
              insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
@@ -13879,13 +13813,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_GOT_TLSGD16_HI:
        case R_PPC64_GOT_TLSGD16_HA:
          tls_gd = TLS_TPRELGD;
-         if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
            goto tls_gdld_hi;
          break;
 
        case R_PPC64_GOT_TLSLD16_HI:
        case R_PPC64_GOT_TLSLD16_HA:
-         if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0)
            {
            tls_gdld_hi:
              if ((tls_mask & tls_gd) != 0)
@@ -13904,15 +13838,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_GOT_TLSGD16:
        case R_PPC64_GOT_TLSGD16_LO:
          tls_gd = TLS_TPRELGD;
-         if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
            goto tls_ldgd_opt;
          break;
 
        case R_PPC64_GOT_TLSLD16:
        case R_PPC64_GOT_TLSLD16_LO:
-         if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0)
            {
-             unsigned int insn1, insn2, insn3;
+             unsigned int insn1, insn2;
              bfd_vma offset;
 
            tls_ldgd_opt:
@@ -13991,18 +13925,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              bfd_put_32 (input_bfd, insn1,
                          contents + rel->r_offset - d_offset);
              if (offset != (bfd_vma) -1)
-               {
-                 insn3 = bfd_get_32 (input_bfd,
-                                     contents + offset + 4);
-                 if (insn3 == NOP
-                     || insn3 == CROR_151515 || insn3 == CROR_313131)
-                   {
-                     rel[1].r_offset += 4;
-                     bfd_put_32 (input_bfd, insn2, contents + offset + 4);
-                     insn2 = NOP;
-                   }
-                 bfd_put_32 (input_bfd, insn2, contents + offset);
-               }
+               bfd_put_32 (input_bfd, insn2, contents + offset);
              if ((tls_mask & tls_gd) == 0
                  && (tls_gd == 0 || toc_symndx != 0))
                {
@@ -14014,9 +13937,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          break;
 
        case R_PPC64_TLSGD:
-         if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
+             && rel + 1 < relend)
            {
-             unsigned int insn2, insn3;
+             unsigned int insn2;
              bfd_vma offset = rel->r_offset;
 
              if ((tls_mask & TLS_TPRELGD) != 0)
@@ -14041,15 +13965,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              /* Zap the reloc on the _tls_get_addr call too.  */
              BFD_ASSERT (offset == rel[1].r_offset);
              rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_PPC64_NONE);
-             insn3 = bfd_get_32 (input_bfd,
-                                 contents + offset + 4);
-             if (insn3 == NOP
-                 || insn3 == CROR_151515 || insn3 == CROR_313131)
-               {
-                 rel->r_offset += 4;
-                 bfd_put_32 (input_bfd, insn2, contents + offset + 4);
-                 insn2 = NOP;
-               }
              bfd_put_32 (input_bfd, insn2, contents + offset);
              if ((tls_mask & TLS_TPRELGD) == 0 && toc_symndx != 0)
                goto again;
@@ -14057,9 +13972,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          break;
 
        case R_PPC64_TLSLD:
-         if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0
+             && rel + 1 < relend)
            {
-             unsigned int insn2, insn3;
+             unsigned int insn2;
              bfd_vma offset = rel->r_offset;
 
              if (toc_symndx)
@@ -14084,15 +14000,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              BFD_ASSERT (offset == rel[1].r_offset);
              rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_PPC64_NONE);
              insn2 = 0x38630000;       /* addi 3,3,0 */
-             insn3 = bfd_get_32 (input_bfd,
-                                 contents + offset + 4);
-             if (insn3 == NOP
-                 || insn3 == CROR_151515 || insn3 == CROR_313131)
-               {
-                 rel->r_offset += 4;
-                 bfd_put_32 (input_bfd, insn2, contents + offset + 4);
-                 insn2 = NOP;
-               }
              bfd_put_32 (input_bfd, insn2, contents + offset);
              goto again;
            }
@@ -14373,13 +14280,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                      || stub_entry->stub_type == ppc_stub_plt_call_r2save)
                    info->callbacks->einfo
                      /* xgettext:c-format */
-                     (_("%H: call to `%T' lacks nop, can't restore toc; "
+                     (_("%H: call to `%pT' lacks nop, can't restore toc; "
                         "recompile with -fPIC\n"),
                       input_bfd, input_section, rel->r_offset, sym_name);
                  else
                    info->callbacks->einfo
                      /* xgettext:c-format */
-                     (_("%H: call to `%T' lacks nop, can't restore toc; "
+                     (_("%H: call to `%pT' lacks nop, can't restore toc; "
                         "(-mcmodel=small toc adjust stub)\n"),
                       input_bfd, input_section, rel->r_offset, sym_name);
 
@@ -14505,10 +14412,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       switch (r_type)
        {
        default:
-         info->callbacks->einfo
-           /* xgettext:c-format */
-           (_("%P: %B: unknown relocation type %d for `%T'\n"),
-            input_bfd, (int) r_type, sym_name);
+         /* xgettext:c-format */
+         _bfd_error_handler (_("%pB: %s unsupported"),
+                             input_bfd, ppc64_elf_howto_table[r_type]->name);
 
          bfd_set_error (bfd_error_bad_value);
          ret = FALSE;
@@ -14651,7 +14557,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                             && (h == NULL
                                 || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &h->elf)
                                 || (tls_type == (TLS_TLS | TLS_LD)
-                                    && !h->elf.def_dynamic))))
+                                    && !h->elf.def_dynamic))
+                            && !(tls_type == (TLS_TLS | TLS_TPREL)
+                                 && bfd_link_executable (info)
+                                 && SYMBOL_REFERENCES_LOCAL (info, &h->elf))))
                  relgot = ppc64_elf_tdata (ent->owner)->relgot;
                if (relgot != NULL)
                  {
@@ -14878,12 +14787,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            }
          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.  */
-           goto dodyn;
-         break;
+         /* The TPREL16 relocs shouldn't really be used in shared
+            libs or with non-local symbols as that will result in
+            DT_TEXTREL being set, but support them anyway.  */
+         goto dodyn;
 
        case R_PPC64_DTPREL16:
        case R_PPC64_DTPREL16_LO:
@@ -15056,7 +14963,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                          info->callbacks->einfo
                            /* xgettext:c-format */
                            (_("%H: %s for indirect "
-                              "function `%T' unsupported\n"),
+                              "function `%pT' unsupported\n"),
                             input_bfd, input_section, rel->r_offset,
                             ppc64_elf_howto_table[r_type]->name,
                             sym_name);
@@ -15167,7 +15074,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
          info->callbacks->einfo
            /* xgettext:c-format */
-           (_("%P: %B: %s is not supported for `%T'\n"),
+           (_("%P: %pB: %s is not supported for `%pT'\n"),
             input_bfd,
             ppc64_elf_howto_table[r_type]->name, sym_name);
 
@@ -15178,7 +15085,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
       /* Multi-instruction sequences that access the TOC can be
         optimized, eg. addis ra,r2,0; addi rb,ra,x;
-        to             nop;           addi rb,r2,x;  */
+        to             nop;           addi rb,r2,x;  */
       switch (r_type)
        {
        default:
@@ -15210,6 +15117,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            {
              bfd_byte *p = contents + (rel->r_offset & ~3);
              bfd_put_32 (input_bfd, NOP, p);
+             goto copy_reloc;
            }
          break;
 
@@ -15240,10 +15148,41 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              bfd_put_32 (input_bfd, insn, p);
            }
          break;
+
+       case R_PPC64_TPREL16_HA:
+         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+           {
+             bfd_byte *p = contents + (rel->r_offset & ~3);
+             insn = bfd_get_32 (input_bfd, p);
+             if ((insn & ((0x3f << 26) | 0x1f << 16))
+                 != ((15u << 26) | (13 << 16)) /* addis rt,13,imm */)
+               /* xgettext:c-format */
+               info->callbacks->minfo
+                 (_("%H: warning: %s unexpected insn %#x.\n"),
+                  input_bfd, input_section, rel->r_offset,
+                  ppc64_elf_howto_table[r_type]->name, insn);
+             else
+               {
+                 bfd_put_32 (input_bfd, NOP, p);
+                 goto copy_reloc;
+               }
+           }
+         break;
+
+       case R_PPC64_TPREL16_LO:
+       case R_PPC64_TPREL16_LO_DS:
+         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+           {
+             bfd_byte *p = contents + (rel->r_offset & ~3);
+             insn = bfd_get_32 (input_bfd, p);
+             insn &= ~(0x1f << 16);
+             insn |= 13 << 16;
+             bfd_put_32 (input_bfd, insn, p);
+           }
+         break;
        }
 
       /* Do any further special processing.  */
-      howto = ppc64_elf_howto_table[(int) r_type];
       switch (r_type)
        {
        default:
@@ -15324,7 +15263,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                /* xgettext:c-format */
                (_("%H: error: %s not a multiple of %u\n"),
                 input_bfd, input_section, rel->r_offset,
-                howto->name,
+                ppc64_elf_howto_table[r_type]->name,
                 mask + 1);
              bfd_set_error (bfd_error_bad_value);
              ret = FALSE;
@@ -15336,6 +15275,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
         because such sections are not SEC_ALLOC and thus ld.so will
         not process them.  */
+      howto = ppc64_elf_howto_table[(int) r_type];
       if (unresolved_reloc
          && !((input_section->flags & SEC_DEBUGGING) != 0
               && h->elf.def_dynamic)
@@ -15344,7 +15284,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        {
          info->callbacks->einfo
            /* xgettext:c-format */
-           (_("%H: unresolvable %s against `%T'\n"),
+           (_("%H: unresolvable %s against `%pT'\n"),
             input_bfd, input_section, rel->r_offset,
             howto->name,
             h->elf.root.root.string);
@@ -15441,7 +15381,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            {
              info->callbacks->einfo
                /* xgettext:c-format */
-               (_("%H: %s against `%T': error %d\n"),
+               (_("%H: %s against `%pT': error %d\n"),
                 input_bfd, input_section, rel->r_offset,
                 reloc_name, sym_name, (int) r);
              ret = FALSE;
@@ -15713,7 +15653,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
                 of glink rather than the first entry point, which is
                 what ld.so needs, and now have a bigger stub to
                 support automatic multiple TOCs.  */
-             dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 8 * 4;
+             dyn.d_un.d_ptr += GLINK_PLTRESOLVE_SIZE (htab) - 8 * 4;
              break;
 
            case DT_PPC64_OPD:
@@ -15830,8 +15770,8 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
                    + (p + 8 - htab->glink_eh_frame->contents));
            if (val + 0x80000000 > 0xffffffff)
              {
-               info->callbacks->einfo
-                 (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+               _bfd_error_handler
+                 (_("%s offset too large for .eh_frame sdata4 encoding"),
                   group->stub_sec->name);
                return FALSE;
              }
@@ -15849,8 +15789,8 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
                  + (p + 8 - htab->glink_eh_frame->contents));
          if (val + 0x80000000 > 0xffffffff)
            {
-             info->callbacks->einfo
-               (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+             _bfd_error_handler
+               (_("%s offset too large for .eh_frame sdata4 encoding"),
                 htab->glink->name);
              return FALSE;
            }
This page took 0.065776 seconds and 4 git commands to generate.