* 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>
* 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);
}
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;
}