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:
parent
ab2477e15c
commit
287c7eaf0d
@ -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.
|
||||
|
@ -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;
|
||||
|
115
bfd/elf32-ppc.c
115
bfd/elf32-ppc.c
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user