Allocate ppc64 got and dynrelocs before plt

The idea being to make undefined weak syms dynamic, before deciding
whether a sym needs a plt entry.  Fixes pr19719 ld testcase.

	* elf64-ppc.c (allocate_dynrelocs): Allocate got and other dynamic
	relocs before plt relocs.
This commit is contained in:
Alan Modra
2016-05-18 23:59:04 +09:30
parent 9f284bf9da
commit 57e7d11848
2 changed files with 148 additions and 142 deletions

View File

@ -1,3 +1,8 @@
2016-05-19 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (allocate_dynrelocs): Allocate got and other dynamic
relocs before plt relocs.
2016-05-19 Alan Modra <amodra@gmail.com> 2016-05-19 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_branch_reloc): Check for NULL owner * elf64-ppc.c (ppc64_elf_branch_reloc): Check for NULL owner

View File

@ -5150,7 +5150,7 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info)
} }
/* We need to fix the undefs list for any syms we have twiddled to /* We need to fix the undefs list for any syms we have twiddled to
undef_weak. */ undefweak. */
if (htab->twiddled_syms) if (htab->twiddled_syms)
{ {
bfd_link_repair_undef_list (&htab->elf.root); bfd_link_repair_undef_list (&htab->elf.root);
@ -9553,71 +9553,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
if (htab == NULL) if (htab == NULL)
return FALSE; return FALSE;
if ((htab->elf.dynamic_sections_created
&& h->dynindx != -1
&& WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
|| h->type == STT_GNU_IFUNC)
{
struct plt_entry *pent;
bfd_boolean doneone = FALSE;
for (pent = h->plt.plist; pent != NULL; pent = pent->next)
if (pent->plt.refcount > 0)
{
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
{
s = htab->elf.iplt;
pent->plt.offset = s->size;
s->size += PLT_ENTRY_SIZE (htab);
s = htab->elf.irelplt;
}
else
{
/* If this is the first .plt entry, make room for the special
first entry. */
s = htab->elf.splt;
if (s->size == 0)
s->size += PLT_INITIAL_ENTRY_SIZE (htab);
pent->plt.offset = s->size;
/* Make room for this entry. */
s->size += PLT_ENTRY_SIZE (htab);
/* Make room for the .glink code. */
s = htab->glink;
if (s->size == 0)
s->size += GLINK_CALL_STUB_SIZE;
if (htab->opd_abi)
{
/* We need bigger stubs past index 32767. */
if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
s->size += 4;
s->size += 2*4;
}
else
s->size += 4;
/* We also need to make an entry in the .rela.plt section. */
s = htab->elf.srelplt;
}
s->size += sizeof (Elf64_External_Rela);
doneone = TRUE;
}
else
pent->plt.offset = (bfd_vma) -1;
if (!doneone)
{
h->plt.plist = NULL;
h->needs_plt = 0;
}
}
else
{
h->plt.plist = NULL;
h->needs_plt = 0;
}
eh = (struct ppc_link_hash_entry *) h; eh = (struct ppc_link_hash_entry *) h;
/* Run through the TLS GD got entries first if we're changing them /* Run through the TLS GD got entries first if we're changing them
to TPREL. */ to TPREL. */
@ -9687,25 +9622,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
allocate_got (h, info, gent); allocate_got (h, info, gent);
} }
if (eh->dyn_relocs == NULL if (eh->dyn_relocs != NULL
|| (!htab->elf.dynamic_sections_created && (htab->elf.dynamic_sections_created
&& h->type != STT_GNU_IFUNC)) || h->type == STT_GNU_IFUNC))
return TRUE; {
/* In the shared -Bsymbolic case, discard space allocated for /* In the shared -Bsymbolic case, discard space allocated for
dynamic pc-relative relocs against symbols which turn out to be dynamic pc-relative relocs against symbols which turn out to
defined in regular objects. For the normal shared case, discard be defined in regular objects. For the normal shared case,
space for relocs that have become local due to symbol visibility discard space for relocs that have become local due to symbol
changes. */ visibility changes. */
if (bfd_link_pic (info)) if (bfd_link_pic (info))
{ {
/* Relocs that use pc_count are those that appear on a call insn, /* Relocs that use pc_count are those that appear on a call
or certain REL relocs (see must_be_dyn_reloc) that can be insn, or certain REL relocs (see must_be_dyn_reloc) that
generated via assembly. We want calls to protected symbols to can be generated via assembly. We want calls to
resolve directly to the function rather than going via the plt. protected symbols to resolve directly to the function
If people want function pointer comparisons to work as expected rather than going via the plt. If people want function
then they should avoid writing weird assembly. */ pointer comparisons to work as expected then they should
avoid writing weird assembly. */
if (SYMBOL_CALLS_LOCAL (info, h)) if (SYMBOL_CALLS_LOCAL (info, h))
{ {
struct elf_dyn_relocs **pp; struct elf_dyn_relocs **pp;
@ -9721,8 +9656,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
} }
} }
/* Also discard relocs on undefined weak syms with non-default /* Also discard relocs on undefined weak syms with
visibility. */ non-default visibility. */
if (eh->dyn_relocs != NULL if (eh->dyn_relocs != NULL
&& h->root.type == bfd_link_hash_undefweak) && h->root.type == bfd_link_hash_undefweak)
{ {
@ -9781,6 +9716,72 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
sreloc = htab->elf.irelplt; sreloc = htab->elf.irelplt;
sreloc->size += p->count * sizeof (Elf64_External_Rela); sreloc->size += p->count * sizeof (Elf64_External_Rela);
} }
}
if ((htab->elf.dynamic_sections_created
&& h->dynindx != -1
&& WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
|| h->type == STT_GNU_IFUNC)
{
struct plt_entry *pent;
bfd_boolean doneone = FALSE;
for (pent = h->plt.plist; pent != NULL; pent = pent->next)
if (pent->plt.refcount > 0)
{
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
{
s = htab->elf.iplt;
pent->plt.offset = s->size;
s->size += PLT_ENTRY_SIZE (htab);
s = htab->elf.irelplt;
}
else
{
/* If this is the first .plt entry, make room for the special
first entry. */
s = htab->elf.splt;
if (s->size == 0)
s->size += PLT_INITIAL_ENTRY_SIZE (htab);
pent->plt.offset = s->size;
/* Make room for this entry. */
s->size += PLT_ENTRY_SIZE (htab);
/* Make room for the .glink code. */
s = htab->glink;
if (s->size == 0)
s->size += GLINK_CALL_STUB_SIZE;
if (htab->opd_abi)
{
/* We need bigger stubs past index 32767. */
if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
s->size += 4;
s->size += 2*4;
}
else
s->size += 4;
/* We also need to make an entry in the .rela.plt section. */
s = htab->elf.srelplt;
}
s->size += sizeof (Elf64_External_Rela);
doneone = TRUE;
}
else
pent->plt.offset = (bfd_vma) -1;
if (!doneone)
{
h->plt.plist = NULL;
h->needs_plt = 0;
}
}
else
{
h->plt.plist = NULL;
h->needs_plt = 0;
}
return TRUE; return TRUE;
} }