aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2005-04-01 02:50:15 +0000
committerAlan Modra <amodra@gmail.com>2005-04-01 02:50:15 +0000
commit35090471860b6c110a9090aba7ff901ec019de2b (patch)
tree2fed8bd860189fe92f01177fc58cb6744ae0c8a3 /bfd
parent77623a344f4966ec46edcf3c68ea2fb29169d880 (diff)
downloadgdb-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')
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elf64-ppc.c101
2 files changed, 106 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index a4c1de2..c5b7887 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
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;