diff options
-rw-r--r-- | bfd/ChangeLog | 12 | ||||
-rw-r--r-- | bfd/elf32-hppa.c | 119 |
2 files changed, 94 insertions, 37 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ed33136..9bdc0f0 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2017-11-04 Alan Modra <amodra@gmail.com> + + PR 22394 + * elf32-hppa.c (elf32_hppa_check_relocs): Don't create dyn_relocs + for plabels when non-pic. + (maybe_set_textrel): New function. + (readonly_dynrelocs): Move and rewrite. + (elf32_hppa_adjust_dynamic_symbol): Use it. Don't create copy + relocs when def_regular or -z nocopyreloc. Handle non_got_ref + for functions. Expand non_got_ref comments. + (elf32_hppa_size_dynamic_sections): Use maybe_set_textrel. + 2017-11-03 H.J. Lu <hongjiu.lu@intel.com> * elf32-i386.c (elf_i386_check_relocs): Set plt.refcount to 1. diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index be88d87..acc96af 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -1210,7 +1210,9 @@ elf32_hppa_check_relocs (bfd *abfd, functions indirectly or to compare function pointers. We avoid the mess by always pointing a PLABEL into the .plt, even for local functions. */ - need_entry = PLT_PLABEL | NEED_PLT | NEED_DYNREL; + need_entry = PLT_PLABEL | NEED_PLT; + if (bfd_link_pic (info)) + need_entry |= NEED_DYNREL; break; case R_PARISC_PCREL12F: @@ -1658,6 +1660,25 @@ elf32_hppa_hide_symbol (struct bfd_link_info *info, } } +/* Find any dynamic relocs that apply to read-only sections. */ + +static asection * +readonly_dynrelocs (struct elf_link_hash_entry *eh) +{ + struct elf32_hppa_link_hash_entry *hh; + struct elf32_hppa_dyn_reloc_entry *hdh_p; + + hh = hppa_elf_hash_entry (eh); + for (hdh_p = hh->dyn_relocs; hdh_p != NULL; hdh_p = hdh_p->hdh_next) + { + asection *sec = hdh_p->sec->output_section; + + if (sec != NULL && (sec->flags & SEC_READONLY) != 0) + return hdh_p->sec; + } + return NULL; +} + /* 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 @@ -1676,15 +1697,41 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info, if (eh->type == STT_FUNC || eh->needs_plt) { + /* 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. + 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. */ + 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; + /* 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 hide_symbol can be called before the plabel flag is set. */ if (hppa_elf_hash_entry (eh)->plabel) eh->plt.refcount = 1; + /* Note that unlike some other backends, the refcount is not + incremented for a non-call (and non-plabel) function reference. */ else if (eh->plt.refcount <= 0 - || SYMBOL_CALLS_LOCAL (info, eh) - || UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh)) + || local) { /* The .plt entry is not needed when: a) Garbage collection has removed all references to the @@ -1693,11 +1740,11 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info, object, and it's not a weak definition, nor is the symbol used by a plabel relocation. Either this object is the application or we are doing a shared symbolic link. */ - eh->plt.offset = (bfd_vma) -1; eh->needs_plt = 0; } + /* Function symbols can't have copy relocs. */ return TRUE; } else @@ -1731,28 +1778,25 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info, /* 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) - return TRUE; - - if (ELIMINATE_COPY_RELOCS) { - struct elf32_hppa_link_hash_entry *hh; - struct elf32_hppa_dyn_reloc_entry *hdh_p; + eh->non_got_ref = 1; + return TRUE; + } - hh = hppa_elf_hash_entry (eh); - for (hdh_p = hh->dyn_relocs; hdh_p != NULL; hdh_p = hdh_p->hdh_next) - { - sec = hdh_p->sec->output_section; - if (sec != NULL && (sec->flags & SEC_READONLY) != 0) - break; - } + /* If -z nocopyreloc was given, we won't generate them either. */ + if (info->nocopyreloc) + { + eh->non_got_ref = 0; + 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. */ - if (hdh_p == NULL) - { - eh->non_got_ref = 0; - return TRUE; - } + eh->non_got_ref = 0; + return TRUE; } /* We must allocate the symbol in our .dynbss section, which will @@ -2029,28 +2073,29 @@ clobber_millicode_symbols (struct elf_link_hash_entry *eh, return TRUE; } -/* Find any dynamic relocs that apply to read-only sections. */ +/* Set DF_TEXTREL if we find any dynamic relocs that apply to + read-only sections. */ static bfd_boolean -readonly_dynrelocs (struct elf_link_hash_entry *eh, void *inf) +maybe_set_textrel (struct elf_link_hash_entry *eh, void *inf) { - struct elf32_hppa_link_hash_entry *hh; - struct elf32_hppa_dyn_reloc_entry *hdh_p; + asection *sec; - hh = hppa_elf_hash_entry (eh); - for (hdh_p = hh->dyn_relocs; hdh_p != NULL; hdh_p = hdh_p->hdh_next) - { - asection *sec = hdh_p->sec->output_section; + if (eh->root.type == bfd_link_hash_indirect) + return TRUE; - if (sec != NULL && (sec->flags & SEC_READONLY) != 0) - { - struct bfd_link_info *info = inf; + sec = readonly_dynrelocs (eh); + if (sec != NULL) + { + struct bfd_link_info *info = (struct bfd_link_info *) inf; - info->flags |= DF_TEXTREL; + info->flags |= DF_TEXTREL; + info->callbacks->minfo + (_("%B: dynamic relocation in read-only section `%A'\n"), + sec->owner, sec); - /* Not an error, just cut short the traversal. */ - return FALSE; - } + /* Not an error, just cut short the traversal. */ + return FALSE; } return TRUE; } @@ -2334,7 +2379,7 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (&htab->etab, readonly_dynrelocs, info); + elf_link_hash_traverse (&htab->etab, maybe_set_textrel, info); if ((info->flags & DF_TEXTREL) != 0) { |