ELF: Don't set non_ir_ref_regular in check_relocs
[deliverable/binutils-gdb.git] / bfd / elf32-hppa.c
index 97b6026c6b0b8fe690a47086edbfb625f6b7b4ba..6b2abb26a14662a883c576ba56e0eafdb1be03bb 100644 (file)
@@ -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
@@ -206,6 +207,15 @@ struct elf32_hppa_stub_hash_entry
   asection *id_sec;
 };
 
+enum _tls_type
+  {
+    GOT_UNKNOWN = 0,
+    GOT_NORMAL = 1,
+    GOT_TLS_GD = 2,
+    GOT_TLS_LDM = 4,
+    GOT_TLS_IE = 8
+  };
+
 struct elf32_hppa_link_hash_entry
 {
   struct elf_link_hash_entry eh;
@@ -233,10 +243,7 @@ struct elf32_hppa_link_hash_entry
 #endif
   } *dyn_relocs;
 
-  enum
-  {
-    GOT_UNKNOWN = 0, GOT_NORMAL = 1, GOT_TLS_GD = 2, GOT_TLS_LDM = 4, GOT_TLS_IE = 8
-  } tls_type;
+  ENUM_BITFIELD (_tls_type) tls_type : 8;
 
   /* Set if this symbol is used by a plabel reloc.  */
   unsigned int plabel:1;
@@ -1014,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)
        {
@@ -1132,7 +1140,6 @@ elf32_hppa_check_relocs (bfd *abfd,
   const Elf_Internal_Rela *rela_end;
   struct elf32_hppa_link_hash_table *htab;
   asection *sreloc;
-  int tls_type = GOT_UNKNOWN, old_tls_type = GOT_UNKNOWN;
 
   if (bfd_link_relocatable (info))
     return TRUE;
@@ -1168,10 +1175,6 @@ elf32_hppa_check_relocs (bfd *abfd,
          while (hh->eh.root.type == bfd_link_hash_indirect
                 || hh->eh.root.type == bfd_link_hash_warning)
            hh = hppa_elf_hash_entry (hh->eh.root.u.i.link);
-
-         /* PR15323, ref flags aren't set for references in the same
-            object.  */
-         hh->eh.root.non_ir_ref_regular = 1;
        }
 
       r_type = ELF32_R_TYPE (rela->r_info);
@@ -1210,7 +1213,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:
@@ -1310,7 +1315,7 @@ elf32_hppa_check_relocs (bfd *abfd,
 
        case R_PARISC_TLS_IE21L:
        case R_PARISC_TLS_IE14R:
-         if (bfd_link_pic (info))
+         if (bfd_link_dll (info))
             info->flags |= DF_STATIC_TLS;
          need_entry = NEED_GOT;
          break;
@@ -1322,22 +1327,23 @@ elf32_hppa_check_relocs (bfd *abfd,
       /* Now carry out our orders.  */
       if (need_entry & NEED_GOT)
        {
+         int tls_type = GOT_NORMAL;
+
          switch (r_type)
            {
            default:
-             tls_type = GOT_NORMAL;
              break;
            case R_PARISC_TLS_GD21L:
            case R_PARISC_TLS_GD14R:
-             tls_type |= GOT_TLS_GD;
+             tls_type = GOT_TLS_GD;
              break;
            case R_PARISC_TLS_LDM21L:
            case R_PARISC_TLS_LDM14R:
-             tls_type |= GOT_TLS_LDM;
+             tls_type = GOT_TLS_LDM;
              break;
            case R_PARISC_TLS_IE21L:
            case R_PARISC_TLS_IE14R:
-             tls_type |= GOT_TLS_IE;
+             tls_type = GOT_TLS_IE;
              break;
            }
 
@@ -1349,39 +1355,28 @@ elf32_hppa_check_relocs (bfd *abfd,
                return FALSE;
            }
 
-         if (r_type == R_PARISC_TLS_LDM21L
-             || r_type == R_PARISC_TLS_LDM14R)
-           htab->tls_ldm_got.refcount += 1;
-         else
+         if (hh != NULL)
            {
-             if (hh != NULL)
-               {
-                 hh->eh.got.refcount += 1;
-                 old_tls_type = hh->tls_type;
-               }
+             if (tls_type == GOT_TLS_LDM)
+               htab->tls_ldm_got.refcount += 1;
              else
-               {
-                 bfd_signed_vma *local_got_refcounts;
-
-                 /* This is a global offset table entry for a local symbol.  */
-                 local_got_refcounts = hppa32_elf_local_refcounts (abfd);
-                 if (local_got_refcounts == NULL)
-                   return FALSE;
-                 local_got_refcounts[r_symndx] += 1;
-
-                 old_tls_type = hppa_elf_local_got_tls_type (abfd) [r_symndx];
-               }
-
-             tls_type |= old_tls_type;
+               hh->eh.got.refcount += 1;
+             hh->tls_type |= tls_type;
+           }
+         else
+           {
+             bfd_signed_vma *local_got_refcounts;
 
-             if (old_tls_type != tls_type)
-               {
-                 if (hh != NULL)
-                   hh->tls_type = tls_type;
-                 else
-                   hppa_elf_local_got_tls_type (abfd) [r_symndx] = tls_type;
-               }
+             /* This is a global offset table entry for a local symbol.  */
+             local_got_refcounts = hppa32_elf_local_refcounts (abfd);
+             if (local_got_refcounts == NULL)
+               return FALSE;
+             if (tls_type == GOT_TLS_LDM)
+               htab->tls_ldm_got.refcount += 1;
+             else
+               local_got_refcounts[r_symndx] += 1;
 
+             hppa_elf_local_got_tls_type (abfd) [r_symndx] |= tls_type;
            }
        }
 
@@ -1423,7 +1418,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 +1456,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 +1463,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)))
@@ -1659,6 +1653,43 @@ 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;
+}
+
+/* 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
@@ -1677,18 +1708,23 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
   if (eh->type == STT_FUNC
       || eh->needs_plt)
     {
+      bfd_boolean local = (SYMBOL_CALLS_LOCAL (info, eh)
+                          || UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh));
+      /* Discard dyn_relocs when non-pic if we've decided that a
+        function symbol is local.  */
+      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
         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))))
+      /* 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
+              || local)
        {
          /* The .plt entry is not needed when:
             a) Garbage collection has removed all references to the
@@ -1697,11 +1733,16 @@ 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;
        }
 
+      /* 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;
     }
   else
@@ -1710,15 +1751,14 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (eh->u.weakdef != NULL)
+  if (eh->is_weakalias)
     {
-      if (eh->u.weakdef->root.type != bfd_link_hash_defined
-         && eh->u.weakdef->root.type != bfd_link_hash_defweak)
-       abort ();
-      eh->root.u.def.section = eh->u.weakdef->root.u.def.section;
-      eh->root.u.def.value = eh->u.weakdef->root.u.def.value;
+      struct elf_link_hash_entry *def = weakdef (eh);
+      BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+      eh->root.u.def.section = def->root.u.def.section;
+      eh->root.u.def.value = def->root.u.def.value;
       if (ELIMINATE_COPY_RELOCS)
-       eh->non_got_ref = eh->u.weakdef->non_got_ref;
+       eh->non_got_ref = def->non_got_ref;
       return TRUE;
     }
 
@@ -1737,26 +1777,16 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
   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;
-
-      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)
+    return TRUE;
 
+  if (ELIMINATE_COPY_RELOCS
+      && !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.  */
-      if (hdh_p == NULL)
-       {
-         eh->non_got_ref = 0;
-         return TRUE;
-       }
+      return TRUE;
     }
 
   /* We must allocate the symbol in our .dynbss section, which will
@@ -1792,6 +1822,8 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
       eh->needs_copy = 1;
     }
 
+  /* We no longer want dyn_relocs.  */
+  hppa_elf_hash_entry (eh)->dyn_relocs = NULL;
   return _bfd_elf_adjust_dynamic_copy (info, eh, sec);
 }
 
@@ -1876,6 +1908,39 @@ allocate_plt_static (struct elf_link_hash_entry *eh, void *inf)
   return TRUE;
 }
 
+/* Calculate size of GOT entries for symbol given its TLS_TYPE.  */
+
+static inline unsigned int
+got_entries_needed (int tls_type)
+{
+  unsigned int need = 0;
+
+  if ((tls_type & GOT_NORMAL) != 0)
+    need += GOT_ENTRY_SIZE;
+  if ((tls_type & GOT_TLS_GD) != 0)
+    need += GOT_ENTRY_SIZE * 2;
+  if ((tls_type & GOT_TLS_IE) != 0)
+    need += GOT_ENTRY_SIZE;
+  return need;
+}
+
+/* Calculate size of relocs needed for symbol given its TLS_TYPE and
+   NEEDed GOT entries.  KNOWN says a TPREL offset can be calculated
+   at link time.  */
+
+static inline unsigned int
+got_relocs_needed (int tls_type, unsigned int need, bfd_boolean known)
+{
+  /* All the entries we allocated need relocs.
+     Except IE in executable with a local symbol.  We could also omit
+     the DTPOFF reloc on the second word of a GD entry under the same
+     condition as that for IE, but ld.so might want to differentiate
+     LD and GD entries at some stage.  */
+  if ((tls_type & GOT_TLS_IE) != 0 && known)
+    need -= GOT_ENTRY_SIZE;
+  return need * sizeof (Elf32_External_Rela) / GOT_ENTRY_SIZE;
+}
+
 /* Allocate space in .plt, .got and associated reloc sections for
    global syms.  */
 
@@ -1915,32 +1980,40 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
 
   if (eh->got.refcount > 0)
     {
+      unsigned int need;
+
       if (!ensure_undef_dynamic (info, eh))
        return FALSE;
 
       sec = htab->etab.sgot;
       eh->got.offset = sec->size;
-      sec->size += GOT_ENTRY_SIZE;
-      /* R_PARISC_TLS_GD* needs two GOT entries */
-      if ((hh->tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
-       sec->size += GOT_ENTRY_SIZE * 2;
-      else if ((hh->tls_type & GOT_TLS_GD) == GOT_TLS_GD)
-       sec->size += GOT_ENTRY_SIZE;
+      need = got_entries_needed (hh->tls_type);
+      sec->size += need;
       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))
-           htab->etab.srelgot->size += 2 * sizeof (Elf32_External_Rela);
-         else if ((hh->tls_type & GOT_TLS_GD) == GOT_TLS_GD)
-           htab->etab.srelgot->size += sizeof (Elf32_External_Rela);
+         bfd_boolean tprel_known = (bfd_link_executable (info)
+                                    && SYMBOL_REFERENCES_LOCAL (info, eh));
+         htab->etab.srelgot->size
+           += got_relocs_needed (hh->tls_type, need, tprel_known);
        }
     }
   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;
+
+  /* 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;
 
@@ -1951,15 +2024,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
      changes.  */
   if (bfd_link_pic (info))
     {
-      /* 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)))
-       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;
 
@@ -1981,19 +2047,15 @@ 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))))
+      if (eh->dynamic_adjusted
+         && !eh->def_regular
+         && !ELF_COMMON_DEF_P (eh))
        {
          if (!ensure_undef_dynamic (info, eh))
            return FALSE;
@@ -2034,28 +2096,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;
 }
@@ -2155,20 +2218,17 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        {
          if (*local_got > 0)
            {
+             unsigned int need;
+
              *local_got = sec->size;
-             sec->size += GOT_ENTRY_SIZE;
-             if ((*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
-               sec->size += 2 * GOT_ENTRY_SIZE;
-             else if ((*local_tls_type & GOT_TLS_GD) == GOT_TLS_GD)
-               sec->size += GOT_ENTRY_SIZE;
+             need = got_entries_needed (*local_tls_type);
+             sec->size += need;
              if (bfd_link_pic (info))
-               {
-                 srel->size += sizeof (Elf32_External_Rela);
-                 if ((*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
-                   srel->size += 2 * sizeof (Elf32_External_Rela);
-                 else if ((*local_tls_type & GOT_TLS_GD) == GOT_TLS_GD)
-                   srel->size += sizeof (Elf32_External_Rela);
-               }
+               {
+                 bfd_boolean tprel_known = bfd_link_executable (info);
+                 htab->etab.srelgot->size
+                   += got_relocs_needed (*local_tls_type, need, tprel_known);
+               }
            }
          else
            *local_got = (bfd_vma) -1;
@@ -2339,7 +2399,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)
            {
@@ -3550,7 +3610,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 +3673,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 +3684,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 +3695,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 +3715,7 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                    else
                      {
                        hh->eh.got.offset |= 1;
-                       do_got = 1;
+                       do_got = TRUE;
                      }
                  }
              }
@@ -3673,13 +3735,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
@@ -3833,34 +3895,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 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.  */
-         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)
-              && (IS_ABSOLUTE_RELOC (r_type)
-                  || !SYMBOL_CALLS_LOCAL (info, &hh->eh)))
-             || (!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)))
+         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;
@@ -3992,17 +4033,17 @@ elf32_hppa_relocate_section (bfd *output_bfd,
            indx = 0;
            if (hh != NULL)
              {
-               bfd_boolean dyn;
-               dyn = htab->etab.dynamic_sections_created;
-
-               if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
-                                                    bfd_link_pic (info),
-                                                    &hh->eh)
-                   && (!bfd_link_pic (info)
-                       || !SYMBOL_REFERENCES_LOCAL (info, &hh->eh)))
-                 {
-                   indx = hh->eh.dynindx;
-                 }
+               if (!htab->etab.dynamic_sections_created
+                   || hh->eh.dynindx == -1
+                   || SYMBOL_REFERENCES_LOCAL (info, &hh->eh)
+                   || UNDEFWEAK_NO_DYNAMIC_RELOC (info, &hh->eh))
+                 /* This is actually a static link, or it is a
+                    -Bsymbolic link and the symbol is defined
+                    locally, or the symbol was forced to be local
+                    because of a version file.  */
+                 ;
+               else
+                 indx = hh->eh.dynindx;
                off = hh->eh.got.offset;
                tls_type = hh->tls_type;
              }
@@ -4028,44 +4069,41 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                   now, and emit any relocations.  If both an IE GOT and a
                   GD GOT are necessary, we emit the GD first.  */
 
-               if ((bfd_link_pic (info) || indx != 0)
-                   && (hh == NULL
-                       || ELF_ST_VISIBILITY (hh->eh.other) == STV_DEFAULT
-                       || hh->eh.root.type != bfd_link_hash_undefweak))
+               if (indx != 0
+                   || (bfd_link_pic (info)
+                       && (hh == NULL
+                           || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &hh->eh))))
                  {
                    need_relocs = TRUE;
                    loc = htab->etab.srelgot->contents;
-                   /* FIXME (CAO): Should this be reloc_count++ ? */
-                   loc += htab->etab.srelgot->reloc_count * sizeof (Elf32_External_Rela);
+                   loc += (htab->etab.srelgot->reloc_count
+                           * sizeof (Elf32_External_Rela));
                  }
 
                if (tls_type & GOT_TLS_GD)
                  {
                    if (need_relocs)
                      {
-                       outrel.r_offset = (cur_off
-                                          + htab->etab.sgot->output_section->vma
-                                          + htab->etab.sgot->output_offset);
-                       outrel.r_info = ELF32_R_INFO (indx,R_PARISC_TLS_DTPMOD32);
+                       outrel.r_offset
+                         = (cur_off
+                            + htab->etab.sgot->output_section->vma
+                            + htab->etab.sgot->output_offset);
+                       outrel.r_info
+                         = ELF32_R_INFO (indx, R_PARISC_TLS_DTPMOD32);
                        outrel.r_addend = 0;
-                       bfd_put_32 (output_bfd, 0, htab->etab.sgot->contents + cur_off);
                        bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
                        htab->etab.srelgot->reloc_count++;
                        loc += sizeof (Elf32_External_Rela);
-
-                       if (indx == 0)
-                         bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
-                                     htab->etab.sgot->contents + cur_off + 4);
-                       else
-                         {
-                           bfd_put_32 (output_bfd, 0,
-                                       htab->etab.sgot->contents + cur_off + 4);
-                           outrel.r_info = ELF32_R_INFO (indx, R_PARISC_TLS_DTPOFF32);
-                           outrel.r_offset += 4;
-                           bfd_elf32_swap_reloca_out (output_bfd, &outrel,loc);
-                           htab->etab.srelgot->reloc_count++;
-                           loc += sizeof (Elf32_External_Rela);
-                         }
+                       outrel.r_info
+                         = ELF32_R_INFO (indx, R_PARISC_TLS_DTPOFF32);
+                       outrel.r_offset += 4;
+                       bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+                       htab->etab.srelgot->reloc_count++;
+                       loc += sizeof (Elf32_External_Rela);
+                       bfd_put_32 (output_bfd, 0,
+                                   htab->etab.sgot->contents + cur_off);
+                       bfd_put_32 (output_bfd, 0,
+                                   htab->etab.sgot->contents + cur_off + 4);
                      }
                    else
                      {
@@ -4076,28 +4114,28 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                           to module 1, the executable.  */
                        bfd_put_32 (output_bfd, 1,
                                    htab->etab.sgot->contents + cur_off);
-                       bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
+                       bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
                                    htab->etab.sgot->contents + cur_off + 4);
                      }
-
-
                    cur_off += 8;
                  }
 
                if (tls_type & GOT_TLS_IE)
                  {
-                   if (need_relocs)
+                   if (need_relocs
+                       && !(bfd_link_executable (info)
+                            && SYMBOL_REFERENCES_LOCAL (info, &hh->eh)))
                      {
-                       outrel.r_offset = (cur_off
-                                          + htab->etab.sgot->output_section->vma
-                                          + htab->etab.sgot->output_offset);
-                       outrel.r_info = ELF32_R_INFO (indx, R_PARISC_TLS_TPREL32);
-
+                       outrel.r_offset
+                         = (cur_off
+                            + htab->etab.sgot->output_section->vma
+                            + htab->etab.sgot->output_offset);
+                       outrel.r_info = ELF32_R_INFO (indx,
+                                                     R_PARISC_TLS_TPREL32);
                        if (indx == 0)
                          outrel.r_addend = relocation - dtpoff_base (info);
                        else
                          outrel.r_addend = 0;
-
                        bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
                        htab->etab.srelgot->reloc_count++;
                        loc += sizeof (Elf32_External_Rela);
@@ -4105,7 +4143,6 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                    else
                      bfd_put_32 (output_bfd, tpoff (info, relocation),
                                  htab->etab.sgot->contents + cur_off);
-
                    cur_off += 4;
                  }
 
@@ -4115,6 +4152,35 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                  local_got_offsets[r_symndx] |= 1;
              }
 
+           if ((tls_type & GOT_NORMAL) != 0
+               && (tls_type & (GOT_TLS_GD | GOT_TLS_LDM | GOT_TLS_IE)) != 0)
+             {
+               if (hh != NULL)
+                 _bfd_error_handler (_("%s has both normal and TLS relocs"),
+                                     hh_name (hh));
+               else
+                 {
+                   Elf_Internal_Sym *isym
+                     = bfd_sym_from_r_symndx (&htab->sym_cache,
+                                              input_bfd, r_symndx);
+                   if (isym == NULL)
+                     return FALSE;
+                   sym_name
+                     = bfd_elf_string_from_elf_section (input_bfd,
+                                                        symtab_hdr->sh_link,
+                                                        isym->st_name);
+                   if (sym_name == NULL)
+                     return FALSE;
+                   if (*sym_name == '\0')
+                     sym_name = bfd_section_name (input_bfd, sym_sec);
+                   _bfd_error_handler
+                     (_("%B:%s has both normal and TLS relocs"),
+                      input_bfd, sym_name);
+                 }
+               bfd_set_error (bfd_error_bad_value);
+               return FALSE;
+             }
+
            if ((tls_type & GOT_TLS_GD)
                && r_type != R_PARISC_TLS_GD21L
                && r_type != R_PARISC_TLS_GD14R)
@@ -4257,43 +4323,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_NORMAL) != 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)
This page took 0.034951 seconds and 4 git commands to generate.