diff options
author | Alan Modra <amodra@gmail.com> | 2005-04-01 02:50:15 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2005-04-01 02:50:15 +0000 |
commit | 35090471860b6c110a9090aba7ff901ec019de2b (patch) | |
tree | 2fed8bd860189fe92f01177fc58cb6744ae0c8a3 /bfd/elf64-ppc.c | |
parent | 77623a344f4966ec46edcf3c68ea2fb29169d880 (diff) | |
download | gdb-35090471860b6c110a9090aba7ff901ec019de2b.zip gdb-35090471860b6c110a9090aba7ff901ec019de2b.tar.gz gdb-35090471860b6c110a9090aba7ff901ec019de2b.tar.bz2 |
* elf64-ppc.c (ppc64_elf_edit_toc): Account for dynamic relocs
that we no longer need.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r-- | bfd/elf64-ppc.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 9377564..592fbe0 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; |