mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-22 11:00:01 +08:00
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:
@ -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
|
||||||
|
285
bfd/elf64-ppc.c
285
bfd/elf64-ppc.c
@ -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,99 +9622,165 @@ 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
|
|
||||||
dynamic pc-relative relocs against symbols which turn out to be
|
|
||||||
defined in regular objects. For the normal shared case, discard
|
|
||||||
space for relocs that have become local due to symbol visibility
|
|
||||||
changes. */
|
|
||||||
|
|
||||||
if (bfd_link_pic (info))
|
|
||||||
{
|
{
|
||||||
/* Relocs that use pc_count are those that appear on a call insn,
|
/* In the shared -Bsymbolic case, discard space allocated for
|
||||||
or certain REL relocs (see must_be_dyn_reloc) that can be
|
dynamic pc-relative relocs against symbols which turn out to
|
||||||
generated via assembly. We want calls to protected symbols to
|
be defined in regular objects. For the normal shared case,
|
||||||
resolve directly to the function rather than going via the plt.
|
discard space for relocs that have become local due to symbol
|
||||||
If people want function pointer comparisons to work as expected
|
visibility changes. */
|
||||||
then they should avoid writing weird assembly. */
|
|
||||||
if (SYMBOL_CALLS_LOCAL (info, h))
|
|
||||||
{
|
|
||||||
struct elf_dyn_relocs **pp;
|
|
||||||
|
|
||||||
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
|
if (bfd_link_pic (info))
|
||||||
|
{
|
||||||
|
/* Relocs that use pc_count are those that appear on a call
|
||||||
|
insn, or certain REL relocs (see must_be_dyn_reloc) that
|
||||||
|
can be generated via assembly. We want calls to
|
||||||
|
protected symbols to resolve directly to the function
|
||||||
|
rather than going via the plt. If people want function
|
||||||
|
pointer comparisons to work as expected then they should
|
||||||
|
avoid writing weird assembly. */
|
||||||
|
if (SYMBOL_CALLS_LOCAL (info, h))
|
||||||
{
|
{
|
||||||
p->count -= p->pc_count;
|
struct elf_dyn_relocs **pp;
|
||||||
p->pc_count = 0;
|
|
||||||
if (p->count == 0)
|
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
|
||||||
*pp = p->next;
|
{
|
||||||
else
|
p->count -= p->pc_count;
|
||||||
pp = &p->next;
|
p->pc_count = 0;
|
||||||
|
if (p->count == 0)
|
||||||
|
*pp = p->next;
|
||||||
|
else
|
||||||
|
pp = &p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Also discard relocs on undefined weak syms with
|
||||||
|
non-default visibility. */
|
||||||
|
if (eh->dyn_relocs != NULL
|
||||||
|
&& h->root.type == bfd_link_hash_undefweak)
|
||||||
|
{
|
||||||
|
if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
|
||||||
|
eh->dyn_relocs = NULL;
|
||||||
|
|
||||||
|
/* Make sure this symbol is output as a dynamic symbol.
|
||||||
|
Undefined weak syms won't yet be marked as dynamic. */
|
||||||
|
else if (h->dynindx == -1
|
||||||
|
&& !h->forced_local)
|
||||||
|
{
|
||||||
|
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (h->type == STT_GNU_IFUNC)
|
||||||
/* Also discard relocs on undefined weak syms with non-default
|
|
||||||
visibility. */
|
|
||||||
if (eh->dyn_relocs != NULL
|
|
||||||
&& h->root.type == bfd_link_hash_undefweak)
|
|
||||||
{
|
{
|
||||||
if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
|
if (!h->non_got_ref)
|
||||||
eh->dyn_relocs = NULL;
|
eh->dyn_relocs = NULL;
|
||||||
|
|
||||||
/* Make sure this symbol is output as a dynamic symbol.
|
|
||||||
Undefined weak syms won't yet be marked as dynamic. */
|
|
||||||
else if (h->dynindx == -1
|
|
||||||
&& !h->forced_local)
|
|
||||||
{
|
|
||||||
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else if (ELIMINATE_COPY_RELOCS)
|
||||||
else if (h->type == STT_GNU_IFUNC)
|
|
||||||
{
|
|
||||||
if (!h->non_got_ref)
|
|
||||||
eh->dyn_relocs = NULL;
|
|
||||||
}
|
|
||||||
else if (ELIMINATE_COPY_RELOCS)
|
|
||||||
{
|
|
||||||
/* For the non-shared case, discard space for relocs against
|
|
||||||
symbols which turn out to need copy relocs or are not
|
|
||||||
dynamic. */
|
|
||||||
|
|
||||||
if (!h->non_got_ref
|
|
||||||
&& !h->def_regular)
|
|
||||||
{
|
{
|
||||||
/* Make sure this symbol is output as a dynamic symbol.
|
/* For the non-shared case, discard space for relocs against
|
||||||
Undefined weak syms won't yet be marked as dynamic. */
|
symbols which turn out to need copy relocs or are not
|
||||||
if (h->dynindx == -1
|
dynamic. */
|
||||||
&& !h->forced_local)
|
|
||||||
|
if (!h->non_got_ref
|
||||||
|
&& !h->def_regular)
|
||||||
{
|
{
|
||||||
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
/* Make sure this symbol is output as a dynamic symbol.
|
||||||
return FALSE;
|
Undefined weak syms won't yet be marked as dynamic. */
|
||||||
|
if (h->dynindx == -1
|
||||||
|
&& !h->forced_local)
|
||||||
|
{
|
||||||
|
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If that succeeded, we know we'll be keeping all the
|
||||||
|
relocs. */
|
||||||
|
if (h->dynindx != -1)
|
||||||
|
goto keep;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If that succeeded, we know we'll be keeping all the
|
eh->dyn_relocs = NULL;
|
||||||
relocs. */
|
|
||||||
if (h->dynindx != -1)
|
keep: ;
|
||||||
goto keep;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eh->dyn_relocs = NULL;
|
/* Finally, allocate space. */
|
||||||
|
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
||||||
keep: ;
|
{
|
||||||
|
asection *sreloc = elf_section_data (p->sec)->sreloc;
|
||||||
|
if (eh->elf.type == STT_GNU_IFUNC)
|
||||||
|
sreloc = htab->elf.irelplt;
|
||||||
|
sreloc->size += p->count * sizeof (Elf64_External_Rela);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally, allocate space. */
|
if ((htab->elf.dynamic_sections_created
|
||||||
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
&& h->dynindx != -1
|
||||||
|
&& WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
|
||||||
|
|| h->type == STT_GNU_IFUNC)
|
||||||
{
|
{
|
||||||
asection *sreloc = elf_section_data (p->sec)->sreloc;
|
struct plt_entry *pent;
|
||||||
if (eh->elf.type == STT_GNU_IFUNC)
|
bfd_boolean doneone = FALSE;
|
||||||
sreloc = htab->elf.irelplt;
|
for (pent = h->plt.plist; pent != NULL; pent = pent->next)
|
||||||
sreloc->size += p->count * sizeof (Elf64_External_Rela);
|
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;
|
||||||
|
Reference in New Issue
Block a user