+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.
#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
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)
{
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
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
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;
}
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. */
}
/* 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);
}
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
dynamic. */
if (eh->dynamic_adjusted
- && eh->non_got_ref
&& !eh->def_regular
&& !ELF_COMMON_DEF_P (eh))
{
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. */
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;
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)
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;
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
|| 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. */
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. */
&& !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
}
/* 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);
}
\f
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
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
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. */
|| 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;