* elf32-ppc.c (struct ppc_dyn_relocs): New.

(ppc_elf_check_relocs): Separate dynrel counts for local syms
	into ifunc and non-ifunc.
	(allocate_dynrelocs): Always put ifunc relocs into reliplt.
	(ppc_elf_size_dynamic_sections): Likewise.
	(ppc_elf_relocate_section): Likewise.
This commit is contained in:
Alan Modra
2013-03-28 07:07:25 +00:00
parent 3afd2652d4
commit f95f8542c5
2 changed files with 73 additions and 34 deletions

View File

@ -1,3 +1,12 @@
2013-03-28 Alan Modra <amodra@gmail.com>
* elf32-ppc.c (struct ppc_dyn_relocs): New.
(ppc_elf_check_relocs): Separate dynrel counts for local syms
into ifunc and non-ifunc.
(allocate_dynrelocs): Always put ifunc relocs into reliplt.
(ppc_elf_size_dynamic_sections): Likewise.
(ppc_elf_relocate_section): Likewise.
2013-03-28 Alan Modra <amodra@gmail.com> 2013-03-28 Alan Modra <amodra@gmail.com>
* elf-bfd.h (enum elf_reloc_type_class): Add reloc_class_ifunc. * elf-bfd.h (enum elf_reloc_type_class): Add reloc_class_ifunc.

View File

@ -3083,6 +3083,21 @@ must_be_dyn_reloc (struct bfd_link_info *info,
shared lib. */ shared lib. */
#define ELIMINATE_COPY_RELOCS 1 #define ELIMINATE_COPY_RELOCS 1
/* Used to track dynamic relocations for local symbols. */
struct ppc_dyn_relocs
{
struct ppc_dyn_relocs *next;
/* The input section of the reloc. */
asection *sec;
/* Total number of relocs copied for the input section. */
unsigned int count : 31;
/* Whether this entry is for STT_GNU_IFUNC symbols. */
unsigned int ifunc : 1;
};
/* PPC ELF linker hash entry. */ /* PPC ELF linker hash entry. */
struct ppc_elf_link_hash_entry struct ppc_elf_link_hash_entry
@ -4414,9 +4429,6 @@ ppc_elf_check_relocs (bfd *abfd,
&& (h->root.type == bfd_link_hash_defweak && (h->root.type == bfd_link_hash_defweak
|| !h->def_regular))) || !h->def_regular)))
{ {
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **rel_head;
#ifdef DEBUG #ifdef DEBUG
fprintf (stderr, fprintf (stderr,
"ppc_elf_check_relocs needs to " "ppc_elf_check_relocs needs to "
@ -4440,13 +4452,34 @@ ppc_elf_check_relocs (bfd *abfd,
relocations we need for this symbol. */ relocations we need for this symbol. */
if (h != NULL) if (h != NULL)
{ {
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **rel_head;
rel_head = &ppc_elf_hash_entry (h)->dyn_relocs; rel_head = &ppc_elf_hash_entry (h)->dyn_relocs;
p = *rel_head;
if (p == NULL || p->sec != sec)
{
p = bfd_alloc (htab->elf.dynobj, sizeof *p);
if (p == NULL)
return FALSE;
p->next = *rel_head;
*rel_head = p;
p->sec = sec;
p->count = 0;
p->pc_count = 0;
}
p->count += 1;
if (!must_be_dyn_reloc (info, r_type))
p->pc_count += 1;
} }
else else
{ {
/* Track dynamic relocs needed for local syms too. /* Track dynamic relocs needed for local syms too.
We really need local syms available to do this We really need local syms available to do this
easily. Oh well. */ easily. Oh well. */
struct ppc_dyn_relocs *p;
struct ppc_dyn_relocs **rel_head;
bfd_boolean is_ifunc;
asection *s; asection *s;
void *vpp; void *vpp;
Elf_Internal_Sym *isym; Elf_Internal_Sym *isym;
@ -4461,25 +4494,24 @@ ppc_elf_check_relocs (bfd *abfd,
s = sec; s = sec;
vpp = &elf_section_data (s)->local_dynrel; vpp = &elf_section_data (s)->local_dynrel;
rel_head = (struct elf_dyn_relocs **) vpp; rel_head = (struct ppc_dyn_relocs **) vpp;
is_ifunc = ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC;
p = *rel_head;
if (p != NULL && p->sec == sec && p->ifunc != is_ifunc)
p = p->next;
if (p == NULL || p->sec != sec || p->ifunc != is_ifunc)
{
p = bfd_alloc (htab->elf.dynobj, sizeof *p);
if (p == NULL)
return FALSE;
p->next = *rel_head;
*rel_head = p;
p->sec = sec;
p->ifunc = is_ifunc;
p->count = 0;
}
p->count += 1;
} }
p = *rel_head;
if (p == NULL || p->sec != sec)
{
p = bfd_alloc (htab->elf.dynobj, sizeof *p);
if (p == NULL)
return FALSE;
p->next = *rel_head;
*rel_head = p;
p->sec = sec;
p->count = 0;
p->pc_count = 0;
}
p->count += 1;
if (!must_be_dyn_reloc (info, r_type))
p->pc_count += 1;
} }
break; break;
@ -6023,7 +6055,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
for (p = eh->dyn_relocs; p != NULL; p = p->next) for (p = eh->dyn_relocs; p != NULL; p = p->next)
{ {
asection *sreloc = elf_section_data (p->sec)->sreloc; asection *sreloc = elf_section_data (p->sec)->sreloc;
if (!htab->elf.dynamic_sections_created) if (eh->elf.type == STT_GNU_IFUNC)
sreloc = htab->reliplt; sreloc = htab->reliplt;
sreloc->size += p->count * sizeof (Elf32_External_Rela); sreloc->size += p->count * sizeof (Elf32_External_Rela);
} }
@ -6116,9 +6148,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
for (s = ibfd->sections; s != NULL; s = s->next) for (s = ibfd->sections; s != NULL; s = s->next)
{ {
struct elf_dyn_relocs *p; struct ppc_dyn_relocs *p;
for (p = ((struct elf_dyn_relocs *) for (p = ((struct ppc_dyn_relocs *)
elf_section_data (s)->local_dynrel); elf_section_data (s)->local_dynrel);
p != NULL; p != NULL;
p = p->next) p = p->next)
@ -6141,7 +6173,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
else if (p->count != 0) else if (p->count != 0)
{ {
asection *sreloc = elf_section_data (p->sec)->sreloc; asection *sreloc = elf_section_data (p->sec)->sreloc;
if (!htab->elf.dynamic_sections_created) if (p->ifunc)
sreloc = htab->reliplt; sreloc = htab->reliplt;
sreloc->size += p->count * sizeof (Elf32_External_Rela); sreloc->size += p->count * sizeof (Elf32_External_Rela);
if ((p->sec->output_section->flags if ((p->sec->output_section->flags
@ -7390,7 +7422,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
Elf_Internal_Rela *rel; Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend; Elf_Internal_Rela *relend;
Elf_Internal_Rela outrel; Elf_Internal_Rela outrel;
asection *got2, *sreloc = NULL; asection *got2;
bfd_vma *local_got_offsets; bfd_vma *local_got_offsets;
bfd_boolean ret = TRUE; bfd_boolean ret = TRUE;
bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0); bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0);
@ -8244,7 +8276,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
&& !h->def_regular)) && !h->def_regular))
{ {
int skip; int skip;
bfd_byte * loc; bfd_byte *loc;
asection *sreloc;
#ifdef DEBUG #ifdef DEBUG
fprintf (stderr, "ppc_elf_relocate_section needs to " fprintf (stderr, "ppc_elf_relocate_section needs to "
"create relocation for %s\n", "create relocation for %s\n",
@ -8255,14 +8288,11 @@ ppc_elf_relocate_section (bfd *output_bfd,
/* When generating a shared object, these relocations /* When generating a shared object, these relocations
are copied into the output file to be resolved at run are copied into the output file to be resolved at run
time. */ time. */
sreloc = elf_section_data (input_section)->sreloc;
if (ifunc)
sreloc = htab->reliplt;
if (sreloc == NULL) if (sreloc == NULL)
{ return FALSE;
sreloc = elf_section_data (input_section)->sreloc;
if (!htab->elf.dynamic_sections_created)
sreloc = htab->reliplt;
if (sreloc == NULL)
return FALSE;
}
skip = 0; skip = 0;
outrel.r_offset = _bfd_elf_section_offset (output_bfd, info, outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,