* 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.
This commit is contained in:
Alan Modra 2004-08-09 00:22:53 +00:00
parent ead80d2530
commit 4025353c27
2 changed files with 68 additions and 36 deletions

View File

@ -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> 2004-08-06 Paul Brook <paul@codesourcery.com>
* elfarm-nabi.c (elf32_arm_howto_table): Add new EABI relocations. * elfarm-nabi.c (elf32_arm_howto_table): Add new EABI relocations.

View File

@ -2492,6 +2492,16 @@ ppc64_elf_new_section_hook (bfd *abfd, asection *sec)
return _bfd_elf_new_section_hook (abfd, 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 /* The following functions are specific to the ELF linker, while
functions above are used generally. Those named ppc64_elf_* are 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; return TRUE;
sym_sec = eh->elf.root.u.def.section; sym_sec = eh->elf.root.u.def.section;
if (sym_sec != NULL opd_adjust = get_opd_info (sym_sec);
&& elf_section_data (sym_sec) != NULL if (opd_adjust != NULL)
&& (opd_adjust = ppc64_elf_section_data (sym_sec)->opd.adjust) != NULL)
{ {
eh->elf.root.u.def.value += opd_adjust[eh->elf.root.u.def.value / 24]; 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; eh->adjust_done = 1;
} }
return TRUE; return TRUE;
@ -4966,7 +4984,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info)
struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **sym_hashes;
bfd_vma offset; bfd_vma offset;
bfd_size_type amt; bfd_size_type amt;
long *adjust; long *opd_adjust;
bfd_boolean need_edit; bfd_boolean need_edit;
sec = bfd_get_section_by_name (ibfd, ".opd"); sec = bfd_get_section_by_name (ibfd, ".opd");
@ -4974,15 +4992,15 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info)
continue; continue;
amt = sec->size * sizeof (long) / 24; amt = sec->size * sizeof (long) / 24;
adjust = ppc64_elf_section_data (sec)->opd.adjust; opd_adjust = get_opd_info (sec);
if (adjust == NULL) if (opd_adjust == NULL)
{ {
/* Must be a ld -r link. ie. check_relocs hasn't been /* Must be a ld -r link. ie. check_relocs hasn't been
called. */ called. */
adjust = bfd_zalloc (obfd, amt); opd_adjust = bfd_zalloc (obfd, amt);
ppc64_elf_section_data (sec)->opd.adjust = adjust; 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) if (sec->output_section == bfd_abs_section_ptr)
continue; continue;
@ -5134,7 +5152,8 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info)
if (rel->r_offset == offset) if (rel->r_offset == offset)
{ {
struct ppc_link_hash_entry *fdh = NULL; 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, fdh = get_fdh ((struct ppc_link_hash_entry *) h,
ppc_hash_table (info)); 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); || sym_sec->output_section == bfd_abs_section_ptr);
if (skip) if (skip)
{ {
if (h != NULL && sym_sec->owner == ibfd) if (fdh != NULL && sym_sec->owner == ibfd)
{ {
/* Arrange for the function descriptor sym /* Arrange for the function descriptor sym
to be dropped. */ to be dropped. */
fdh->elf.root.u.def.value = 0; fdh->elf.root.u.def.value = 0;
fdh->elf.root.u.def.section = sym_sec; fdh->elf.root.u.def.section = sym_sec;
} }
opd_adjust[rel->r_offset / 24] = -1;
} }
else else
{ {
/* We'll be keeping this opd entry. */ /* We'll be keeping this opd entry. */
if (h != NULL) if (fdh != NULL)
{ {
/* Redefine the function descriptor symbol to /* Redefine the function descriptor symbol to
this location in the opd section. It is 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 for the function descriptor sym which we
don't have at the moment. So keep an don't have at the moment. So keep an
array of adjustments. */ array of adjustments. */
adjust[rel->r_offset / 24] = wptr - rptr; opd_adjust[rel->r_offset / 24] = wptr - rptr;
if (wptr != rptr) if (wptr != rptr)
memcpy (wptr, rptr, 24); 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; value = h->root.u.def.value;
} }
else else
{ /* Symbols referenced by TLS relocs must be of type
value = sym->st_value; STT_TLS. So no need for .opd local sym adjust. */
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];
}
}
ok_tprel = FALSE; ok_tprel = FALSE;
is_local = FALSE; is_local = FALSE;
@ -7455,18 +7467,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
if (r_symndx < symtab_hdr->sh_info) if (r_symndx < symtab_hdr->sh_info)
{ {
/* It's a local symbol. */ /* It's a local symbol. */
long *opd_adjust;
sym = local_syms + r_symndx; sym = local_syms + r_symndx;
sec = local_sections[r_symndx]; sec = local_sections[r_symndx];
sym_name = bfd_elf_local_sym_name (input_bfd, sym); sym_name = bfd_elf_local_sym_name (input_bfd, sym);
sym_type = ELF64_ST_TYPE (sym->st_info); sym_type = ELF64_ST_TYPE (sym->st_info);
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 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; long adjust = opd_adjust[(sym->st_value + rel->r_addend) / 24];
if (adjust == -1)
opd_sym_adjust = ppc64_elf_section_data (sec)->opd.adjust; relocation = 0;
if (opd_sym_adjust != NULL) else
relocation += opd_sym_adjust[sym->st_value / 24]; relocation += adjust;
} }
} }
else else
@ -8745,20 +8760,25 @@ ppc64_elf_output_symbol_hook (struct bfd_link_info *info,
asection *input_sec, asection *input_sec,
struct elf_link_hash_entry *h) struct elf_link_hash_entry *h)
{ {
long *adjust; long *opd_adjust, adjust;
bfd_vma value; bfd_vma value;
if (h != NULL if (h != NULL)
|| input_sec == NULL return TRUE;
|| ppc64_elf_section_data (input_sec) == NULL
|| (adjust = ppc64_elf_section_data (input_sec)->opd.adjust) == NULL) opd_adjust = get_opd_info (input_sec);
if (opd_adjust == NULL)
return TRUE; return TRUE;
value = elfsym->st_value - input_sec->output_offset; value = elfsym->st_value - input_sec->output_offset;
if (!info->relocatable) if (!info->relocatable)
value -= input_sec->output_section->vma; 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; return TRUE;
} }