From: Alan Modra Date: Fri, 1 Apr 2005 02:50:15 +0000 (+0000) Subject: * elf64-ppc.c (ppc64_elf_edit_toc): Account for dynamic relocs X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=35090471860b6c110a9090aba7ff901ec019de2b;p=binutils-gdb.git * elf64-ppc.c (ppc64_elf_edit_toc): Account for dynamic relocs that we no longer need. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a4c1de21b5d..c5b78870290 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2005-04-01 Alan Modra + + * elf64-ppc.c (ppc64_elf_edit_toc): Account for dynamic relocs + that we no longer need. + 2005-04-01 Alan Modra * elf64-ppc.c (ppc64_elf_get_synthetic_symtab): Return -1 on errors diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 9377564b1e2..592fbe02b2d 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -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;