* addr2line.c (slurp_symtab): If canonicalization reveals that
[binutils-gdb.git] / bfd / elf64-ppc.c
index 27574b9d7ad20ae974fd191a590c32c6158aa745..22468ec7d3ab90e19220e1509e5d5d63857077c0 100644 (file)
@@ -2677,10 +2677,10 @@ ppc64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
     return FALSE;
 
   /* pr_cursig */
-  elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+  elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
 
   /* pr_pid */
-  elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 32);
+  elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 32);
 
   /* pr_reg */
   offset = 112;
@@ -2697,11 +2697,11 @@ ppc64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
   if (note->descsz != 136)
     return FALSE;
 
-  elf_tdata (abfd)->core_pid
+  elf_tdata (abfd)->core->pid
     = bfd_get_32 (abfd, note->descdata + 24);
-  elf_tdata (abfd)->core_program
+  elf_tdata (abfd)->core->program
     = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
-  elf_tdata (abfd)->core_command
+  elf_tdata (abfd)->core->command
     = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
 
   return TRUE;
@@ -3259,7 +3259,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
              slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
              if (! (*slurp_relocs) (abfd, relplt, dyn_syms, TRUE))
                goto free_contents_and_exit;
-       
+
              plt_count = relplt->size / sizeof (Elf64_External_Rela);
              size += plt_count * sizeof (asymbol);
 
@@ -3757,6 +3757,9 @@ struct ppc_link_hash_table
   struct ppc_link_hash_entry *tls_get_addr;
   struct ppc_link_hash_entry *tls_get_addr_fd;
 
+  /* The special .TOC. symbol.  */
+  struct ppc_link_hash_entry *dot_toc_dot;
+
   /* The size of reliplt used by got entry relocs.  */
   bfd_size_type got_reli_size;
 
@@ -4040,7 +4043,7 @@ ppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
   bfd_hash_table_free (&htab->branch_hash_table);
   if (htab->tocsave_htab)
     htab_delete (htab->tocsave_htab);
-  _bfd_generic_link_hash_table_free (hash);
+  _bfd_elf_link_hash_table_free (hash);
 }
 
 /* Satisfy the ELF linker by filling in some fields in our fake bfd.  */
@@ -4071,7 +4074,7 @@ ppc_stub_name (const asection *input_section,
               const Elf_Internal_Rela *rel)
 {
   char *stub_name;
-  bfd_size_type len;
+  ssize_t len;
 
   /* rel->r_addend is actually 64 bit, but who uses more than +/- 2^31
      offsets from a sym as a branch target?  In fact, we could
@@ -4085,10 +4088,10 @@ ppc_stub_name (const asection *input_section,
       if (stub_name == NULL)
        return stub_name;
 
-      sprintf (stub_name, "%08x.%s+%x",
-              input_section->id & 0xffffffff,
-              h->elf.root.root.string,
-              (int) rel->r_addend & 0xffffffff);
+      len = sprintf (stub_name, "%08x.%s+%x",
+                    input_section->id & 0xffffffff,
+                    h->elf.root.root.string,
+                    (int) rel->r_addend & 0xffffffff);
     }
   else
     {
@@ -4097,13 +4100,13 @@ ppc_stub_name (const asection *input_section,
       if (stub_name == NULL)
        return stub_name;
 
-      sprintf (stub_name, "%08x.%x:%x+%x",
-              input_section->id & 0xffffffff,
-              sym_sec->id & 0xffffffff,
-              (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
-              (int) rel->r_addend & 0xffffffff);
+      len = sprintf (stub_name, "%08x.%x:%x+%x",
+                    input_section->id & 0xffffffff,
+                    sym_sec->id & 0xffffffff,
+                    (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
+                    (int) rel->r_addend & 0xffffffff);
     }
-  if (stub_name[len - 2] == '+' && stub_name[len - 1] == '0')
+  if (len > 2 && stub_name[len - 2] == '+' && stub_name[len - 1] == '0')
     stub_name[len - 2] = 0;
   return stub_name;
 }
@@ -4485,7 +4488,7 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
   /* If we were called to copy over info for a weak sym, that's all.
      You might think dyn_relocs need not be copied over;  After all,
      both syms will be dynamic or both non-dynamic so we're just
-     moving reloc accounting around.  However, ELIMINATE_COPY_RELOCS 
+     moving reloc accounting around.  However, ELIMINATE_COPY_RELOCS
      code in ppc64_elf_adjust_dynamic_symbol needs to check for
      dyn_relocs in read-only sections, and it does so on what is the
      DIR sym here.  */
@@ -6608,7 +6611,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 `%s' requires lazy plt linking; "
+       (_("%P: copy reloc against `%T' requires lazy plt linking; "
           "avoid setting LD_BIND_NOW=1 or upgrade gcc\n"),
         h->root.root.string);
     }
@@ -7053,14 +7056,15 @@ dec_dynrel_count (bfd_vma r_info,
          void *vpp = &elf_section_data (sec)->local_dynrel;
          pp = (struct elf_dyn_relocs **) vpp;
        }
-
-      /* elf_gc_sweep may have already removed all dyn relocs associated
-        with local syms for a given section.  Don't report a dynreloc
-        miscount.  */
-      if (*pp == NULL)
-       return TRUE;
     }
 
+  /* elf_gc_sweep may have already removed all dyn relocs associated
+     with local syms for a given section.  Also, symbol flags are
+     changed by elf_gc_sweep_symbol, confusing the test above.  Don't
+     report a dynreloc miscount.  */
+  if (*pp == NULL && info->gc_sections)
+    return TRUE;
+
   while ((p = *pp) != NULL)
     {
       if (p->sec == sec)
@@ -8250,7 +8254,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
         .  addi ry,rx,addr@toc@l
         when addr is within 2G of the toc pointer.  This then means
         that the word storing "addr" in the toc is no longer needed.  */
-        
+
       if (!ppc64_elf_tdata (ibfd)->has_small_toc_reloc
          && toc->output_section->rawsize < (bfd_vma) 1 << 31
          && toc->reloc_count != 0)
@@ -8372,150 +8376,156 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
            goto error_ret;
 
          /* Mark toc entries referenced as used.  */
-         repeat = 0;
          do
-           for (rel = relstart; rel < relstart + sec->reloc_count; ++rel)
-             {
-               enum elf_ppc64_reloc_type r_type;
-               unsigned long r_symndx;
-               asection *sym_sec;
-               struct elf_link_hash_entry *h;
-               Elf_Internal_Sym *sym;
-               bfd_vma val;
-               enum {no_check, check_lo, check_ha} insn_check;
-
-               r_type = ELF64_R_TYPE (rel->r_info);
-               switch (r_type)
-                 {
-                 default:
-                   insn_check = no_check;
-                   break;
+           {
+             repeat = 0;
+             for (rel = relstart; rel < relstart + sec->reloc_count; ++rel)
+               {
+                 enum elf_ppc64_reloc_type r_type;
+                 unsigned long r_symndx;
+                 asection *sym_sec;
+                 struct elf_link_hash_entry *h;
+                 Elf_Internal_Sym *sym;
+                 bfd_vma val;
+                 enum {no_check, check_lo, check_ha} insn_check;
 
-                 case R_PPC64_GOT_TLSLD16_HA:
-                 case R_PPC64_GOT_TLSGD16_HA:
-                 case R_PPC64_GOT_TPREL16_HA:
-                 case R_PPC64_GOT_DTPREL16_HA:
-                 case R_PPC64_GOT16_HA:
-                 case R_PPC64_TOC16_HA:
-                   insn_check = check_ha;
-                   break;
+                 r_type = ELF64_R_TYPE (rel->r_info);
+                 switch (r_type)
+                   {
+                   default:
+                     insn_check = no_check;
+                     break;
 
-                 case R_PPC64_GOT_TLSLD16_LO:
-                 case R_PPC64_GOT_TLSGD16_LO:
-                 case R_PPC64_GOT_TPREL16_LO_DS:
-                 case R_PPC64_GOT_DTPREL16_LO_DS:
-                 case R_PPC64_GOT16_LO:
-                 case R_PPC64_GOT16_LO_DS:
-                 case R_PPC64_TOC16_LO:
-                 case R_PPC64_TOC16_LO_DS:
-                   insn_check = check_lo;
-                   break;
-                 }
+                   case R_PPC64_GOT_TLSLD16_HA:
+                   case R_PPC64_GOT_TLSGD16_HA:
+                   case R_PPC64_GOT_TPREL16_HA:
+                   case R_PPC64_GOT_DTPREL16_HA:
+                   case R_PPC64_GOT16_HA:
+                   case R_PPC64_TOC16_HA:
+                     insn_check = check_ha;
+                     break;
 
-               if (insn_check != no_check)
-                 {
-                   bfd_vma off = rel->r_offset & ~3;
-                   unsigned char buf[4];
-                   unsigned int insn;
+                   case R_PPC64_GOT_TLSLD16_LO:
+                   case R_PPC64_GOT_TLSGD16_LO:
+                   case R_PPC64_GOT_TPREL16_LO_DS:
+                   case R_PPC64_GOT_DTPREL16_LO_DS:
+                   case R_PPC64_GOT16_LO:
+                   case R_PPC64_GOT16_LO_DS:
+                   case R_PPC64_TOC16_LO:
+                   case R_PPC64_TOC16_LO_DS:
+                     insn_check = check_lo;
+                     break;
+                   }
 
-                   if (!bfd_get_section_contents (ibfd, sec, buf, off, 4))
-                     {
-                       free (used);
-                       goto error_ret;
-                     }
-                   insn = bfd_get_32 (ibfd, buf);
-                   if (insn_check == check_lo
-                       ? !ok_lo_toc_insn (insn)
-                       : ((insn & ((0x3f << 26) | 0x1f << 16))
-                          != ((15u << 26) | (2 << 16)) /* addis rt,2,imm */))
-                     {
-                       char str[12];
-
-                       ppc64_elf_tdata (ibfd)->unexpected_toc_insn = 1;
-                       sprintf (str, "%#08x", insn);
-                       info->callbacks->einfo
-                         (_("%P: %H: toc optimization is not supported for"
-                            " %s instruction.\n"),
-                          ibfd, sec, rel->r_offset & ~3, str);
-                     }
-                 }
+                 if (insn_check != no_check)
+                   {
+                     bfd_vma off = rel->r_offset & ~3;
+                     unsigned char buf[4];
+                     unsigned int insn;
 
-               switch (r_type)
-                 {
-                 case R_PPC64_TOC16:
-                 case R_PPC64_TOC16_LO:
-                 case R_PPC64_TOC16_HI:
-                 case R_PPC64_TOC16_HA:
-                 case R_PPC64_TOC16_DS:
-                 case R_PPC64_TOC16_LO_DS:
-                   /* In case we're taking addresses of toc entries.  */
-                 case R_PPC64_ADDR64:
-                   break;
+                     if (!bfd_get_section_contents (ibfd, sec, buf, off, 4))
+                       {
+                         free (used);
+                         goto error_ret;
+                       }
+                     insn = bfd_get_32 (ibfd, buf);
+                     if (insn_check == check_lo
+                         ? !ok_lo_toc_insn (insn)
+                         : ((insn & ((0x3f << 26) | 0x1f << 16))
+                            != ((15u << 26) | (2 << 16)) /* addis rt,2,imm */))
+                       {
+                         char str[12];
 
-                 default:
-                   continue;
-                 }
+                         ppc64_elf_tdata (ibfd)->unexpected_toc_insn = 1;
+                         sprintf (str, "%#08x", insn);
+                         info->callbacks->einfo
+                           (_("%P: %H: toc optimization is not supported for"
+                              " %s instruction.\n"),
+                            ibfd, sec, rel->r_offset & ~3, str);
+                       }
+                   }
 
-               r_symndx = ELF64_R_SYM (rel->r_info);
-               if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
-                               r_symndx, ibfd))
-                 {
-                   free (used);
-                   goto error_ret;
-                 }
+                 switch (r_type)
+                   {
+                   case R_PPC64_TOC16:
+                   case R_PPC64_TOC16_LO:
+                   case R_PPC64_TOC16_HI:
+                   case R_PPC64_TOC16_HA:
+                   case R_PPC64_TOC16_DS:
+                   case R_PPC64_TOC16_LO_DS:
+                     /* In case we're taking addresses of toc entries.  */
+                   case R_PPC64_ADDR64:
+                     break;
 
-               if (sym_sec != toc)
-                 continue;
+                   default:
+                     continue;
+                   }
 
-               if (h != NULL)
-                 val = h->root.u.def.value;
-               else
-                 val = sym->st_value;
-               val += rel->r_addend;
+                 r_symndx = ELF64_R_SYM (rel->r_info);
+                 if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
+                                 r_symndx, ibfd))
+                   {
+                     free (used);
+                     goto error_ret;
+                   }
 
-               if (val >= toc->size)
-                 continue;
+                 if (sym_sec != toc)
+                   continue;
 
-               if ((skip[val >> 3] & can_optimize) != 0)
-                 {
-                   bfd_vma off;
-                   unsigned char opc;
+                 if (h != NULL)
+                   val = h->root.u.def.value;
+                 else
+                   val = sym->st_value;
+                 val += rel->r_addend;
 
-                   switch (r_type)
-                     {
-                     case R_PPC64_TOC16_HA:
-                       break;
+                 if (val >= toc->size)
+                   continue;
 
-                     case R_PPC64_TOC16_LO_DS:
-                       off = rel->r_offset + (bfd_big_endian (ibfd) ? -2 : 3);
-                       if (!bfd_get_section_contents (ibfd, sec, &opc, off, 1))
-                         {
-                           free (used);
-                           goto error_ret;
-                         }
-                       if ((opc & (0x3f << 2)) == (58u << 2))
+                 if ((skip[val >> 3] & can_optimize) != 0)
+                   {
+                     bfd_vma off;
+                     unsigned char opc;
+
+                     switch (r_type)
+                       {
+                       case R_PPC64_TOC16_HA:
                          break;
-                       /* Fall thru */
 
-                     default:
-                       /* Wrong sort of reloc, or not a ld.  We may
-                          as well clear ref_from_discarded too.  */
-                       skip[val >> 3] = 0;
-                     }
-                 }
+                       case R_PPC64_TOC16_LO_DS:
+                         off = rel->r_offset;
+                         off += (bfd_big_endian (ibfd) ? -2 : 3);
+                         if (!bfd_get_section_contents (ibfd, sec, &opc,
+                                                        off, 1))
+                           {
+                             free (used);
+                             goto error_ret;
+                           }
+                         if ((opc & (0x3f << 2)) == (58u << 2))
+                           break;
+                         /* Fall thru */
 
-               /* For the toc section, we only mark as used if
-                  this entry itself isn't unused.  */
-               if (sec == toc
-                   && !used[val >> 3]
-                   && (used[rel->r_offset >> 3]
-                       || !(skip[rel->r_offset >> 3] & ref_from_discarded)))
-                 /* Do all the relocs again, to catch reference
-                    chains.  */
-                 repeat = 1;
-
-               used[val >> 3] = 1;
-             }
+                       default:
+                         /* Wrong sort of reloc, or not a ld.  We may
+                            as well clear ref_from_discarded too.  */
+                         skip[val >> 3] = 0;
+                       }
+                   }
+
+                 if (sec != toc)
+                   used[val >> 3] = 1;
+                 /* For the toc section, we only mark as used if this
+                    entry itself isn't unused.  */
+                 else if ((used[rel->r_offset >> 3]
+                           || !(skip[rel->r_offset >> 3] & ref_from_discarded))
+                          && !used[val >> 3])
+                   {
+                     /* Do all the relocs again, to catch reference
+                        chains.  */
+                     repeat = 1;
+                     used[val >> 3] = 1;
+                   }
+               }
+           }
          while (repeat);
 
          if (elf_section_data (sec)->relocs != relstart)
@@ -8657,7 +8667,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                          if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
                            ppc_howto_init ();
                          info->callbacks->einfo
-                           (_("%P: %H: %s relocation references "
+                           (_("%P: %H: %s references "
                               "optimized away TOC entry\n"),
                             ibfd, sec, rel->r_offset,
                             ppc64_elf_howto_table[r_type]->name);
@@ -9644,8 +9654,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
       bfd_vma glinkoff = GLINK_CALL_STUB_SIZE + pltindex * 8;
       bfd_vma to, from;
 
-      if (pltindex > 32767)
-       glinkoff += (pltindex - 32767) * 4;
+      if (pltindex > 32768)
+       glinkoff += (pltindex - 32768) * 4;
       to = (glinkoff
            + htab->glink->output_offset
            + htab->glink->output_section->vma);
@@ -9763,7 +9773,7 @@ build_plt_stub (struct ppc_link_hash_table *htab,
     {
       bfd_put_32 (obfd, CMPLDI_R2_0, p),                       p += 4;
       bfd_put_32 (obfd, BNECTR_P4, p),                         p += 4;
-      bfd_put_32 (obfd, B_DOT + cmp_branch_off, p),            p += 4;
+      bfd_put_32 (obfd, B_DOT | (cmp_branch_off & 0x3fffffc), p), p += 4;
     }
   else
     bfd_put_32 (obfd, BCTR, p),                                        p += 4;
@@ -9864,7 +9874,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 %s\n"),
+         info->callbacks->einfo (_("%P: cannot find opd entry toc for `%T'\n"),
                                  stub_entry->h->elf.root.root.string);
          bfd_set_error (bfd_error_bad_value);
          return 0;
@@ -9946,8 +9956,9 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       if (off + (1 << 25) >= (bfd_vma) (1 << 26))
        {
-         info->callbacks->einfo (_("%P: long branch stub `%s' offset overflow\n"),
-                                 stub_entry->root.string);
+         info->callbacks->einfo
+           (_("%P: long branch stub `%s' offset overflow\n"),
+            stub_entry->root.string);
          htab->stub_error = TRUE;
          return FALSE;
        }
@@ -10067,7 +10078,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
        {
          info->callbacks->einfo
-           (_("%P: linkage table error against `%s'\n"),
+           (_("%P: linkage table error against `%T'\n"),
             stub_entry->root.string);
          bfd_set_error (bfd_error_bad_value);
          htab->stub_error = TRUE;
@@ -10210,7 +10221,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
        {
          info->callbacks->einfo
-           (_("%P: linkage table error against `%s'\n"),
+           (_("%P: linkage table error against `%T'\n"),
             stub_entry->h != NULL
             ? stub_entry->h->elf.root.root.string
             : "<local sym>");
@@ -11294,6 +11305,7 @@ maybe_strip_output (struct bfd_link_info *info, asection *isec)
 {
   if (isec->size == 0
       && isec->output_section->size == 0
+      && !(isec->output_section->flags & SEC_KEEP)
       && !bfd_section_removed_from_list (info->output_bfd,
                                         isec->output_section)
       && elf_section_data (isec->output_section)->dynindx == 0)
@@ -11324,9 +11336,11 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
 
   htab->plt_static_chain = plt_static_chain;
   htab->plt_stub_align = plt_stub_align;
+  if (plt_thread_safe == -1 && !info->executable)
+    plt_thread_safe = 1;
   if (plt_thread_safe == -1)
     {
-      const char *const thread_starter[] =
+      static const char *const thread_starter[] =
        {
          "pthread_create",
          /* libstdc++ */
@@ -11342,7 +11356,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
          "GOMP_parallel_loop_dynamic_start",
          "GOMP_parallel_loop_guided_start",
          "GOMP_parallel_loop_runtime_start",
-         "GOMP_parallel_sections_start", 
+         "GOMP_parallel_sections_start",
        };
       unsigned i;
 
@@ -11357,6 +11371,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
        }
     }
   htab->plt_thread_safe = plt_thread_safe;
+  htab->dot_toc_dot = ((struct ppc_link_hash_entry *)
+                      elf_link_hash_lookup (&htab->elf, ".TOC.",
+                                            FALSE, FALSE, TRUE));
   stubs_always_before_branch = group_size < 0;
   if (group_size < 0)
     stub_group_size = -group_size;
@@ -12249,7 +12266,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
   for (; rel < relend; rel++)
     {
       enum elf_ppc64_reloc_type r_type;
-      bfd_vma addend, orig_addend;
+      bfd_vma addend;
       bfd_reloc_status_type r;
       Elf_Internal_Sym *sym;
       asection *sec;
@@ -12264,11 +12281,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_boolean warned;
+      enum { DEST_NORMAL, DEST_OPD, DEST_STUB } reloc_dest;
       unsigned int insn;
       unsigned int mask;
       struct ppc_stub_hash_entry *stub_entry;
       bfd_vma max_br_offset;
       bfd_vma from;
+      const Elf_Internal_Rela orig_rel = *rel;
 
       r_type = ELF64_R_TYPE (rel->r_info);
       r_symndx = ELF64_R_SYM (rel->r_info);
@@ -12288,7 +12307,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       sym_name = NULL;
       unresolved_reloc = FALSE;
       warned = FALSE;
-      orig_addend = rel->r_addend;
 
       if (r_symndx < symtab_hdr->sh_info)
        {
@@ -12355,6 +12373,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                      }
                  }
            }
+         if (h_elf == &htab->dot_toc_dot->elf)
+           {
+             relocation = (TOCstart
+                           + htab->stub_group[input_section->id].toc_off);
+             sec = bfd_abs_section_ptr;
+             unresolved_reloc = FALSE;
+           }
        }
       h = (struct ppc_link_hash_entry *) h_elf;
 
@@ -12421,8 +12446,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          else
            info->callbacks->einfo
              (!IS_PPC64_TLS_RELOC (r_type)
-              ? _("%P: %H: %s used with TLS symbol %s\n")
-              : _("%P: %H: %s used with non-TLS symbol %s\n"),
+              ? _("%P: %H: %s used with TLS symbol `%T'\n")
+              : _("%P: %H: %s used with non-TLS symbol `%T'\n"),
               input_bfd, input_section, rel->r_offset,
               ppc64_elf_howto_table[r_type]->name,
               sym_name);
@@ -12828,6 +12853,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       insn = 0;
       max_br_offset = 1 << 25;
       addend = rel->r_addend;
+      reloc_dest = DEST_NORMAL;
       switch (r_type)
        {
        default:
@@ -12877,7 +12903,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              && h->oh != NULL
              && h->oh->is_func_descriptor)
            fdh = ppc_follow_link (h->oh);
-         stub_entry = ppc_get_stub_entry (input_section, sec, fdh, rel, htab);
+         stub_entry = ppc_get_stub_entry (input_section, sec, fdh, &orig_rel,
+                                          htab);
          if (stub_entry != NULL
              && (stub_entry->stub_type == ppc_stub_plt_call
                  || stub_entry->stub_type == ppc_stub_plt_call_r2save
@@ -12932,25 +12959,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                    }
                  else
                    {
-                     if (strcmp (input_section->output_section->name,
-                                 ".init") == 0
-                         || strcmp (input_section->output_section->name,
-                                    ".fini") == 0)
-                       info->callbacks->einfo
-                         (_("%P: %H: automatic multiple TOCs "
-                            "not supported using your crt files; "
-                            "recompile with -mminimal-toc or upgrade gcc\n"),
-                          input_bfd, input_section, rel->r_offset);
-                     else
-                       info->callbacks->einfo
-                         (_("%P: %H: sibling call optimization to `%s' "
-                            "does not allow automatic multiple TOCs; "
-                            "recompile with -mminimal-toc or "
-                            "-fno-optimize-sibling-calls, "
-                            "or make `%s' extern\n"),
-                          input_bfd, input_section, rel->r_offset,
-                          sym_name,
-                          sym_name);
+                     info->callbacks->einfo
+                       (_("%P: %H: call to `%T' lacks nop, can't restore toc; "
+                          "recompile with -fPIC"),
+                          input_bfd, input_section, rel->r_offset, sym_name);
+
                      bfd_set_error (bfd_error_bad_value);
                      ret = FALSE;
                    }
@@ -12976,6 +12989,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                {
                  relocation = dest;
                  addend = 0;
+                 reloc_dest = DEST_OPD;
                }
            }
 
@@ -13003,6 +13017,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                            + stub_entry->stub_sec->output_offset
                            + stub_entry->stub_sec->output_section->vma);
              addend = 0;
+             reloc_dest = DEST_STUB;
 
              if ((stub_entry->stub_type == ppc_stub_plt_call
                   || stub_entry->stub_type == ppc_stub_plt_call_r2save)
@@ -13060,7 +13075,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        {
        default:
          info->callbacks->einfo
-           (_("%P: %B: unknown relocation type %d for symbol %s\n"),
+           (_("%P: %B: unknown relocation type %d for `%T'\n"),
             input_bfd, (int) r_type, sym_name);
 
          bfd_set_error (bfd_error_bad_value);
@@ -13159,7 +13174,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  }
 
                for (; ent != NULL; ent = ent->next)
-                 if (ent->addend == orig_addend
+                 if (ent->addend == orig_rel.r_addend
                      && ent->owner == input_bfd
                      && ent->tls_type == tls_type)
                    break;
@@ -13312,7 +13327,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            {
              struct plt_entry *ent;
              for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next)
-               if (ent->addend == orig_addend
+               if (ent->addend == orig_rel.r_addend
                    && ent->plt.offset != (bfd_vma) -1)
                  {
                    relocation = (htab->plt->output_section->vma
@@ -13570,8 +13585,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                          : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
                        {
                          info->callbacks->einfo
-                           (_("%P: %H: relocation %s for indirect "
-                              "function %s unsupported\n"),
+                           (_("%P: %H: %s for indirect "
+                              "function `%T' unsupported\n"),
                             input_bfd, input_section, rel->r_offset,
                             ppc64_elf_howto_table[r_type]->name,
                             sym_name);
@@ -13675,7 +13690,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          /* These ones haven't been implemented yet.  */
 
          info->callbacks->einfo
-           (_("%P: %B: relocation %s is not supported for symbol %s\n"),
+           (_("%P: %B: %s is not supported for `%T'\n"),
             input_bfd,
             ppc64_elf_howto_table[r_type]->name, sym_name);
 
@@ -13845,7 +13860,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                                      rel->r_offset) != (bfd_vma) -1)
        {
          info->callbacks->einfo
-           (_("%P: %H: unresolvable %s relocation against symbol `%s'\n"),
+           (_("%P: %H: unresolvable %s against `%T'\n"),
             input_bfd, input_section, rel->r_offset,
             ppc64_elf_howto_table[(int) r_type]->name,
             h->elf.root.root.string);
@@ -13862,8 +13877,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
       if (r != bfd_reloc_ok)
        {
-         if (sym_name == NULL)
-           sym_name = "(null)";
+         char *more_info = NULL;
+         const char *reloc_name = ppc64_elf_howto_table[r_type]->name;
+
+         if (reloc_dest != DEST_NORMAL)
+           {
+             more_info = bfd_malloc (strlen (reloc_name) + 8);
+             if (more_info != NULL)
+               {
+                 strcpy (more_info, reloc_name);
+                 strcat (more_info, (reloc_dest == DEST_OPD
+                                     ? " (OPD)" : " (stub)"));
+                 reloc_name = more_info;
+               }
+           }
+
          if (r == bfd_reloc_overflow)
            {
              if (warned)
@@ -13882,21 +13910,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                }
 
              if (!((*info->callbacks->reloc_overflow)
-                   (info, (h ? &h->elf.root : NULL), sym_name,
-                    ppc64_elf_howto_table[r_type]->name,
-                    orig_addend, input_bfd, input_section, rel->r_offset)))
+                   (info, &h->elf.root, sym_name,
+                    reloc_name, orig_rel.r_addend,
+                    input_bfd, input_section, rel->r_offset)))
                return FALSE;
            }
          else
            {
              info->callbacks->einfo
-               (_("%P: %H: %s reloc against `%s': error %d\n"),
+               (_("%P: %H: %s against `%T': error %d\n"),
                 input_bfd, input_section, rel->r_offset,
-                ppc64_elf_howto_table[r_type]->name,
-                sym_name,
-                (int) r);
+                reloc_name, sym_name, (int) r);
              ret = FALSE;
            }
+         if (more_info != NULL)
+           free (more_info);
        }
     }