* elf32-bfin.c (bfd_const_reloc, bfd_oper_reloc, bfin_push_reloc,
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index 3f219fa9d725b33b752cd19ec450251d2935ecfe..fc8c182e83da94b31000c62349cd3a9e7d322a2e 100644 (file)
@@ -1,5 +1,5 @@
 /* PowerPC64-specific support for 64-bit ELF.
-   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
    Written by Linus Nordberg, Swox AB <info@swox.com>,
    based on elf32-ppc.c by Ian Lance Taylor.
@@ -89,12 +89,14 @@ static bfd_vma opd_entry_value
 #define elf_backend_check_directives         ppc64_elf_check_directives
 #define elf_backend_archive_symbol_lookup     ppc64_elf_archive_symbol_lookup
 #define elf_backend_check_relocs             ppc64_elf_check_relocs
+#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_always_size_sections      ppc64_elf_func_desc_adjust
 #define elf_backend_size_dynamic_sections     ppc64_elf_size_dynamic_sections
+#define elf_backend_action_discarded         ppc64_elf_action_discarded
 #define elf_backend_relocate_section         ppc64_elf_relocate_section
 #define elf_backend_finish_dynamic_symbol     ppc64_elf_finish_dynamic_symbol
 #define elf_backend_reloc_type_class         ppc64_elf_reloc_type_class
@@ -3462,18 +3464,21 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
   if (htab == NULL)
     return NULL;
 
-  if (! _bfd_elf_link_hash_table_init (&htab->elf, abfd, link_hash_newfunc))
+  if (!_bfd_elf_link_hash_table_init (&htab->elf, abfd, link_hash_newfunc,
+                                     sizeof (struct ppc_link_hash_entry)))
     {
       free (htab);
       return NULL;
     }
 
   /* Init the stub hash table too.  */
-  if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc))
+  if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc,
+                           sizeof (struct ppc_stub_hash_entry)))
     return NULL;
 
   /* And the branch hash table.  */
-  if (!bfd_hash_table_init (&htab->branch_hash_table, branch_hash_newfunc))
+  if (!bfd_hash_table_init (&htab->branch_hash_table, branch_hash_newfunc,
+                           sizeof (struct ppc_branch_hash_entry)))
     return NULL;
 
   /* Initializing two fields of the union is just cosmetic.  We really
@@ -3843,10 +3848,9 @@ move_plt_plist (struct ppc_link_hash_entry *from,
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
 
 static void
-ppc64_elf_copy_indirect_symbol
-  (const struct elf_backend_data *bed ATTRIBUTE_UNUSED,
-   struct elf_link_hash_entry *dir,
-   struct elf_link_hash_entry *ind)
+ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
+                               struct elf_link_hash_entry *dir,
+                               struct elf_link_hash_entry *ind)
 {
   struct ppc_link_hash_entry *edir, *eind;
 
@@ -3861,10 +3865,7 @@ ppc64_elf_copy_indirect_symbol
          struct ppc_dyn_relocs **pp;
          struct ppc_dyn_relocs *p;
 
-         if (eind->elf.root.type == bfd_link_hash_indirect)
-           abort ();
-
-         /* Add reloc counts against the weak sym to the strong sym
+         /* Add reloc counts against the indirect sym to the direct sym
             list.  Merge any entries against the same section.  */
          for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
            {
@@ -3944,15 +3945,16 @@ ppc64_elf_copy_indirect_symbol
   /* And plt entries.  */
   move_plt_plist (eind, edir);
 
-  if (edir->elf.dynindx == -1)
+  if (eind->elf.dynindx != -1)
     {
+      if (edir->elf.dynindx != -1)
+       _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                               edir->elf.dynstr_index);
       edir->elf.dynindx = eind->elf.dynindx;
       edir->elf.dynstr_index = eind->elf.dynstr_index;
       eind->elf.dynindx = -1;
       eind->elf.dynstr_index = 0;
     }
-  else
-    BFD_ASSERT (eind->elf.dynindx == -1);
 }
 
 /* Find the function descriptor hash entry from the given function code
@@ -4509,7 +4511,24 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_REL14:
        case R_PPC64_REL14_BRTAKEN:
        case R_PPC64_REL14_BRNTAKEN:
-         htab->has_14bit_branch = 1;
+         {
+           asection *dest = NULL;
+
+           /* Heuristic: If jumping outside our section, chances are
+              we are going to need a stub.  */
+           if (h != NULL)
+             {
+               /* If the sym is weak it may be overridden later, so
+                  don't assume we know where a weak sym lives.  */
+               if (h->root.type == bfd_link_hash_defined)
+                 dest = h->root.u.def.section;
+             }
+           else
+             dest = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+                                               sec, r_symndx);
+           if (dest != sec)
+             htab->has_14bit_branch = 1;
+         }
          /* Fall through.  */
 
        case R_PPC64_REL24:
@@ -4767,13 +4786,15 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                     easily.  Oh well.  */
 
                  asection *s;
+                 void *vpp;
+
                  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
                                                 sec, r_symndx);
                  if (s == NULL)
                    return FALSE;
 
-                 head = ((struct ppc_dyn_relocs **)
-                         &elf_section_data (s)->local_dynrel);
+                 vpp = &elf_section_data (s)->local_dynrel;
+                 head = (struct ppc_dyn_relocs **) vpp;
                }
 
              p = *head;
@@ -4922,6 +4943,54 @@ opd_entry_value (asection *opd_sec,
   return val;
 }
 
+/* Mark sections containing dynamically referenced symbols.  When
+   building shared libraries, we must assume that any visible symbol is
+   referenced.  */
+
+static bfd_boolean
+ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf)
+{
+  struct bfd_link_info *info = (struct bfd_link_info *) inf;
+  struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) h;
+
+  if (eh->elf.root.type == bfd_link_hash_warning)
+    eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link;
+
+  /* Dynamic linking info is on the func descriptor sym.  */
+  if (eh->oh != NULL
+      && eh->oh->is_func_descriptor
+      && (eh->oh->elf.root.type == bfd_link_hash_defined
+         || eh->oh->elf.root.type == bfd_link_hash_defweak))
+    eh = eh->oh;
+
+  if ((eh->elf.root.type == bfd_link_hash_defined
+       || eh->elf.root.type == bfd_link_hash_defweak)
+      && (eh->elf.ref_dynamic
+         || (!info->executable
+             && eh->elf.def_regular
+             && ELF_ST_VISIBILITY (eh->elf.other) != STV_INTERNAL
+             && ELF_ST_VISIBILITY (eh->elf.other) != STV_HIDDEN)))
+    {
+      asection *code_sec;
+
+      eh->elf.root.u.def.section->flags |= SEC_KEEP;
+
+      /* Function descriptor syms cause the associated
+        function code sym section to be marked.  */
+      if (eh->is_func_descriptor
+         && (eh->oh->elf.root.type == bfd_link_hash_defined
+             || eh->oh->elf.root.type == bfd_link_hash_defweak))
+       eh->oh->elf.root.u.def.section->flags |= SEC_KEEP;
+      else if (get_opd_info (eh->elf.root.u.def.section) != NULL
+              && opd_entry_value (eh->elf.root.u.def.section,
+                                  eh->elf.root.u.def.value,
+                                  &code_sec, NULL) != (bfd_vma) -1)
+       code_sec->flags |= SEC_KEEP;
+    }
+
+  return TRUE;
+}
+
 /* Return the section that should be marked against GC for a given
    relocation.  */
 
@@ -4941,7 +5010,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
       struct bfd_sym_chain *sym = info->gc_sym_list;
 
       info->gc_sym_list = NULL;
-      do
+      for (; sym != NULL; sym = sym->next)
        {
          struct ppc_link_hash_entry *eh;
 
@@ -4971,10 +5040,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
          rsec = eh->elf.root.u.def.section;
          if (!rsec->gc_mark)
            _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
-
-         sym = sym->next;
        }
-      while (sym != NULL);
     }
 
   /* Syms return NULL if we're marking .opd, so we avoid marking all
@@ -6118,10 +6184,25 @@ dec_dynrel_count (bfd_vma r_info,
 
   if (h != NULL)
     pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
-  else if (sym_sec != NULL)
-    pp = (struct ppc_dyn_relocs **) &elf_section_data (sym_sec)->local_dynrel;
   else
-    pp = (struct ppc_dyn_relocs **) &elf_section_data (sec)->local_dynrel;
+    {
+      if (sym_sec != NULL)
+       {
+         void *vpp = &elf_section_data (sym_sec)->local_dynrel;
+         pp = (struct ppc_dyn_relocs **) vpp;
+       }
+      else
+       {
+         void *vpp = &elf_section_data (sec)->local_dynrel;
+         pp = (struct ppc_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;
+    }
 
   while ((p = *pp) != NULL)
     {
@@ -6468,7 +6549,8 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
 
              if (skip)
                {
-                 if (!info->relocatable
+                 if (!NO_OPD_RELOCS
+                     && !info->relocatable
                      && !dec_dynrel_count (rel->r_info, sec, info,
                                            NULL, h, sym_sec))
                    goto error_ret;
@@ -7503,9 +7585,21 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
-      if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+      if (eh->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
-       eh->dyn_relocs = NULL;
+       {
+         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+           eh->dyn_relocs = NULL;
+
+         /* Make sure this symbol is output as a dynamic symbol.
+            Undefined weak syms won't yet be marked as dynamic.  */
+         else if (h->dynindx == -1
+                  && !h->forced_local)
+           {
+             if (! bfd_elf_link_record_dynamic_symbol (info, h))
+               return FALSE;
+           }
+       }
     }
   else if (ELIMINATE_COPY_RELOCS)
     {
@@ -7638,10 +7732,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        {
          struct ppc_dyn_relocs *p;
 
-         for (p = *((struct ppc_dyn_relocs **)
-                    &elf_section_data (s)->local_dynrel);
-              p != NULL;
-              p = p->next)
+         for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
            {
              if (!bfd_is_abs_section (p->sec)
                  && bfd_is_abs_section (p->sec->output_section))
@@ -7888,26 +7979,34 @@ ppc_type_of_stub (asection *input_sec,
 
   if (h != NULL)
     {
-      if (h->oh != NULL
-         && h->oh->is_func_descriptor)
-       h = h->oh;
+      struct ppc_link_hash_entry *fdh = h;
+      if (fdh->oh != NULL
+         && fdh->oh->is_func_descriptor)
+       fdh = fdh->oh;
 
-      if (h->elf.dynindx != -1)
+      if (fdh->elf.dynindx != -1)
        {
          struct plt_entry *ent;
 
-         for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next)
+         for (ent = fdh->elf.plt.plist; ent != NULL; ent = ent->next)
            if (ent->addend == rel->r_addend
                && ent->plt.offset != (bfd_vma) -1)
              {
-               *hash = h;
+               *hash = fdh;
                return ppc_stub_plt_call;
              }
        }
 
-      if (!(h->elf.root.type == bfd_link_hash_defined
-           || h->elf.root.type == bfd_link_hash_defweak)
-         || h->elf.root.u.def.section->output_section == NULL)
+      /* Here, we know we don't have a plt entry.  If we don't have a
+        either a defined function descriptor or a defined entry symbol
+        in a regular object file, then it is pointless trying to make
+        any other type of stub.  */
+      if (!((fdh->elf.root.type == bfd_link_hash_defined
+           || fdh->elf.root.type == bfd_link_hash_defweak)
+           && fdh->elf.root.u.def.section->output_section != NULL)
+         && !((h->elf.root.type == bfd_link_hash_defined
+               || h->elf.root.type == bfd_link_hash_defweak)
+              && h->elf.root.u.def.section->output_section != NULL))
        return ppc_stub_none;
     }
 
@@ -8015,7 +8114,13 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        }
       bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc);
 
-      BFD_ASSERT (off + (1 << 25) < (bfd_vma) (1 << 26));
+      if (off + (1 << 25) >= (bfd_vma) (1 << 26))
+       {
+         (*_bfd_error_handler) (_("long branch stub `%s' offset overflow"),
+                                stub_entry->root.string);
+         htab->stub_error = TRUE;
+         return FALSE;
+       }
 
       if (info->emitrelocations)
        {
@@ -8087,7 +8192,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (br_entry == NULL)
        {
          (*_bfd_error_handler) (_("can't find branch stub `%s'"),
-                                stub_entry->root.string + 9);
+                                stub_entry->root.string);
          htab->stub_error = TRUE;
          return FALSE;
        }
@@ -8331,7 +8436,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          if (br_entry == NULL)
            {
              (*_bfd_error_handler) (_("can't build branch stub `%s'"),
-                                    stub_entry->root.string + 9);
+                                    stub_entry->root.string);
              htab->stub_error = TRUE;
              return FALSE;
            }
@@ -8752,7 +8857,10 @@ group_sections (struct ppc_link_hash_table *htab,
 
          curr = tail;
          total = tail->size;
-         big_sec = total >= stub_group_size;
+         big_sec = total > stub_group_size;
+         if (big_sec)
+           (*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
+                                    tail->owner, tail);
          curr_toc = htab->stub_group[tail->id].toc_off;
 
          while ((prev = PREV_SEC (curr)) != NULL
@@ -8854,10 +8962,8 @@ ppc64_elf_size_stubs (bfd *output_bfd,
       bfd *input_bfd;
       unsigned int bfd_indx;
       asection *stub_sec;
-      bfd_boolean stub_changed;
 
       htab->stub_iteration += 1;
-      stub_changed = FALSE;
 
       for (input_bfd = info->input_bfds, bfd_indx = 0;
           input_bfd != NULL;
@@ -8867,6 +8973,9 @@ ppc64_elf_size_stubs (bfd *output_bfd,
          asection *section;
          Elf_Internal_Sym *local_syms = NULL;
 
+         if (!is_ppc64_elf_target (input_bfd->xvec))
+           continue;
+
          /* We'll need the symbol table in a second.  */
          symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
          if (symtab_hdr->sh_info == 0)
@@ -8944,16 +9053,25 @@ ppc64_elf_size_stubs (bfd *output_bfd,
 
                  ok_dest = FALSE;
                  fdh = NULL;
+                 sym_value = 0;
                  if (hash == NULL)
                    {
                      sym_value = sym->st_value;
                      ok_dest = TRUE;
                    }
-                 else
+                 else if (hash->elf.root.type == bfd_link_hash_defined
+                          || hash->elf.root.type == bfd_link_hash_defweak)
+                   {
+                     sym_value = hash->elf.root.u.def.value;
+                     if (sym_sec->output_section != NULL)
+                       ok_dest = TRUE;
+                   }
+                 else if (hash->elf.root.type == bfd_link_hash_undefweak
+                          || hash->elf.root.type == bfd_link_hash_undefined)
                    {
-                     sym_value = 0;
                      /* Recognise an old ABI func code entry sym, and
-                        use the func descriptor sym instead.  */
+                        use the func descriptor sym instead if it is
+                        defined.  */
                      if (hash->elf.root.root.string[0] == '.'
                          && (fdh = get_fdh (hash, htab)) != NULL)
                        {
@@ -8968,22 +9086,11 @@ ppc64_elf_size_stubs (bfd *output_bfd,
                          else
                            fdh = NULL;
                        }
-                     else if (hash->elf.root.type == bfd_link_hash_defined
-                              || hash->elf.root.type == bfd_link_hash_defweak)
-                       {
-                         sym_value = hash->elf.root.u.def.value;
-                         if (sym_sec->output_section != NULL)
-                           ok_dest = TRUE;
-                       }
-                     else if (hash->elf.root.type == bfd_link_hash_undefweak)
-                       ;
-                     else if (hash->elf.root.type == bfd_link_hash_undefined)
-                       ;
-                     else
-                       {
-                         bfd_set_error (bfd_error_bad_value);
-                         goto error_ret_free_internal;
-                       }
+                   }
+                 else
+                   {
+                     bfd_set_error (bfd_error_bad_value);
+                     goto error_ret_free_internal;
                    }
 
                  destination = 0;
@@ -9106,8 +9213,6 @@ ppc64_elf_size_stubs (bfd *output_bfd,
 
                  if (stub_entry->h != NULL)
                    htab->stub_globals += 1;
-
-                 stub_changed = TRUE;
                }
 
              /* We're done with the internal relocs, free them.  */
@@ -9125,16 +9230,14 @@ ppc64_elf_size_stubs (bfd *output_bfd,
            }
        }
 
-      if (!stub_changed)
-       break;
-
-      /* OK, we've added some stubs.  Find out the new size of the
+      /* We may have added some stubs.  Find out the new size of the
         stub sections.  */
       for (stub_sec = htab->stub_bfd->sections;
           stub_sec != NULL;
           stub_sec = stub_sec->next)
        if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
          {
+           stub_sec->rawsize = stub_sec->size;
            stub_sec->size = 0;
            stub_sec->reloc_count = 0;
          }
@@ -9145,6 +9248,18 @@ ppc64_elf_size_stubs (bfd *output_bfd,
 
       bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info);
 
+      for (stub_sec = htab->stub_bfd->sections;
+          stub_sec != NULL;
+          stub_sec = stub_sec->next)
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
+           && stub_sec->rawsize != stub_sec->size)
+         break;
+
+      /* Exit from this loop when no stubs have been added, and no stubs
+        have changed size.  */
+      if (stub_sec == NULL)
+       break;
+
       /* Ask the linker to do its stuff.  */
       (*htab->layout_sections_again) ();
     }
@@ -9428,6 +9543,24 @@ ppc64_elf_restore_symbols (struct bfd_link_info *info)
   elf_link_hash_traverse (&htab->elf, undo_symbol_twiddle, info);
 }
 
+/* What to do when ld finds relocations against symbols defined in
+   discarded sections.  */
+
+static unsigned int
+ppc64_elf_action_discarded (asection *sec)
+{
+  if (strcmp (".opd", sec->name) == 0)
+    return 0;
+
+  if (strcmp (".toc", sec->name) == 0)
+    return 0;
+
+  if (strcmp (".toc1", sec->name) == 0)
+    return 0;
+
+  return _bfd_elf_default_action_discarded (sec);
+}
+
 /* The RELOCATE_SECTION function is called by the ELF backend linker
    to handle the relocations for a section.
 
@@ -9481,9 +9614,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
   /* Disabled until we sort out how ld should choose 'y' vs 'at'.  */
   bfd_boolean is_power4 = FALSE;
 
-  if (info->relocatable)
-    return TRUE;
-
   /* Initialize howto table if needed.  */
   if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
     ppc_howto_init ();
@@ -9505,7 +9635,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
   for (; rel < relend; rel++)
     {
       enum elf_ppc64_reloc_type r_type;
-      bfd_vma addend;
+      bfd_vma addend, orig_addend;
       bfd_reloc_status_type r;
       Elf_Internal_Sym *sym;
       asection *sec;
@@ -9542,6 +9672,7 @@ 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)
        {
@@ -9560,11 +9691,25 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              if (adjust == -1)
                relocation = 0;
              else
-               relocation += adjust;
+               {
+                 /* If this is a relocation against the opd section sym
+                    and we have edited .opd, adjust the reloc addend so
+                    that ld -r and ld --emit-relocs output is correct.
+                    If it is a reloc against some other .opd symbol,
+                    then the symbol value will be adjusted later.  */
+                 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+                   rel->r_addend += adjust;
+                 else
+                   relocation += adjust;
+               }
            }
+         if (info->relocatable)
+           continue;
        }
       else
        {
+         if (info->relocatable)
+           continue;
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   h_elf, sec, relocation,
@@ -10001,10 +10146,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  if (stub_entry->stub_type == ppc_stub_plt_call)
                    {
                      /* If this is a plain branch rather than a branch
-                        and link, don't require a nop.  */
+                        and link, don't require a nop.  However, don't
+                        allow tail calls in a shared library as they
+                        will result in r2 being corrupted.  */
                      unsigned long br;
                      br = bfd_get_32 (input_bfd, contents + rel->r_offset);
-                     if ((br & 1) == 0)
+                     if (info->executable && (br & 1) == 0)
                        can_plt_call = TRUE;
                      else
                        stub_entry = NULL;
@@ -10055,8 +10202,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              && get_opd_info (sec) != NULL)
            {
              /* The branch destination is the value of the opd entry. */
-             bfd_vma off = (relocation - sec->output_section->vma
-                            - sec->output_offset + rel->r_addend);
+             bfd_vma off = (relocation + addend
+                            - sec->output_section->vma
+                            - sec->output_offset);
              bfd_vma dest = opd_entry_value (sec, off, NULL, NULL);
              if (dest != (bfd_vma) -1)
                {
@@ -10072,7 +10220,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  + input_section->output_section->vma);
 
          if (stub_entry == NULL
-             && (relocation + rel->r_addend - from + max_br_offset
+             && (relocation + addend - from + max_br_offset
                  >= 2 * max_br_offset)
              && r_type != R_PPC64_ADDR14_BRTAKEN
              && r_type != R_PPC64_ADDR14_BRNTAKEN)
@@ -10106,7 +10254,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              else
                {
                  /* Invert 'y' bit if not the default.  */
-                 if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
+                 if ((bfd_signed_vma) (relocation + addend - from) < 0)
                    insn ^= 0x01 << 21;
                }
 
@@ -10120,7 +10268,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                   && h->elf.root.type == bfd_link_hash_undefweak
                   && r_type == R_PPC64_REL24
                   && relocation == 0
-                  && rel->r_addend == 0)
+                  && addend == 0)
            {
              bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
              continue;
@@ -10229,7 +10377,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  }
 
                for (; ent != NULL; ent = ent->next)
-                 if (ent->addend == rel->r_addend
+                 if (ent->addend == orig_addend
                      && ent->owner == input_bfd
                      && ent->tls_type == tls_type)
                    break;
@@ -10264,7 +10412,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                    outrel.r_offset = (got->output_section->vma
                                       + got->output_offset
                                       + off);
-                   outrel.r_addend = rel->r_addend;
+                   outrel.r_addend = addend;
                    if (tls_type & (TLS_LD | TLS_GD))
                      {
                        outrel.r_addend = 0;
@@ -10277,7 +10425,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                            bfd_elf64_swap_reloca_out (output_bfd,
                                                       &outrel, loc);
                            outrel.r_offset += 8;
-                           outrel.r_addend = rel->r_addend;
+                           outrel.r_addend = addend;
                            outrel.r_info
                              = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
                          }
@@ -10315,7 +10463,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                   emitting a reloc.  */
                else
                  {
-                   relocation += rel->r_addend;
+                   relocation += addend;
                    if (tls_type == (TLS_TLS | TLS_LD))
                      relocation = 1;
                    else if (tls_type != 0)
@@ -10368,7 +10516,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 == rel->r_addend
+               if (ent->addend == orig_addend
                    && ent->plt.offset != (bfd_vma) -1)
                  {
                    relocation = (htab->plt->output_section->vma
@@ -10624,6 +10772,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              if (sreloc == NULL)
                abort ();
 
+             if (sreloc->reloc_count * sizeof (Elf64_External_Rela)
+                 >= sreloc->size)
+               abort ();
              loc = sreloc->contents;
              loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
              bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
@@ -10814,7 +10965,7 @@ 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,
-                    rel->r_addend, input_bfd, input_section, rel->r_offset)))
+                    orig_addend, input_bfd, input_section, rel->r_offset)))
                return FALSE;
            }
          else
@@ -10837,7 +10988,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
      adjusted.  Worse, reloc symbol indices will be for the output
      file rather than the input.  Save a copy of the relocs for
      opd_entry_value.  */
-  if (is_opd && info->emitrelocations)
+  if (is_opd && (info->emitrelocations || info->relocatable))
     {
       bfd_size_type amt;
       amt = input_section->reloc_count * sizeof (Elf_Internal_Rela);
This page took 0.039422 seconds and 4 git commands to generate.