* 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:
parent
ead80d2530
commit
4025353c27
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue