+2017-11-12 Alan Modra <amodra@gmail.com>
+
+ * elf32-hppa.c (elf32_hppa_adjust_dynamic_symbol): Set non_got_ref
+ to keep dyn_relocs, clear to discard. Comment.
+ (allocate_dynrelocs): Always clear non_got_ref when clearing
+ dyn_relocs in non-pic case. Invert non_got_ref test. Also test
+ dynamic_adjusted and ELF_COMMON_DEF_P. Move code deleting
+ dyn_relocs on undefined syms to handle for non-pic too.
+ (elf32_hppa_relocate_section): Simplify test for non-pic dyn relocs.
+ * elf32-ppc.c (ppc_elf_adjust_dynamic_symbol): Set non_got_ref
+ to keep dyn_relocs, clear to discard. Comment.
+ (allocate_dynrelocs): Always clear non_got_ref when clearing
+ dyn_relocs in non-pic case. Invert non_got_ref test. Also test
+ dynamic_adjusted and ELF_COMMON_DEF_P. Move code deleting
+ dyn_relocs on undefined syms to handle for non-pic too.
+ (ppc_elf_relocate_section): Simplify test for non-pic dyn relocs.
+ * elf64-ppc.c (ppc64_elf_adjust_dynamic_symbol): Discard
+ dyn_relocs here. Don't bother setting non_got_ref. Comment.
+ (allocate_dynrelocs): Delete special handling of non-pic ELFv2
+ ifuncs. Move code deleting dyn_relocs on undefined symbols to
+ handle for non-pic too. Don't test non_got_ref. Do test
+ dynamic_adjusted and ELF_COMMON_DEF_P.
+
2017-11-08 Djordje Todorovic <djordje.todorovic@rt-rk.com>
* elf32-mips.c (elf32_mips_grok_psinfo): Extract core->pid.
if (eh->type == STT_FUNC
|| eh->needs_plt)
{
- /* After adjust_dynamic_symbol, non_got_ref set in the non-pic
+ /* 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
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. dyn_relocs therefore
- should not be discarded for function symbols, generally.
- However we should discard dyn_relocs if we've decided that an
- undefined function symbol is local, for example due to
- non-default visibility, or UNDEFWEAK_NO_DYNAMIC_RELOC is
- true for an undefined weak symbol. */
+ have a local definition in that case. */
bfd_boolean local = (SYMBOL_CALLS_LOCAL (info, eh)
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh));
- /* Prior to adjust_dynamic_symbol, non_got_ref set means that
- check_relocs set up some dyn_relocs for this symbol.
- The !non_got_ref term here is saying that if we didn't have
- any dyn_relocs set up by check_relocs, then we don't want
- relocate_section looking for them.
- FIXME: Get rid of the inversion, so non_got_ref set after
- dyn_relocs means we do have dyn_relocs. */
- eh->non_got_ref = local || !eh->non_got_ref;
+ /* Arrange to discard dyn_relocs if we've decided that a
+ function symbol is local. */
+ if (local)
+ eh->non_got_ref = 0;
/* 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
/* If there are no references to this symbol that do not use the
GOT, we don't need to generate a copy reloc. */
if (!eh->non_got_ref)
- {
- eh->non_got_ref = 1;
- return TRUE;
- }
+ return TRUE;
/* If -z nocopyreloc was given, we won't generate them either. */
if (info->nocopyreloc)
- {
- eh->non_got_ref = 0;
- return TRUE;
- }
+ return TRUE;
if (ELIMINATE_COPY_RELOCS
&& !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. */
- eh->non_got_ref = 0;
return TRUE;
}
eh->needs_copy = 1;
}
+ /* We no longer want dyn_relocs. */
+ eh->non_got_ref = 0;
return _bfd_elf_adjust_dynamic_copy (info, eh, sec);
}
if (!htab->etab.dynamic_sections_created)
hh->dyn_relocs = NULL;
+ /* Discard relocs on undefined syms with non-default visibility. */
+ else if ((eh->root.type == bfd_link_hash_undefined
+ && ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT)
+ || UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
+ hh->dyn_relocs = NULL;
+
if (hh->dyn_relocs == NULL)
- return TRUE;
+ {
+ eh->non_got_ref = 0;
+ return TRUE;
+ }
/* If this is a -Bsymbolic shared link, then we need to discard all
space allocated for dynamic pc-relative relocs against symbols
changes. */
if (bfd_link_pic (info))
{
- /* Discard relocs on undefined syms with non-default visibility. */
- if ((eh->root.type == bfd_link_hash_undefined
- && ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT)
- || UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
- hh->dyn_relocs = NULL;
-
#if RELATIVE_DYNRELOCS
- else if (SYMBOL_CALLS_LOCAL (info, eh))
+ if (SYMBOL_CALLS_LOCAL (info, eh))
{
struct elf32_hppa_dyn_reloc_entry **hdh_pp;
symbols which turn out to need copy relocs or are not
dynamic. */
- if (!eh->non_got_ref
- && !eh->def_regular)
+ if (eh->dynamic_adjusted
+ && eh->non_got_ref
+ && !eh->def_regular
+ && !ELF_COMMON_DEF_P (eh))
{
if (!ensure_undef_dynamic (info, eh))
return FALSE;
if (eh->dynindx == -1)
- hh->dyn_relocs = NULL;
+ {
+ eh->non_got_ref = 0;
+ hh->dyn_relocs = NULL;
+ }
}
else
- hh->dyn_relocs = NULL;
+ {
+ eh->non_got_ref = 0;
+ hh->dyn_relocs = NULL;
+ }
}
/* Finally, allocate space. */
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& hh != NULL
- && hh->eh.dynindx != -1
- && !hh->eh.non_got_ref
- && !hh->eh.def_regular))
+ && hh->eh.non_got_ref))
{
Elf_Internal_Rela outrel;
bfd_boolean skip;
|| 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->u.weakdef != NULL
+ ? h->u.weakdef->non_got_ref
+ : !local && (((struct ppc_elf_link_hash_entry *) h)
+ ->dyn_relocs != NULL));
+
/* Clear procedure linkage table information for any symbol that
won't need a .plt entry. */
struct plt_entry *ent;
if (ent->plt.refcount > 0)
break;
if (ent == NULL
- || (h->type != STT_GNU_IFUNC
- && (SYMBOL_CALLS_LOCAL (info, h)
- || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))))
+ || (h->type != STT_GNU_IFUNC && local))
{
/* A PLT entry is not required/allowed when:
h->plt.plist = NULL;
h->needs_plt = 0;
h->pointer_equality_needed = 0;
- /* After adjust_dynamic_symbol, non_got_ref set 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, and for
- function symbols, defining the symbol on the PLT call
- stub code. Set non_got_ref here to ensure undef weaks
- stay undefined. */
- h->non_got_ref = 1;
}
else
{
&& !readonly_dynrelocs (h))
{
h->pointer_equality_needed = 0;
- /* Say that we do want dynamic relocs. */
- h->non_got_ref = 0;
/* If we haven't seen a branch reloc then we don't need
a plt entry. */
if (!h->needs_plt)
h->plt.plist = NULL;
}
+ else
+ /* 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;
}
h->protected_def = 0;
/* Function symbols can't have copy relocs. */
&& htab->params->pic_fixup == 0
&& info->disable_target_specific_optimizations <= 1)
htab->params->pic_fixup = 1;
- h->non_got_ref = 0;
return TRUE;
}
/* If -z nocopyreloc was given, we won't generate them either. */
if (info->nocopyreloc)
- {
- h->non_got_ref = 0;
- return TRUE;
- }
+ return TRUE;
/* 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.
&& !htab->is_vxworks
&& !h->def_regular
&& !readonly_dynrelocs (h))
- {
- h->non_got_ref = 0;
- return TRUE;
- }
+ return TRUE;
/* We must allocate the symbol in our .dynbss section, which will
become part of the .bss section of the executable. There will be
h->needs_copy = 1;
}
+ /* We no longer want dyn_relocs. */
+ h->non_got_ref = 0;
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
\f
&& h->type != STT_GNU_IFUNC)
eh->dyn_relocs = NULL;
+ /* Discard relocs on undefined symbols that must be local. */
+ else if (h->root.type == bfd_link_hash_undefined
+ && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ eh->dyn_relocs = NULL;
+
+ /* Also discard relocs on undefined weak syms with non-default
+ visibility, or when dynamic_undefined_weak says so. */
+ else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+ 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
changes. */
else if (bfd_link_pic (info))
{
- /* Discard relocs on undefined symbols that must be local. */
- if (h->root.type == bfd_link_hash_undefined
- && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- eh->dyn_relocs = NULL;
-
- /* Also discard relocs on undefined weak syms with non-default
- visibility, or when dynamic_undefined_weak says so. */
- else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
- eh->dyn_relocs = NULL;
-
/* 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. */
- else if (SYMBOL_CALLS_LOCAL (info, h))
+ if (SYMBOL_CALLS_LOCAL (info, h))
{
struct elf_dyn_relocs **pp;
/* For the non-pic case, discard space for relocs against
symbols which turn out to need copy relocs or are not
dynamic. */
- if (!h->non_got_ref
+ if (h->dynamic_adjusted
+ && h->non_got_ref
&& !h->def_regular
+ && !ELF_COMMON_DEF_P (h)
&& !(h->protected_def
&& eh->has_addr16_ha
&& eh->has_addr16_lo
return FALSE;
if (h->dynindx == -1)
- eh->dyn_relocs = NULL;
+ {
+ h->non_got_ref = 0;
+ eh->dyn_relocs = NULL;
+ }
}
else
- eh->dyn_relocs = NULL;
+ {
+ h->non_got_ref = 0;
+ eh->dyn_relocs = NULL;
+ }
}
/* Allocate space. */
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& h != NULL
- && h->dynindx != -1
- && !h->non_got_ref
- && !h->def_regular
- && !(h->protected_def
- && ppc_elf_hash_entry (h)->has_addr16_ha
- && ppc_elf_hash_entry (h)->has_addr16_lo
- && htab->params->pic_fixup > 0)))
+ && h->non_got_ref))
{
int skip;
bfd_byte *loc;
|| h->type == STT_GNU_IFUNC
|| h->needs_plt)
{
+ bfd_boolean local = (((struct ppc_link_hash_entry *) h)->save_res
+ || SYMBOL_CALLS_LOCAL (info, h)
+ || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+ /* Discard dyn_relocs when non-pic if we've decided that a
+ function symbol is local and not an ifunc. We keep dynamic
+ relocs for ifuncs when local rather than always emitting a
+ plt call stub for them and defining the symbol on the call
+ stub. We can't do that for ELFv1 anyway (a function symbol
+ is defined on a descriptor, not code) and it can be faster at
+ run-time due to not needing to bounce through a stub. The
+ dyn_relocs for ifuncs will be applied even in a static
+ executable. */
+ if (!bfd_link_pic (info)
+ && h->type != STT_GNU_IFUNC
+ && local)
+ ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
+
/* Clear procedure linkage table information for any symbol that
won't need a .plt entry. */
struct plt_entry *ent;
if (ent->plt.refcount > 0)
break;
if (ent == NULL
- || (h->type != STT_GNU_IFUNC
- && (SYMBOL_CALLS_LOCAL (info, h)
- || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
- || ((struct ppc_link_hash_entry *) h)->save_res)
+ || (h->type != STT_GNU_IFUNC && local))
{
h->plt.plist = NULL;
h->needs_plt = 0;
h->pointer_equality_needed = 0;
- /* After adjust_dynamic_symbol, non_got_ref set 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, and for
- ELFv2 function symbols, defining the symbol on the PLT
- call stub code. Set non_got_ref here to ensure undef
- weaks stay undefined. */
- h->non_got_ref = 1;
}
else if (abiversion (info->output_bfd) >= 2)
{
relocs is that calling via a global entry stub costs a
few more instructions, and pointer_equality_needed causes
extra work in ld.so when resolving these symbols. */
- if (global_entry_stub (h)
- && !alias_readonly_dynrelocs (h))
+ if (global_entry_stub (h))
{
- h->pointer_equality_needed = 0;
- /* Say that we do want dynamic relocs. */
- h->non_got_ref = 0;
- /* If we haven't seen a branch reloc then we don't need
- a plt entry. */
- if (!h->needs_plt)
- h->plt.plist = NULL;
+ if (!alias_readonly_dynrelocs (h))
+ {
+ h->pointer_equality_needed = 0;
+ /* If we haven't seen a branch reloc then we don't need
+ a plt entry. */
+ if (!h->needs_plt)
+ h->plt.plist = NULL;
+ }
+ 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. */
+ ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
}
/* ELFv2 function symbols can't have copy relocs. */
plt entry. */
h->plt.plist = NULL;
h->pointer_equality_needed = 0;
- h->non_got_ref = 0;
return TRUE;
}
}
definition for the variable. Text relocations are preferable
to an incorrect program. */
|| h->protected_def)
- {
- h->non_got_ref = 0;
- return TRUE;
- }
+ return TRUE;
if (h->plt.plist != NULL)
{
h->needs_copy = 1;
}
+ /* We no longer want dyn_relocs. */
+ ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
&& h->type != STT_GNU_IFUNC)
eh->dyn_relocs = NULL;
+ /* Discard relocs on undefined symbols that must be local. */
+ else if (h->root.type == bfd_link_hash_undefined
+ && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ eh->dyn_relocs = NULL;
+
/* Also discard relocs on undefined weak syms with non-default
visibility, or when dynamic_undefined_weak says so. */
else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
return FALSE;
}
}
- else if (h->type == STT_GNU_IFUNC)
- {
- /* A plt entry is always created when making direct calls to
- an ifunc, even when building a static executable, but
- that doesn't cover all cases. We may have only an ifunc
- initialised function pointer for a given ifunc symbol.
-
- For ELFv2, dynamic relocations are not required when
- generating a global entry PLT stub. */
- if (abiversion (info->output_bfd) >= 2)
- {
- if (global_entry_stub (h))
- eh->dyn_relocs = NULL;
- }
-
- /* For ELFv1 we have function descriptors. Descriptors need
- to be treated like PLT entries and thus have dynamic
- relocations. One exception is when the function
- descriptor is copied into .dynbss (which should only
- happen with ancient versions of gcc). */
- else if (h->needs_copy)
- eh->dyn_relocs = NULL;
- }
- else if (ELIMINATE_COPY_RELOCS)
+ else if (ELIMINATE_COPY_RELOCS && h->type != STT_GNU_IFUNC)
{
/* For the non-pic 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)
+ if (h->dynamic_adjusted
+ && !h->def_regular
+ && !ELF_COMMON_DEF_P (h))
{
/* Make sure this symbol is output as a dynamic symbol. */
if (!ensure_undef_dynamic (info, h))