* elf64-ppc.c (ppc64_elf_edit_toc): Account for dynamic relocs
authorAlan Modra <amodra@gmail.com>
Fri, 1 Apr 2005 02:50:15 +0000 (02:50 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 1 Apr 2005 02:50:15 +0000 (02:50 +0000)
that we no longer need.

bfd/ChangeLog
bfd/elf64-ppc.c

index a4c1de2..c5b7887 100644 (file)
@@ -1,5 +1,10 @@
 2005-04-01  Alan Modra  <amodra@bigpond.net.au>
 
+       * elf64-ppc.c (ppc64_elf_edit_toc): Account for dynamic relocs
+       that we no longer need.
+
+2005-04-01  Alan Modra  <amodra@bigpond.net.au>
+
        * elf64-ppc.c (ppc64_elf_get_synthetic_symtab): Return -1 on errors
        rather than 0.
        (ppc64_elf_check_relocs): Remove unnecessary SEC_ALLOC check.
index 9377564..592fbe0 100644 (file)
@@ -7056,6 +7056,107 @@ ppc64_elf_edit_toc (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
                    wrel->r_addend = rel->r_addend;
                    ++wrel;
                  }
+               else
+                 {
+                   unsigned long r_symndx;
+                   enum elf_ppc64_reloc_type r_type;
+                   asection *sym_sec;
+                   struct elf_link_hash_entry *h;
+                   Elf_Internal_Sym *sym;
+                   struct ppc_dyn_relocs *p;
+                   struct ppc_dyn_relocs **head;
+
+                   /* Can this reloc be dynamic?
+                      This switch, and later tests here should be kept
+                      in sync with the code in check_relocs.  */
+                   r_type = ELF64_R_TYPE (rel->r_info);
+                   switch (r_type)
+                     {
+                     default:
+                       continue;
+
+                     case R_PPC64_TPREL16:
+                     case R_PPC64_TPREL16_LO:
+                     case R_PPC64_TPREL16_HI:
+                     case R_PPC64_TPREL16_HA:
+                     case R_PPC64_TPREL16_DS:
+                     case R_PPC64_TPREL16_LO_DS:
+                     case R_PPC64_TPREL16_HIGHER:
+                     case R_PPC64_TPREL16_HIGHERA:
+                     case R_PPC64_TPREL16_HIGHEST:
+                     case R_PPC64_TPREL16_HIGHESTA:
+                       if (!info->shared)
+                         continue;
+
+                     case R_PPC64_TPREL64:
+                     case R_PPC64_DTPMOD64:
+                     case R_PPC64_DTPREL64:
+                     case R_PPC64_ADDR64:
+                     case R_PPC64_REL30:
+                     case R_PPC64_REL32:
+                     case R_PPC64_REL64:
+                     case R_PPC64_ADDR14:
+                     case R_PPC64_ADDR14_BRNTAKEN:
+                     case R_PPC64_ADDR14_BRTAKEN:
+                     case R_PPC64_ADDR16:
+                     case R_PPC64_ADDR16_DS:
+                     case R_PPC64_ADDR16_HA:
+                     case R_PPC64_ADDR16_HI:
+                     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:
+                     case R_PPC64_ADDR24:
+                     case R_PPC64_ADDR32:
+                     case R_PPC64_UADDR16:
+                     case R_PPC64_UADDR32:
+                     case R_PPC64_UADDR64:
+                     case R_PPC64_TOC:
+                       break;
+                     }
+
+                   r_symndx = ELF64_R_SYM (rel->r_info);
+                   if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
+                                   r_symndx, ibfd))
+                     goto error_ret;
+
+                   if ((info->shared
+                        && (MUST_BE_DYN_RELOC (r_type)
+                            || (h != NULL
+                                && (!info->symbolic
+                                    || h->root.type == bfd_link_hash_defweak
+                                    || !h->def_regular))))
+                       || (ELIMINATE_COPY_RELOCS
+                           && !info->shared
+                           && h != NULL
+                           && (h->root.type == bfd_link_hash_defweak
+                               || !h->def_regular)))
+                     ;
+                   else
+                     continue;
+
+                   if (h != NULL)
+                     head = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
+                   else
+                     {
+                       if (sym_sec == NULL)
+                         goto error_ret;
+
+                       head = ((struct ppc_dyn_relocs **)
+                               &elf_section_data (sym_sec)->local_dynrel);
+                     }
+                   for (p = *head; p != NULL; p = p->next)
+                     if (p->sec == toc)
+                       {
+                         p->count -= 1;
+                         if (!MUST_BE_DYN_RELOC (r_type))
+                           p->pc_count -= 1;
+                         break;
+                       }
+                 }
+
              toc->reloc_count = wrel - relstart;
              sz = elf_section_data (toc)->rel_hdr.sh_entsize;
              elf_section_data (toc)->rel_hdr.sh_size = toc->reloc_count * sz;