From 287c7eaf0d90cc1bbb5a5463c665b163c6ee04e7 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 22 Nov 2017 21:07:03 +1030 Subject: [PATCH] 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. --- bfd/ChangeLog | 19 ++++++++ bfd/elf32-hppa.c | 88 +++++++++++++++++------------------- bfd/elf32-ppc.c | 115 ++++++++++++++++++++++------------------------- 3 files changed, 113 insertions(+), 109 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 40776497908..55fe3b4e61e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,22 @@ +2017-11-23 Alan Modra + + * 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 * elf64-ppc.c (struct ppc_link_hash_entry): Delete weakref field. diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 01060dbef9c..a0f7060fe1a 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -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; diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 756523b1dd3..81e53153224 100644 --- a/bfd/elf32-ppc.c +++ b/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; -- 2.30.2