aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2004-08-09 00:22:53 +0000
committerAlan Modra <amodra@gmail.com>2004-08-09 00:22:53 +0000
commit4025353c276c5dce0358199e59379a1ca6e72bbb (patch)
tree9a8ebe491e6ff429974014e3b4cdb29c87ca587f
parentead80d253022288d1d3437f14445dec0c3371c86 (diff)
downloadfsf-binutils-gdb-4025353c276c5dce0358199e59379a1ca6e72bbb.zip
fsf-binutils-gdb-4025353c276c5dce0358199e59379a1ca6e72bbb.tar.gz
fsf-binutils-gdb-4025353c276c5dce0358199e59379a1ca6e72bbb.tar.bz2
* elf64-ppc.c (get_opd_info): New function.
(adjust_opd_syms): Use get_opd_info. Define removed symbols as zero. (ppc64_elf_edit_opd): Use get_opd_info. Check that sym has a dot before calling get_fdh. Test fdh rather than h before dereferencing fdh. Mark removed symbols in opd_adjust. (ppc64_elf_tls_optimize): Don't bother with opd adjustment here. (ppc64_elf_relocate_section): Use get_opd_info, and handle removed opd symbols. (ppc64_elf_output_symbol_hook): Likewise.
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/elf64-ppc.c92
2 files changed, 68 insertions, 36 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 42132ad..1d3d305 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,15 @@
+2004-08-09 Alan Modra <amodra@bigpond.net.au>
+
+ * elf64-ppc.c (get_opd_info): New function.
+ (adjust_opd_syms): Use get_opd_info. Define removed symbols as zero.
+ (ppc64_elf_edit_opd): Use get_opd_info. Check that sym has a dot
+ before calling get_fdh. Test fdh rather than h before dereferencing
+ fdh. Mark removed symbols in opd_adjust.
+ (ppc64_elf_tls_optimize): Don't bother with opd adjustment here.
+ (ppc64_elf_relocate_section): Use get_opd_info, and handle removed
+ opd symbols.
+ (ppc64_elf_output_symbol_hook): Likewise.
+
2004-08-06 Paul Brook <paul@codesourcery.com>
* elfarm-nabi.c (elf32_arm_howto_table): Add new EABI relocations.
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index d269b9f..1adb7a5 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -2492,6 +2492,16 @@ ppc64_elf_new_section_hook (bfd *abfd, asection *sec)
return _bfd_elf_new_section_hook (abfd, sec);
}
+
+static void *
+get_opd_info (asection * sec)
+{
+ if (sec != NULL
+ && ppc64_elf_section_data (sec) != NULL
+ && ppc64_elf_section_data (sec)->opd.adjust != NULL)
+ return ppc64_elf_section_data (sec)->opd.adjust;
+ return NULL;
+}
/* The following functions are specific to the ELF linker, while
functions above are used generally. Those named ppc64_elf_* are
@@ -4935,11 +4945,19 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
return TRUE;
sym_sec = eh->elf.root.u.def.section;
- if (sym_sec != NULL
- && elf_section_data (sym_sec) != NULL
- && (opd_adjust = ppc64_elf_section_data (sym_sec)->opd.adjust) != NULL)
+ opd_adjust = get_opd_info (sym_sec);
+ if (opd_adjust != NULL)
{
eh->elf.root.u.def.value += opd_adjust[eh->elf.root.u.def.value / 24];
+ long adjust = opd_adjust[eh->elf.root.u.def.value / 24];
+ if (adjust == -1)
+ {
+ /* This entry has been deleted. */
+ eh->elf.root.u.def.value = 0;
+ eh->elf.root.u.def.section = &bfd_abs_section;
+ }
+ else
+ eh->elf.root.u.def.value += adjust;
eh->adjust_done = 1;
}
return TRUE;
@@ -4966,7 +4984,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info)
struct elf_link_hash_entry **sym_hashes;
bfd_vma offset;
bfd_size_type amt;
- long *adjust;
+ long *opd_adjust;
bfd_boolean need_edit;
sec = bfd_get_section_by_name (ibfd, ".opd");
@@ -4974,15 +4992,15 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info)
continue;
amt = sec->size * sizeof (long) / 24;
- adjust = ppc64_elf_section_data (sec)->opd.adjust;
- if (adjust == NULL)
+ opd_adjust = get_opd_info (sec);
+ if (opd_adjust == NULL)
{
/* Must be a ld -r link. ie. check_relocs hasn't been
called. */
- adjust = bfd_zalloc (obfd, amt);
- ppc64_elf_section_data (sec)->opd.adjust = adjust;
+ opd_adjust = bfd_zalloc (obfd, amt);
+ ppc64_elf_section_data (sec)->opd.adjust = opd_adjust;
}
- memset (adjust, 0, amt);
+ memset (opd_adjust, 0, amt);
if (sec->output_section == bfd_abs_section_ptr)
continue;
@@ -5134,7 +5152,8 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info)
if (rel->r_offset == offset)
{
struct ppc_link_hash_entry *fdh = NULL;
- if (h != NULL)
+ if (h != NULL
+ && h->root.root.string[0] == '.')
fdh = get_fdh ((struct ppc_link_hash_entry *) h,
ppc_hash_table (info));
@@ -5142,19 +5161,20 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info)
|| sym_sec->output_section == bfd_abs_section_ptr);
if (skip)
{
- if (h != NULL && sym_sec->owner == ibfd)
+ if (fdh != NULL && sym_sec->owner == ibfd)
{
/* Arrange for the function descriptor sym
to be dropped. */
fdh->elf.root.u.def.value = 0;
fdh->elf.root.u.def.section = sym_sec;
}
+ opd_adjust[rel->r_offset / 24] = -1;
}
else
{
/* We'll be keeping this opd entry. */
- if (h != NULL)
+ if (fdh != NULL)
{
/* Redefine the function descriptor symbol to
this location in the opd section. It is
@@ -5173,7 +5193,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info)
for the function descriptor sym which we
don't have at the moment. So keep an
array of adjustments. */
- adjust[rel->r_offset / 24] = wptr - rptr;
+ opd_adjust[rel->r_offset / 24] = wptr - rptr;
if (wptr != rptr)
memcpy (wptr, rptr, 24);
@@ -5345,17 +5365,9 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
value = h->root.u.def.value;
}
else
- {
- value = sym->st_value;
-
- if (elf_section_data (sym_sec) != NULL)
- {
- long *adjust;
- adjust = ppc64_elf_section_data (sym_sec)->opd.adjust;
- if (adjust != NULL)
- value += adjust[value / 24];
- }
- }
+ /* Symbols referenced by TLS relocs must be of type
+ STT_TLS. So no need for .opd local sym adjust. */
+ value = sym->st_value;
ok_tprel = FALSE;
is_local = FALSE;
@@ -7455,18 +7467,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
if (r_symndx < symtab_hdr->sh_info)
{
/* It's a local symbol. */
+ long *opd_adjust;
+
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
sym_name = bfd_elf_local_sym_name (input_bfd, sym);
sym_type = ELF64_ST_TYPE (sym->st_info);
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
- if (elf_section_data (sec) != NULL)
+ opd_adjust = get_opd_info (sec);
+ if (opd_adjust != NULL)
{
- long *opd_sym_adjust;
-
- opd_sym_adjust = ppc64_elf_section_data (sec)->opd.adjust;
- if (opd_sym_adjust != NULL)
- relocation += opd_sym_adjust[sym->st_value / 24];
+ long adjust = opd_adjust[(sym->st_value + rel->r_addend) / 24];
+ if (adjust == -1)
+ relocation = 0;
+ else
+ relocation += adjust;
}
}
else
@@ -8745,20 +8760,25 @@ ppc64_elf_output_symbol_hook (struct bfd_link_info *info,
asection *input_sec,
struct elf_link_hash_entry *h)
{
- long *adjust;
+ long *opd_adjust, adjust;
bfd_vma value;
- if (h != NULL
- || input_sec == NULL
- || ppc64_elf_section_data (input_sec) == NULL
- || (adjust = ppc64_elf_section_data (input_sec)->opd.adjust) == NULL)
+ if (h != NULL)
+ return TRUE;
+
+ opd_adjust = get_opd_info (input_sec);
+ if (opd_adjust == NULL)
return TRUE;
value = elfsym->st_value - input_sec->output_offset;
if (!info->relocatable)
value -= input_sec->output_section->vma;
- elfsym->st_value += adjust[value / 24];
+ adjust = opd_adjust[value / 24];
+ if (adjust == -1)
+ elfsym->st_value = 0;
+ else
+ elfsym->st_value += adjust;
return TRUE;
}