Skip to content

Commit

Permalink
* elf32-ppc.c (struct ppc_dyn_relocs): New.
Browse files Browse the repository at this point in the history
	(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.
  • Loading branch information
Alan Modra committed Mar 28, 2013
1 parent c5a0780 commit 82e1762
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 34 deletions.
9 changes: 9 additions & 0 deletions bfd/ChangeLog
Original file line number Diff line number Diff line change
@@ -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>

* elf-bfd.h (enum elf_reloc_type_class): Add reloc_class_ifunc.
Expand Down
98 changes: 64 additions & 34 deletions bfd/elf32-ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3083,6 +3083,21 @@ must_be_dyn_reloc (struct bfd_link_info *info,
shared lib. */
#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. */

struct ppc_elf_link_hash_entry
Expand Down Expand Up @@ -4414,9 +4429,6 @@ ppc_elf_check_relocs (bfd *abfd,
&& (h->root.type == bfd_link_hash_defweak
|| !h->def_regular)))
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **rel_head;

#ifdef DEBUG
fprintf (stderr,
"ppc_elf_check_relocs needs to "
Expand All @@ -4440,13 +4452,34 @@ ppc_elf_check_relocs (bfd *abfd,
relocations we need for this symbol. */
if (h != NULL)
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **rel_head;

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
{
/* Track dynamic relocs needed for local syms too.
We really need local syms available to do this
easily. Oh well. */
struct ppc_dyn_relocs *p;
struct ppc_dyn_relocs **rel_head;
bfd_boolean is_ifunc;
asection *s;
void *vpp;
Elf_Internal_Sym *isym;
Expand All @@ -4461,25 +4494,24 @@ ppc_elf_check_relocs (bfd *abfd,
s = sec;

vpp = &elf_section_data (s)->local_dynrel;
rel_head = (struct elf_dyn_relocs **) vpp;
}

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;
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->count += 1;
if (!must_be_dyn_reloc (info, r_type))
p->pc_count += 1;
}

break;
Expand Down Expand Up @@ -6023,7 +6055,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
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->size += p->count * sizeof (Elf32_External_Rela);
}
Expand Down Expand Up @@ -6116,9 +6148,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,

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);
p != NULL;
p = p->next)
Expand All @@ -6141,7 +6173,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
else if (p->count != 0)
{
asection *sreloc = elf_section_data (p->sec)->sreloc;
if (!htab->elf.dynamic_sections_created)
if (p->ifunc)
sreloc = htab->reliplt;
sreloc->size += p->count * sizeof (Elf32_External_Rela);
if ((p->sec->output_section->flags
Expand Down Expand Up @@ -7390,7 +7422,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
Elf_Internal_Rela outrel;
asection *got2, *sreloc = NULL;
asection *got2;
bfd_vma *local_got_offsets;
bfd_boolean ret = TRUE;
bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0);
Expand Down Expand Up @@ -8244,7 +8276,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
&& !h->def_regular))
{
int skip;
bfd_byte * loc;
bfd_byte *loc;
asection *sreloc;
#ifdef DEBUG
fprintf (stderr, "ppc_elf_relocate_section needs to "
"create relocation for %s\n",
Expand All @@ -8255,14 +8288,11 @@ ppc_elf_relocate_section (bfd *output_bfd,
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
time. */
sreloc = elf_section_data (input_section)->sreloc;
if (ifunc)
sreloc = htab->reliplt;
if (sreloc == NULL)
{
sreloc = elf_section_data (input_section)->sreloc;
if (!htab->elf.dynamic_sections_created)
sreloc = htab->reliplt;
if (sreloc == NULL)
return FALSE;
}
return FALSE;

skip = 0;
outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
Expand Down

0 comments on commit 82e1762

Please sign in to comment.