Don't move weak alias dyn_relocs to weakdef

I did this for powerpc64 a while ago.  Not moving weak symbol
dyn_relocs to the strong alias makes for a much simpler test for
dynamic relocs in relocate_section.

This patch implements the change for powerpc and hppa.  Other targets
could benefit from similar changes.

	* elf32-hppa.c (pc_dynrelocs): Define.
	(elf32_hppa_copy_indirect_symbol): Don't copy dyn_relocs to weakdefs.
	(alias_readonly_dynrelocs): New function.
	(elf32_hppa_adjust_dynamic_symbol): Don't clear non_got_ref to
	indicate dyn_relocs should be discarded, discard them here.
	Use alias_readonly_dynrelocs.
	(allocate_dynrelocs): Don't test or clear non_got_ref.
	(elf32_hppa_relocate_section): Simplify test for dynamic relocs.
	* elf32-ppc.c (ppc_elf_copy_indirect_symbol): Don't copy dyn_relocs
	to weakdefs.
	(alias_readonly_dynrelocs, pc_dynrelocs): New functions.
	(ppc_elf_adjust_dynamic_symbol): Don't clear non_got_ref to
	indicate dyn_relocs should be discarded, discard them here.
	Use alias_readonly_dynrelocs.
	(allocate_dynrelocs): Don't test or clear non_got_ref.
	(ppc_elf_relocate_section): Simplify test for dynamic relocs.
This commit is contained in:
Alan Modra 2017-11-22 21:07:03 +10:30
parent ab2477e15c
commit 287c7eaf0d
3 changed files with 113 additions and 109 deletions

View File

@ -1,3 +1,22 @@
2017-11-23 Alan Modra <amodra@gmail.com>
* elf32-hppa.c (pc_dynrelocs): Define.
(elf32_hppa_copy_indirect_symbol): Don't copy dyn_relocs to weakdefs.
(alias_readonly_dynrelocs): New function.
(elf32_hppa_adjust_dynamic_symbol): Don't clear non_got_ref to
indicate dyn_relocs should be discarded, discard them here.
Use alias_readonly_dynrelocs.
(allocate_dynrelocs): Don't test or clear non_got_ref.
(elf32_hppa_relocate_section): Simplify test for dynamic relocs.
* elf32-ppc.c (ppc_elf_copy_indirect_symbol): Don't copy dyn_relocs
to weakdefs.
(alias_readonly_dynrelocs, pc_dynrelocs): New functions.
(ppc_elf_adjust_dynamic_symbol): Don't clear non_got_ref to
indicate dyn_relocs should be discarded, discard them here.
Use alias_readonly_dynrelocs.
(allocate_dynrelocs): Don't test or clear non_got_ref.
(ppc_elf_relocate_section): Simplify test for dynamic relocs.
2017-11-23 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (struct ppc_link_hash_entry): Delete weakref field.

View File

@ -162,6 +162,7 @@ static const bfd_byte plt_stub[] =
#ifndef RELATIVE_DYNRELOCS
#define RELATIVE_DYNRELOCS 0
#define IS_ABSOLUTE_RELOC(r_type) 1
#define pc_dynrelocs(hh) 0
#endif
/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
@ -1020,7 +1021,8 @@ elf32_hppa_copy_indirect_symbol (struct bfd_link_info *info,
hh_dir = hppa_elf_hash_entry (eh_dir);
hh_ind = hppa_elf_hash_entry (eh_ind);
if (hh_ind->dyn_relocs != NULL)
if (hh_ind->dyn_relocs != NULL
&& eh_ind->root.type == bfd_link_hash_indirect)
{
if (hh_dir->dyn_relocs != NULL)
{
@ -1674,6 +1676,24 @@ readonly_dynrelocs (struct elf_link_hash_entry *eh)
return NULL;
}
/* Return true if we have dynamic relocs against H or any of its weak
aliases, that apply to read-only sections. Cannot be used after
size_dynamic_sections. */
static bfd_boolean
alias_readonly_dynrelocs (struct elf_link_hash_entry *eh)
{
struct elf32_hppa_link_hash_entry *hh = hppa_elf_hash_entry (eh);
do
{
if (readonly_dynrelocs (&hh->eh))
return TRUE;
hh = hppa_elf_hash_entry (hh->eh.u.alias);
} while (hh != NULL && &hh->eh != eh);
return FALSE;
}
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
@ -1692,23 +1712,12 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
if (eh->type == STT_FUNC
|| eh->needs_plt)
{
/* Prior to adjust_dynamic_symbol, non_got_ref set means that
check_relocs generated dyn_relocs for this symbol.
After adjust_dynamic_symbol, non_got_ref clear in the non-pic
case means that dyn_relocs for this symbol should be
discarded; We either want the symbol to remain undefined, or
we have a local definition of some sort. The "local
definition" for non-function symbols may be due to creating a
local definition in .dynbss.
Unlike other targets, elf32-hppa.c does not define a function
symbol in a non-pic executable on PLT stub code, so we don't
have a local definition in that case. */
bfd_boolean local = (SYMBOL_CALLS_LOCAL (info, eh)
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh));
/* Arrange to discard dyn_relocs if we've decided that a
/* Discard dyn_relocs when non-pic if we've decided that a
function symbol is local. */
if (local)
eh->non_got_ref = 0;
if (!bfd_link_pic (info) && local)
hppa_elf_hash_entry (eh)->dyn_relocs = NULL;
/* If the symbol is used by a plabel, we must allocate a PLT slot.
The refcounts are not reliable when it has been hidden since
@ -1732,6 +1741,11 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
eh->needs_plt = 0;
}
/* Unlike other targets, elf32-hppa.c does not define a function
symbol in a non-pic executable on PLT stub code, so we don't
have a local definition in that case. ie. dyn_relocs can't
be discarded. */
/* Function symbols can't have copy relocs. */
return TRUE;
}
@ -1772,7 +1786,7 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
return TRUE;
if (ELIMINATE_COPY_RELOCS
&& !readonly_dynrelocs (eh))
&& !alias_readonly_dynrelocs (eh))
{
/* If we didn't find any dynamic relocs in read-only sections, then
we'll be keeping the dynamic relocs and avoiding the copy reloc. */
@ -1813,7 +1827,7 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
}
/* We no longer want dyn_relocs. */
eh->non_got_ref = 0;
hppa_elf_hash_entry (eh)->dyn_relocs = NULL;
return _bfd_elf_adjust_dynamic_copy (info, eh, sec);
}
@ -2005,10 +2019,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
hh->dyn_relocs = NULL;
if (hh->dyn_relocs == NULL)
{
eh->non_got_ref = 0;
return TRUE;
}
return TRUE;
/* If this is a -Bsymbolic shared link, then we need to discard all
space allocated for dynamic pc-relative relocs against symbols
@ -2047,7 +2058,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
dynamic. */
if (eh->dynamic_adjusted
&& eh->non_got_ref
&& !eh->def_regular
&& !ELF_COMMON_DEF_P (eh))
{
@ -2055,16 +2065,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
return FALSE;
if (eh->dynindx == -1)
{
eh->non_got_ref = 0;
hh->dyn_relocs = NULL;
}
hh->dyn_relocs = NULL;
}
else
{
eh->non_got_ref = 0;
hh->dyn_relocs = NULL;
}
hh->dyn_relocs = NULL;
}
/* Finally, allocate space. */
@ -3895,23 +3899,13 @@ elf32_hppa_relocate_section (bfd *output_bfd,
if ((input_section->flags & SEC_ALLOC) == 0)
break;
/* The reloc types handled here and this conditional
expression must match the code in ..check_relocs and
allocate_dynrelocs. ie. We need exactly the same condition
as in ..check_relocs, with some extra conditions (dynindx
test in this case) to cater for relocs removed by
allocate_dynrelocs. */
if ((bfd_link_pic (info)
&& !(hh != NULL
&& ((hh->eh.root.type == bfd_link_hash_undefined
&& ELF_ST_VISIBILITY (hh->eh.other) != STV_DEFAULT)
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, &hh->eh)))
&& (IS_ABSOLUTE_RELOC (r_type)
|| !SYMBOL_CALLS_LOCAL (info, &hh->eh)))
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& hh != NULL
&& hh->eh.non_got_ref))
if (bfd_link_pic (info)
? ((hh == NULL
|| hh->dyn_relocs != NULL)
&& ((hh != NULL && pc_dynrelocs (hh))
|| IS_ABSOLUTE_RELOC (r_type)))
: (hh != NULL
&& hh->dyn_relocs != NULL))
{
Elf_Internal_Rela outrel;
bfd_boolean skip;

View File

@ -3594,6 +3594,10 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info,
edir->elf.needs_plt |= eind->elf.needs_plt;
edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
/* If we were called to copy over info for a weak sym, that's all. */
if (eind->elf.root.type != bfd_link_hash_indirect)
return;
if (eind->dyn_relocs != NULL)
{
if (edir->dyn_relocs != NULL)
@ -3625,16 +3629,6 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info,
eind->dyn_relocs = NULL;
}
/* If we were called to copy over info for a weak sym, that's all.
You might think dyn_relocs need not be copied over; After all,
both syms will be dynamic or both non-dynamic so we're just
moving reloc accounting around. However, ELIMINATE_COPY_RELOCS
code in ppc_elf_adjust_dynamic_symbol needs to check for
dyn_relocs in read-only sections, and it does so on what is the
DIR sym here. */
if (eind->elf.root.type != bfd_link_hash_indirect)
return;
/* Copy over the GOT refcount entries that we may have already seen to
the symbol which just became indirect. */
edir->elf.got.refcount += eind->elf.got.refcount;
@ -5441,6 +5435,37 @@ readonly_dynrelocs (struct elf_link_hash_entry *h)
return NULL;
}
/* Return true if we have dynamic relocs against H or any of its weak
aliases, that apply to read-only sections. Cannot be used after
size_dynamic_sections. */
static bfd_boolean
alias_readonly_dynrelocs (struct elf_link_hash_entry *h)
{
struct ppc_elf_link_hash_entry *eh = ppc_elf_hash_entry (h);
do
{
if (readonly_dynrelocs (&eh->elf))
return TRUE;
eh = ppc_elf_hash_entry (eh->elf.u.alias);
} while (eh != NULL && &eh->elf != h);
return FALSE;
}
/* Return whether H has pc-relative dynamic relocs. */
static bfd_boolean
pc_dynrelocs (struct elf_link_hash_entry *h)
{
struct elf_dyn_relocs *p;
for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
if (p->pc_count != 0)
return TRUE;
return FALSE;
}
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
@ -5474,35 +5499,12 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|| h->type == STT_GNU_IFUNC
|| h->needs_plt)
{
/* Prior to adjust_dynamic_symbol, non_got_ref set means that
we might need to generate a copy reloc for this symbol.
After adjust_dynamic_symbol, non_got_ref is only relevant for
non-pic and means that the symbol might have dynamic
relocations. If it is clear then dyn_relocs for this symbol
should be discarded; We either want the symbol to remain
undefined, or we have a local definition of some sort. The
"local definition" for non-function symbols may be due to
creating a local definition in .dynbss, and for function
symbols, defining the symbol on the PLT call stub code. */
bfd_boolean local = (SYMBOL_CALLS_LOCAL (info, h)
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
/* Arrange to discard dyn_relocs if we've decided that a
function symbol is local. It might be possible to discard
dyn_relocs here, but when a symbol has a weakdef they have
been transferred to the weakdef symbol for the benefit of
readonly_dynrelocs. (See ppc_elf_copy_indirect_symbol.)
Not only would we need to handle weakdefs here, but also in
allocate_dynrelocs and relocate_section. The latter is
impossible since the weakdef field has been overwritten by
that time. In relocate_section we need a proxy for
dyn_relocs and non_got_ref is that proxy.
Note that function symbols are not supposed to have weakdefs,
but since symbols may not be correctly typed we handle them
here. */
h->non_got_ref = (h->is_weakalias
? weakdef (h)->non_got_ref
: !local && (((struct ppc_elf_link_hash_entry *) h)
->dyn_relocs != NULL));
/* Discard dyn_relocs when non-pic if we've decided that a
function symbol is local. */
if (!bfd_link_pic (info) && local)
ppc_elf_hash_entry (h)->dyn_relocs = NULL;
/* Clear procedure linkage table information for any symbol that
won't need a .plt entry. */
@ -5552,10 +5554,10 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
if (!h->needs_plt)
h->plt.plist = NULL;
}
else
else if (!bfd_link_pic (info))
/* We are going to be defining the function symbol on the
plt stub, so no dyn_relocs needed when non-pic. */
h->non_got_ref = 0;
ppc_elf_hash_entry (h)->dyn_relocs = NULL;
}
h->protected_def = 0;
/* Function symbols can't have copy relocs. */
@ -5628,7 +5630,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
&& !ppc_elf_hash_entry (h)->has_sda_refs
&& !htab->is_vxworks
&& !h->def_regular
&& !readonly_dynrelocs (h))
&& !alias_readonly_dynrelocs (h))
return TRUE;
/* We must allocate the symbol in our .dynbss section, which will
@ -5672,7 +5674,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
}
/* We no longer want dyn_relocs. */
h->non_got_ref = 0;
ppc_elf_hash_entry (h)->dyn_relocs = NULL;
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@ -5912,7 +5914,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
eh->dyn_relocs = NULL;
if (eh->dyn_relocs == NULL)
h->non_got_ref = 0;
;
/* In the shared -Bsymbolic case, discard space allocated for
dynamic pc-relative relocs against symbols which turn out to be
@ -5968,7 +5970,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
symbols which turn out to need copy relocs or are not
dynamic. */
if (h->dynamic_adjusted
&& h->non_got_ref
&& !h->def_regular
&& !ELF_COMMON_DEF_P (h)
&& !(h->protected_def
@ -5981,16 +5982,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
return FALSE;
if (h->dynindx == -1)
{
h->non_got_ref = 0;
eh->dyn_relocs = NULL;
}
eh->dyn_relocs = NULL;
}
else
{
h->non_got_ref = 0;
eh->dyn_relocs = NULL;
}
eh->dyn_relocs = NULL;
}
/* Allocate space. */
@ -8756,17 +8751,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
|| is_vxworks_tls)
break;
if ((bfd_link_pic (info)
&& !(h != NULL
&& ((h->root.type == bfd_link_hash_undefined
&& ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
&& (must_be_dyn_reloc (info, r_type)
|| !SYMBOL_CALLS_LOCAL (info, h)))
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& h != NULL
&& h->non_got_ref))
if (bfd_link_pic (info)
? ((h == NULL
|| ppc_elf_hash_entry (h)->dyn_relocs != NULL)
&& ((h != NULL && pc_dynrelocs (h))
|| must_be_dyn_reloc (info, r_type)))
: (h != NULL
&& ppc_elf_hash_entry (h)->dyn_relocs != NULL))
{
int skip;
bfd_byte *loc;