Fix hppa-linux pr22269-1 fail
authorAlan Modra <amodra@gmail.com>
Fri, 27 Oct 2017 04:34:25 +0000 (15:04 +1030)
committerAlan Modra <amodra@gmail.com>
Mon, 30 Oct 2017 00:33:50 +0000 (11:03 +1030)
Adds UNDEFWEAK_NO_DYNAMIC_RELOC in the rest of places needed in this
file, reduces dynamic relocations in a number of cases, and removes
some bogus code that was attempting to handle dynamic common symbols
specially.

PR 22269
* elf32-hppa.c (elf32_hppa_check_relocs): Move SEC_ALLOC test to
ensure non_got_ref is not set due to debug references.
(elf32_hppa_adjust_dynamic_symbol): Tidy plabel handling.  Use
SYMBOL_CALLS_LOCAL and UNDEFWEAK_NO_DYNAMIC_RELOC when determining
need for a plt entry.
(allocate_dynrelocs): Similarly for got entries.  Tidy code discarding
dynamic relocs when pic.  Remove bogus code attempting to handle
commons.
(elf32_hppa_relocate_section): Similarly.  Delete resolved_to_zero
and simplify.
(elf32_hppa_finish_dynamic_symbol): Use UNDEFWEAK_NO_DYNAMIC_RELOC
and SYMBOL_REFERENCES_LOCAL in GOT handling.

bfd/ChangeLog
bfd/elf32-hppa.c

index 07ad2b8..c56e1cf 100644 (file)
@@ -1,3 +1,19 @@
+2017-10-30  Alan Modra  <amodra@gmail.com>
+
+       PR 22269
+       * elf32-hppa.c (elf32_hppa_check_relocs): Move SEC_ALLOC test to
+       ensure non_got_ref is not set due to debug references.
+       (elf32_hppa_adjust_dynamic_symbol): Tidy plabel handling.  Use
+       SYMBOL_CALLS_LOCAL and UNDEFWEAK_NO_DYNAMIC_RELOC when determining
+       need for a plt entry.
+       (allocate_dynrelocs): Similarly for got entries.  Tidy code discarding
+       dynamic relocs when pic.  Remove bogus code attempting to handle
+       commons.
+       (elf32_hppa_relocate_section): Similarly.  Delete resolved_to_zero
+       and simplify.
+       (elf32_hppa_finish_dynamic_symbol): Use UNDEFWEAK_NO_DYNAMIC_RELOC
+       and SYMBOL_REFERENCES_LOCAL in GOT handling.
+
 2017-10-28  Alan Modra  <amodra@gmail.com>
 
        PR 22300
index 97b6026..be88d87 100644 (file)
@@ -1423,7 +1423,8 @@ elf32_hppa_check_relocs (bfd *abfd,
            }
        }
 
-      if (need_entry & NEED_DYNREL)
+      if ((need_entry & NEED_DYNREL) != 0
+         && (sec->flags & SEC_ALLOC) != 0)
        {
          /* Flag this symbol as having a non-got, non-plt reference
             so that we generate copy relocs if it turns out to be
@@ -1460,7 +1461,6 @@ elf32_hppa_check_relocs (bfd *abfd,
             dynamic library if we manage to avoid copy relocs for the
             symbol.  */
          if ((bfd_link_pic (info)
-              && (sec->flags & SEC_ALLOC) != 0
               && (IS_ABSOLUTE_RELOC (r_type)
                   || (hh != NULL
                       && (!SYMBOLIC_BIND (info, &hh->eh)
@@ -1468,7 +1468,6 @@ elf32_hppa_check_relocs (bfd *abfd,
                           || !hh->eh.def_regular))))
              || (ELIMINATE_COPY_RELOCS
                  && !bfd_link_pic (info)
-                 && (sec->flags & SEC_ALLOC) != 0
                  && hh != NULL
                  && (hh->eh.root.type == bfd_link_hash_defweak
                      || !hh->eh.def_regular)))
@@ -1680,15 +1679,12 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
       /* 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 <= 0)
+      if (hppa_elf_hash_entry (eh)->plabel)
        eh->plt.refcount = 1;
 
-      if (eh->plt.refcount <= 0
-         || (eh->def_regular
-             && eh->root.type != bfd_link_hash_defweak
-             && ! hppa_elf_hash_entry (eh)->plabel
-             && (!bfd_link_pic (info) || SYMBOLIC_BIND (info, eh))))
+      else if (eh->plt.refcount <= 0
+              || SYMBOL_CALLS_LOCAL (info, eh)
+              || UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
        {
          /* The .plt entry is not needed when:
             a) Garbage collection has removed all references to the
@@ -1929,7 +1925,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
       if (htab->etab.dynamic_sections_created
          && (bfd_link_pic (info)
              || (eh->dynindx != -1
-                 && !eh->forced_local)))
+                 && !SYMBOL_REFERENCES_LOCAL (info, eh)))
+         && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
        {
          htab->etab.srelgot->size += sizeof (Elf32_External_Rela);
          if ((hh->tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
@@ -1941,6 +1938,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
   else
     eh->got.offset = (bfd_vma) -1;
 
+  /* If no dynamic sections we can't have dynamic relocs.  */
+  if (!htab->etab.dynamic_sections_created)
+    hh->dyn_relocs = NULL;
+
   if (hh->dyn_relocs == NULL)
     return TRUE;
 
@@ -1953,9 +1954,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
     {
       /* Discard relocs on undefined syms with non-default visibility.  */
       if ((eh->root.type == bfd_link_hash_undefined
-          || eh->root.type == bfd_link_hash_undefweak)
-         && (ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT
-             || UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh)))
+          && ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT)
+         || UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
        hh->dyn_relocs = NULL;
 
 #if RELATIVE_DYNRELOCS
@@ -1981,19 +1981,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
            return FALSE;
        }
     }
-  else
+  else if (ELIMINATE_COPY_RELOCS)
     {
       /* For the non-shared case, discard space for relocs against
         symbols which turn out to need copy relocs or are not
         dynamic.  */
 
       if (!eh->non_got_ref
-         && ((ELIMINATE_COPY_RELOCS
-              && eh->def_dynamic
-              && !eh->def_regular)
-              || (htab->etab.dynamic_sections_created
-                  && (eh->root.type == bfd_link_hash_undefweak
-                      || eh->root.type == bfd_link_hash_undefined))))
+         && !eh->def_regular)
        {
          if (!ensure_undef_dynamic (info, eh))
            return FALSE;
@@ -3550,7 +3545,6 @@ elf32_hppa_relocate_section (bfd *output_bfd,
       const char *sym_name;
       bfd_boolean plabel;
       bfd_boolean warned_undef;
-      bfd_boolean resolved_to_zero;
 
       r_type = ELF32_R_TYPE (rela->r_info);
       if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
@@ -3614,9 +3608,6 @@ elf32_hppa_relocate_section (bfd *output_bfd,
       if (bfd_link_relocatable (info))
        continue;
 
-      resolved_to_zero = (hh != NULL
-                         && UNDEFWEAK_NO_DYNAMIC_RELOC (info, &hh->eh));
-
       /* Do any required modifications to the relocation value, and
         determine what types of dynamic info we need to output, if
         any.  */
@@ -3628,7 +3619,8 @@ elf32_hppa_relocate_section (bfd *output_bfd,
        case R_PARISC_DLTIND21L:
          {
            bfd_vma off;
-           bfd_boolean do_got = 0;
+           bfd_boolean do_got = FALSE;
+           bfd_boolean reloc = bfd_link_pic (info);
 
            /* Relocation is to the entry for this symbol in the
               global offset table.  */
@@ -3638,9 +3630,14 @@ elf32_hppa_relocate_section (bfd *output_bfd,
 
                off = hh->eh.got.offset;
                dyn = htab->etab.dynamic_sections_created;
-               if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
-                                                      bfd_link_pic (info),
-                                                      &hh->eh))
+               reloc = (!UNDEFWEAK_NO_DYNAMIC_RELOC (info, &hh->eh)
+                        && (reloc
+                            || (hh->eh.dynindx != -1
+                                && !SYMBOL_REFERENCES_LOCAL (info, &hh->eh))));
+               if (!reloc
+                   || !WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+                                                        bfd_link_pic (info),
+                                                        &hh->eh))
                  {
                    /* If we aren't going to call finish_dynamic_symbol,
                       then we need to handle initialisation of the .got
@@ -3653,7 +3650,7 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                    else
                      {
                        hh->eh.got.offset |= 1;
-                       do_got = 1;
+                       do_got = TRUE;
                      }
                  }
              }
@@ -3673,13 +3670,13 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                else
                  {
                    local_got_offsets[r_symndx] |= 1;
-                   do_got = 1;
+                   do_got = TRUE;
                  }
              }
 
            if (do_got)
              {
-               if (bfd_link_pic (info))
+               if (reloc)
                  {
                    /* Output a dynamic relocation for this GOT entry.
                       In this case it is relative to the base of the
@@ -3838,29 +3835,20 @@ elf32_hppa_relocate_section (bfd *output_bfd,
             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 you squint, the non-shared test
-            here does indeed match the one in ..check_relocs, the
-            difference being that here we test DEF_DYNAMIC as well as
-            !DEF_REGULAR.  All common syms end up with !DEF_REGULAR,
-            which is why we can't use just that test here.
-            Conversely, DEF_DYNAMIC can't be used in check_relocs as
-            there all files have not been loaded.  */
+            allocate_dynrelocs.  */
          if ((bfd_link_pic (info)
-              && (hh == NULL
-                  || (ELF_ST_VISIBILITY (hh->eh.other) == STV_DEFAULT
-                      && !resolved_to_zero)
-                  || hh->eh.root.type != bfd_link_hash_undefweak)
+              && !(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)))
-             || (!bfd_link_pic (info)
+             || (ELIMINATE_COPY_RELOCS
+                 && !bfd_link_pic (info)
                  && hh != NULL
                  && hh->eh.dynindx != -1
                  && !hh->eh.non_got_ref
-                 && ((ELIMINATE_COPY_RELOCS
-                      && hh->eh.def_dynamic
-                      && !hh->eh.def_regular)
-                     || hh->eh.root.type == bfd_link_hash_undefweak
-                     || hh->eh.root.type == bfd_link_hash_undefined)))
+                 && !hh->eh.def_regular))
            {
              Elf_Internal_Rela outrel;
              bfd_boolean skip;
@@ -4258,42 +4246,49 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
 
   if (eh->got.offset != (bfd_vma) -1
       && (hppa_elf_hash_entry (eh)->tls_type & GOT_TLS_GD) == 0
-      && (hppa_elf_hash_entry (eh)->tls_type & GOT_TLS_IE) == 0)
+      && (hppa_elf_hash_entry (eh)->tls_type & GOT_TLS_IE) == 0
+      && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
     {
-      /* This symbol has an entry in the global offset table.  Set it
-        up.  */
-
-      rela.r_offset = ((eh->got.offset &~ (bfd_vma) 1)
-                     + htab->etab.sgot->output_offset
-                     + htab->etab.sgot->output_section->vma);
-
-      /* If this is a -Bsymbolic link and the symbol is defined
-        locally or was forced to be local because of a version file,
-        we just want to emit a RELATIVE reloc.  The entry in the
-        global offset table will already have been initialized in the
-        relocate_section function.  */
-      if (bfd_link_pic (info)
-         && (SYMBOLIC_BIND (info, eh) || eh->dynindx == -1)
-         && eh->def_regular)
-       {
-         rela.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
-         rela.r_addend = (eh->root.u.def.value
-                         + eh->root.u.def.section->output_offset
-                         + eh->root.u.def.section->output_section->vma);
-       }
-      else
+      bfd_boolean is_dyn = (eh->dynindx != -1
+                           && !SYMBOL_REFERENCES_LOCAL (info, eh));
+
+      if (is_dyn || bfd_link_pic (info))
        {
-         if ((eh->got.offset & 1) != 0)
-           abort ();
+         /* This symbol has an entry in the global offset table.  Set
+            it up.  */
+
+         rela.r_offset = ((eh->got.offset &~ (bfd_vma) 1)
+                          + htab->etab.sgot->output_offset
+                          + htab->etab.sgot->output_section->vma);
+
+         /* If this is a -Bsymbolic link and the symbol is defined
+            locally or was forced to be local because of a version
+            file, we just want to emit a RELATIVE reloc.  The entry
+            in the global offset table will already have been
+            initialized in the relocate_section function.  */
+         if (!is_dyn)
+           {
+             rela.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
+             rela.r_addend = (eh->root.u.def.value
+                              + eh->root.u.def.section->output_offset
+                              + eh->root.u.def.section->output_section->vma);
+           }
+         else
+           {
+             if ((eh->got.offset & 1) != 0)
+               abort ();
 
-         bfd_put_32 (output_bfd, 0, htab->etab.sgot->contents + (eh->got.offset & ~1));
-         rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_DIR32);
-         rela.r_addend = 0;
-       }
+             bfd_put_32 (output_bfd, 0,
+                         htab->etab.sgot->contents + (eh->got.offset & ~1));
+             rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_DIR32);
+             rela.r_addend = 0;
+           }
 
-      loc = htab->etab.srelgot->contents;
-      loc += htab->etab.srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
-      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
+         loc = htab->etab.srelgot->contents;
+         loc += (htab->etab.srelgot->reloc_count++
+                 * sizeof (Elf32_External_Rela));
+         bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
+       }
     }
 
   if (eh->needs_copy)