Rename u.weakdef and make it a circular list
[deliverable/binutils-gdb.git] / bfd / elf32-hppa.c
index 3a3a355d6e6f258bd8a48622b45611da245d01b2..01060dbef9c38e5123f001decc4addf484ee4969 100644 (file)
@@ -1,7 +1,5 @@
 /* BFD back-end for HP PA-RISC ELF files.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 1990-2017 Free Software Foundation, Inc.
 
    Original code by
        Center for Software Science
@@ -10,7 +8,7 @@
    Largely rewritten by Alan Modra <alan@linuxcare.com.au>
    Naming cleanup by Carlos O'Donell <carlos@systemhalted.org>
    TLS support written by Randolph Chung <tausq@debian.org>
+
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    Structure/Variable                  Prefix
    elf_link_hash_table                 "etab"
    elf_link_hash_entry                 "eh"
-   
+
    elf32_hppa_link_hash_table          "htab"
    elf32_hppa_link_hash_entry          "hh"
 
    bfd_hash_table                      "btab"
    bfd_hash_entry                      "bh"
-   
+
    bfd_hash_table containing stubs     "bstab"
    elf32_hppa_stub_hash_entry          "hsh"
 
    elf32_hppa_dyn_reloc_entry          "hdh"
-   
+
    Always remember to use GNU Coding Style. */
-                                         
+
 #define PLT_ENTRY_SIZE 8
 #define GOT_ENTRY_SIZE 4
 #define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
@@ -208,6 +206,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;
@@ -235,10 +242,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;
@@ -272,18 +276,10 @@ struct elf32_hppa_link_hash_table
 
   /* Assorted information used by elf32_hppa_size_stubs.  */
   unsigned int bfd_count;
-  int top_index;
+  unsigned int top_index;
   asection **input_list;
   Elf_Internal_Sym **all_local_syms;
 
-  /* Short-cuts to get to dynamic linker sections.  */
-  asection *sgot;
-  asection *srelgot;
-  asection *splt;
-  asection *srelplt;
-  asection *sdynbss;
-  asection *srelbss;
-
   /* Used during a final link to store the base of the text and data
      segments so that we can perform SEGREL relocations.  */
   bfd_vma text_segment_base;
@@ -409,6 +405,18 @@ hppa_link_hash_newfunc (struct bfd_hash_entry *entry,
   return entry;
 }
 
+/* Free the derived linker hash table.  */
+
+static void
+elf32_hppa_link_hash_table_free (bfd *obfd)
+{
+  struct elf32_hppa_link_hash_table *htab
+    = (struct elf32_hppa_link_hash_table *) obfd->link.hash;
+
+  bfd_hash_table_free (&htab->bstab);
+  _bfd_elf_link_hash_table_free (obfd);
+}
+
 /* Create the derived linker hash table.  The PA ELF port uses the derived
    hash table to keep information specific to the PA ELF linker (without
    using static variables).  */
@@ -419,7 +427,7 @@ elf32_hppa_link_hash_table_create (bfd *abfd)
   struct elf32_hppa_link_hash_table *htab;
   bfd_size_type amt = sizeof (*htab);
 
-  htab = bfd_malloc (amt);
+  htab = bfd_zmalloc (amt);
   if (htab == NULL)
     return NULL;
 
@@ -434,41 +442,27 @@ elf32_hppa_link_hash_table_create (bfd *abfd)
   /* Init the stub hash table too.  */
   if (!bfd_hash_table_init (&htab->bstab, stub_hash_newfunc,
                            sizeof (struct elf32_hppa_stub_hash_entry)))
-    return NULL;
+    {
+      _bfd_elf_link_hash_table_free (abfd);
+      return NULL;
+    }
+  htab->etab.root.hash_table_free = elf32_hppa_link_hash_table_free;
 
-  htab->stub_bfd = NULL;
-  htab->add_stub_section = NULL;
-  htab->layout_sections_again = NULL;
-  htab->stub_group = NULL;
-  htab->sgot = NULL;
-  htab->srelgot = NULL;
-  htab->splt = NULL;
-  htab->srelplt = NULL;
-  htab->sdynbss = NULL;
-  htab->srelbss = NULL;
   htab->text_segment_base = (bfd_vma) -1;
   htab->data_segment_base = (bfd_vma) -1;
-  htab->multi_subspace = 0;
-  htab->has_12bit_branch = 0;
-  htab->has_17bit_branch = 0;
-  htab->has_22bit_branch = 0;
-  htab->need_plt_stub = 0;
-  htab->sym_cache.abfd = NULL;
-  htab->tls_ldm_got.refcount = 0;
-
   return &htab->etab.root;
 }
 
-/* Free the derived linker hash table.  */
+/* Initialize the linker stubs BFD so that we can use it for linker
+   created dynamic sections.  */
 
-static void
-elf32_hppa_link_hash_table_free (struct bfd_link_hash_table *btab)
+void
+elf32_hppa_init_stub_bfd (bfd *abfd, struct bfd_link_info *info)
 {
-  struct elf32_hppa_link_hash_table *htab
-    = (struct elf32_hppa_link_hash_table *) btab;
+  struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info);
 
-  bfd_hash_table_free (&htab->bstab);
-  _bfd_generic_link_hash_table_free (btab);
+  elf_elfheader (abfd)->e_ident[EI_CLASS] = ELFCLASS32;
+  htab->etab.dynobj = abfd;
 }
 
 /* Build a name for an entry in the stub hash table.  */
@@ -595,9 +589,9 @@ hppa_add_stub (const char *stub_name,
                                      TRUE, FALSE);
   if (hsh == NULL)
     {
-      (*_bfd_error_handler) (_("%B: cannot create stub entry %s"),
-                            section->owner,
-                            stub_name);
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%B: cannot create stub entry %s"),
+                         section->owner, stub_name);
       return NULL;
     }
 
@@ -625,7 +619,7 @@ hppa_type_of_stub (asection *input_sec,
       && hh->eh.plt.offset != (bfd_vma) -1
       && hh->eh.dynindx != -1
       && !hh->plabel
-      && (info->shared
+      && (bfd_link_pic (info)
          || !hh->eh.def_regular
          || hh->eh.root.type == bfd_link_hash_defweak))
     {
@@ -784,9 +778,9 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
 
       off &= ~ (bfd_vma) 1;
       sym_value = (off
-                  + htab->splt->output_offset
-                  + htab->splt->output_section->vma
-                  - elf_gp (htab->splt->output_section->owner));
+                  + htab->etab.splt->output_offset
+                  + htab->etab.splt->output_section->vma
+                  - elf_gp (htab->etab.splt->output_section->owner));
 
       insn = ADDIL_DP;
 #if R19_STUBS
@@ -846,11 +840,12 @@ hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
          && (!htab->has_22bit_branch
              || sym_value - 8 + (1 << (22 + 1)) >= (1 << (22 + 2))))
        {
-         (*_bfd_error_handler)
-           (_("%B(%A+0x%lx): cannot reach %s, recompile with -ffunction-sections"),
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("%B(%A+%#Lx): cannot reach %s, recompile with -ffunction-sections"),
             hsh->target_section->owner,
             stub_sec,
-            (long) hsh->stub_offset,
+            hsh->stub_offset,
             hsh->bh_root.string);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
@@ -950,9 +945,9 @@ elf32_hppa_object_p (bfd *abfd)
   i_ehdrp = elf_elfheader (abfd);
   if (strcmp (bfd_get_target (abfd), "elf32-hppa-linux") == 0)
     {
-      /* GCC on hppa-linux produces binaries with OSABI=Linux,
+      /* GCC on hppa-linux produces binaries with OSABI=GNU,
         but the kernel produces corefiles with OSABI=SysV.  */
-      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX &&
+      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_GNU &&
          i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
        return FALSE;
     }
@@ -998,22 +993,13 @@ elf32_hppa_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   htab = hppa_link_hash_table (info);
   if (htab == NULL)
     return FALSE;
-  if (htab->splt != NULL)
+  if (htab->etab.splt != NULL)
     return TRUE;
 
   /* Call the generic code to do most of the work.  */
   if (! _bfd_elf_create_dynamic_sections (abfd, info))
     return FALSE;
 
-  htab->splt = bfd_get_section_by_name (abfd, ".plt");
-  htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
-
-  htab->sgot = bfd_get_section_by_name (abfd, ".got");
-  htab->srelgot = bfd_get_section_by_name (abfd, ".rela.got");
-
-  htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
-  htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
-
   /* hppa-linux needs _GLOBAL_OFFSET_TABLE_ to be visible from the main
      application, because __canonicalize_funcptr_for_compare needs it.  */
   eh = elf_hash_table (info)->hgot;
@@ -1076,19 +1062,20 @@ elf32_hppa_copy_indirect_symbol (struct bfd_link_info *info,
       /* If called to transfer flags for a weakdef during processing
         of elf_adjust_dynamic_symbol, don't copy non_got_ref.
         We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
-      eh_dir->ref_dynamic |= eh_ind->ref_dynamic;
+      if (eh_dir->versioned != versioned_hidden)
+       eh_dir->ref_dynamic |= eh_ind->ref_dynamic;
       eh_dir->ref_regular |= eh_ind->ref_regular;
       eh_dir->ref_regular_nonweak |= eh_ind->ref_regular_nonweak;
       eh_dir->needs_plt |= eh_ind->needs_plt;
     }
   else
     {
-      if (eh_ind->root.type == bfd_link_hash_indirect
-          && eh_dir->got.refcount <= 0)
-        {
-          hh_dir->tls_type = hh_ind->tls_type;
-          hh_ind->tls_type = GOT_UNKNOWN;
-        }
+      if (eh_ind->root.type == bfd_link_hash_indirect)
+       {
+         hh_dir->plabel |= hh_ind->plabel;
+         hh_dir->tls_type |= hh_ind->tls_type;
+         hh_ind->tls_type = GOT_UNKNOWN;
+       }
 
       _bfd_elf_link_hash_copy_indirect (info, eh_dir, eh_ind);
     }
@@ -1110,7 +1097,7 @@ hppa32_elf_local_refcounts (bfd *abfd)
 {
   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   bfd_signed_vma *local_refcounts;
-                  
+
   local_refcounts = elf_local_got_refcounts (abfd);
   if (local_refcounts == NULL)
     {
@@ -1151,9 +1138,8 @@ 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 (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   htab = hppa_link_hash_table (info);
@@ -1187,6 +1173,10 @@ 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);
@@ -1225,7 +1215,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:
@@ -1278,9 +1270,10 @@ elf32_hppa_check_relocs (bfd *abfd,
        case R_PARISC_DPREL14F: /* Used for gp rel data load/store.  */
        case R_PARISC_DPREL14R:
        case R_PARISC_DPREL21L:
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: relocation %s can not be used when making a shared object; recompile with -fPIC"),
                 abfd,
                 elf_hppa_howto_table[r_type].name);
@@ -1324,7 +1317,7 @@ elf32_hppa_check_relocs (bfd *abfd,
 
        case R_PARISC_TLS_IE21L:
        case R_PARISC_TLS_IE14R:
-         if (info->shared)
+         if (bfd_link_dll (info))
             info->flags |= DF_STATIC_TLS;
          need_entry = NEED_GOT;
          break;
@@ -1336,68 +1329,56 @@ 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;
            }
 
          /* Allocate space for a GOT entry, as well as a dynamic
             relocation for this entry.  */
-         if (htab->sgot == NULL)
+         if (htab->etab.sgot == NULL)
            {
-             if (htab->etab.dynobj == NULL)
-               htab->etab.dynobj = abfd;
              if (!elf32_hppa_create_dynamic_sections (htab->etab.dynobj, info))
                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;
            }
        }
 
@@ -1439,12 +1420,13 @@ 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
             dynamic.  */
-         if (hh != NULL && !info->shared)
+         if (hh != NULL && !bfd_link_pic (info))
            hh->eh.non_got_ref = 1;
 
          /* If we are creating a shared library then we need to copy
@@ -1475,16 +1457,14 @@ elf32_hppa_check_relocs (bfd *abfd,
             may need to keep relocations for symbols satisfied by a
             dynamic library if we manage to avoid copy relocs for the
             symbol.  */
-         if ((info->shared
-              && (sec->flags & SEC_ALLOC) != 0
+         if ((bfd_link_pic (info)
               && (IS_ABSOLUTE_RELOC (r_type)
                   || (hh != NULL
-                      && (!info->symbolic
+                      && (!SYMBOLIC_BIND (info, &hh->eh)
                           || hh->eh.root.type == bfd_link_hash_defweak
                           || !hh->eh.def_regular))))
              || (ELIMINATE_COPY_RELOCS
-                 && !info->shared
-                 && (sec->flags & SEC_ALLOC) != 0
+                 && !bfd_link_pic (info)
                  && hh != NULL
                  && (hh->eh.root.type == bfd_link_hash_defweak
                      || !hh->eh.def_regular)))
@@ -1496,9 +1476,6 @@ elf32_hppa_check_relocs (bfd *abfd,
                 this reloc.  */
              if (sreloc == NULL)
                {
-                 if (htab->etab.dynobj == NULL)
-                   htab->etab.dynobj = abfd;
-
                  sreloc = _bfd_elf_make_dynamic_reloc_section
                    (sec, htab->etab.dynobj, 2, abfd, /*rela?*/ TRUE);
 
@@ -1585,130 +1562,6 @@ elf32_hppa_gc_mark_hook (asection *sec,
   return _bfd_elf_gc_mark_hook (sec, info, rela, hh, sym);
 }
 
-/* Update the got and plt entry reference counts for the section being
-   removed.  */
-
-static bfd_boolean
-elf32_hppa_gc_sweep_hook (bfd *abfd,
-                         struct bfd_link_info *info ATTRIBUTE_UNUSED,
-                         asection *sec,
-                         const Elf_Internal_Rela *relocs)
-{
-  Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **eh_syms;
-  bfd_signed_vma *local_got_refcounts;
-  bfd_signed_vma *local_plt_refcounts;
-  const Elf_Internal_Rela *rela, *relend;
-  struct elf32_hppa_link_hash_table *htab;
-
-  if (info->relocatable)
-    return TRUE;
-
-  htab = hppa_link_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  elf_section_data (sec)->local_dynrel = NULL;
-
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  eh_syms = elf_sym_hashes (abfd);
-  local_got_refcounts = elf_local_got_refcounts (abfd);
-  local_plt_refcounts = local_got_refcounts;
-  if (local_plt_refcounts != NULL)
-    local_plt_refcounts += symtab_hdr->sh_info;
-
-  relend = relocs + sec->reloc_count;
-  for (rela = relocs; rela < relend; rela++)
-    {
-      unsigned long r_symndx;
-      unsigned int r_type;
-      struct elf_link_hash_entry *eh = NULL;
-
-      r_symndx = ELF32_R_SYM (rela->r_info);
-      if (r_symndx >= symtab_hdr->sh_info)
-       {
-         struct elf32_hppa_link_hash_entry *hh;
-         struct elf32_hppa_dyn_reloc_entry **hdh_pp;
-         struct elf32_hppa_dyn_reloc_entry *hdh_p;
-
-         eh = eh_syms[r_symndx - symtab_hdr->sh_info];
-         while (eh->root.type == bfd_link_hash_indirect
-                || eh->root.type == bfd_link_hash_warning)
-           eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
-         hh = hppa_elf_hash_entry (eh);
-
-         for (hdh_pp = &hh->dyn_relocs; (hdh_p = *hdh_pp) != NULL; hdh_pp = &hdh_p->hdh_next)
-           if (hdh_p->sec == sec)
-             {
-               /* Everything must go for SEC.  */
-               *hdh_pp = hdh_p->hdh_next;
-               break;
-             }
-       }
-
-      r_type = ELF32_R_TYPE (rela->r_info);
-      r_type = elf32_hppa_optimized_tls_reloc (info, r_type, eh != NULL);
-
-      switch (r_type)
-       {
-       case R_PARISC_DLTIND14F:
-       case R_PARISC_DLTIND14R:
-       case R_PARISC_DLTIND21L:
-       case R_PARISC_TLS_GD21L:
-       case R_PARISC_TLS_GD14R:
-       case R_PARISC_TLS_IE21L:
-       case R_PARISC_TLS_IE14R:
-         if (eh != NULL)
-           {
-             if (eh->got.refcount > 0)
-               eh->got.refcount -= 1;
-           }
-         else if (local_got_refcounts != NULL)
-           {
-             if (local_got_refcounts[r_symndx] > 0)
-               local_got_refcounts[r_symndx] -= 1;
-           }
-         break;
-
-       case R_PARISC_TLS_LDM21L:
-       case R_PARISC_TLS_LDM14R:
-         htab->tls_ldm_got.refcount -= 1;
-         break;
-
-       case R_PARISC_PCREL12F:
-       case R_PARISC_PCREL17C:
-       case R_PARISC_PCREL17F:
-       case R_PARISC_PCREL22F:
-         if (eh != NULL)
-           {
-             if (eh->plt.refcount > 0)
-               eh->plt.refcount -= 1;
-           }
-         break;
-
-       case R_PARISC_PLABEL14R:
-       case R_PARISC_PLABEL21L:
-       case R_PARISC_PLABEL32:
-         if (eh != NULL)
-           {
-             if (eh->plt.refcount > 0)
-               eh->plt.refcount -= 1;
-           }
-         else if (local_plt_refcounts != NULL)
-           {
-             if (local_plt_refcounts[r_symndx] > 0)
-               local_plt_refcounts[r_symndx] -= 1;
-           }
-         break;
-
-       default:
-         break;
-       }
-    }
-
-  return TRUE;
-}
-
 /* Support for core dump NOTE sections.  */
 
 static bfd_boolean
@@ -1724,10 +1577,10 @@ elf32_hppa_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 
       case 396:                /* Linux/hppa */
        /* pr_cursig */
-       elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+       elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
 
        /* pr_pid */
-       elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
+       elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24);
 
        /* pr_reg */
        offset = 72;
@@ -1750,9 +1603,9 @@ elf32_hppa_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
        return FALSE;
 
       case 124:                /* Linux/hppa elf_prpsinfo.  */
-       elf_tdata (abfd)->core_program
+       elf_tdata (abfd)->core->program
          = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
-       elf_tdata (abfd)->core_command
+       elf_tdata (abfd)->core->command
          = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
     }
 
@@ -1760,7 +1613,7 @@ elf32_hppa_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
      onto the end of the args in some (at least one anyway)
      implementations, so strip it off if it exists.  */
   {
-    char *command = elf_tdata (abfd)->core_command;
+    char *command = elf_tdata (abfd)->core->command;
     int n = strlen (command);
 
     if (0 < n && command[n - 1] == ' ')
@@ -1787,15 +1640,40 @@ elf32_hppa_hide_symbol (struct bfd_link_info *info,
          _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
                                  eh->dynstr_index);
        }
+
+      /* PR 16082: Remove version information from hidden symbol.  */
+      eh->verinfo.verdef = NULL;
+      eh->verinfo.vertree = NULL;
     }
 
-  if (! hppa_elf_hash_entry (eh)->plabel)
+  /* STT_GNU_IFUNC symbol must go through PLT.  */
+  if (! hppa_elf_hash_entry (eh)->plabel
+      && eh->type != STT_GNU_IFUNC)
     {
       eh->needs_plt = 0;
-      eh->plt = elf_hash_table (info)->init_plt_refcount;
+      eh->plt = elf_hash_table (info)->init_plt_offset;
     }
 }
 
+/* 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
@@ -1807,18 +1685,41 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
                                  struct elf_link_hash_entry *eh)
 {
   struct elf32_hppa_link_hash_table *htab;
-  asection *sec;
+  asection *sec, *srel;
 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later.  */
   if (eh->type == STT_FUNC
       || eh->needs_plt)
     {
-      if (eh->plt.refcount <= 0
-         || (eh->def_regular
-             && eh->root.type != bfd_link_hash_defweak
-             && ! hppa_elf_hash_entry (eh)->plabel
-             && (!info->shared || info->symbolic)))
+      /* 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
+        function symbol is local.  */
+      if (local)
+       eh->non_got_ref = 0;
+
+      /* 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
+              || local)
        {
          /* The .plt entry is not needed when:
             a) Garbage collection has removed all references to the
@@ -1827,11 +1728,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
@@ -1840,15 +1741,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;
     }
 
@@ -1859,7 +1759,7 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
      only references to the symbol are via the global offset table.
      For such cases we need not do anything here; the relocations will
      be handled correctly by relocate_section.  */
-  if (info->shared)
+  if (bfd_link_pic (info))
     return TRUE;
 
   /* If there are no references to this symbol that do not use the
@@ -1867,32 +1767,15 @@ 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
+      && !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;
-       }
-    }
-
-  if (eh->size == 0)
-    {
-      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
-                            eh->root.root.string);
       return TRUE;
     }
 
@@ -1913,15 +1796,45 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* We must generate a COPY reloc to tell the dynamic linker to
      copy the initial value out of the dynamic object and into the
      runtime process image.  */
-  if ((eh->root.u.def.section->flags & SEC_ALLOC) != 0)
+  if ((eh->root.u.def.section->flags & SEC_READONLY) != 0)
+    {
+      sec = htab->etab.sdynrelro;
+      srel = htab->etab.sreldynrelro;
+    }
+  else
     {
-      htab->srelbss->size += sizeof (Elf32_External_Rela);
+      sec = htab->etab.sdynbss;
+      srel = htab->etab.srelbss;
+    }
+  if ((eh->root.u.def.section->flags & SEC_ALLOC) != 0 && eh->size != 0)
+    {
+      srel->size += sizeof (Elf32_External_Rela);
       eh->needs_copy = 1;
     }
 
-  sec = htab->sdynbss;
+  /* We no longer want dyn_relocs.  */
+  eh->non_got_ref = 0;
+  return _bfd_elf_adjust_dynamic_copy (info, eh, sec);
+}
+
+/* If EH is undefined, make it dynamic if that makes sense.  */
+
+static bfd_boolean
+ensure_undef_dynamic (struct bfd_link_info *info,
+                     struct elf_link_hash_entry *eh)
+{
+  struct elf_link_hash_table *htab = elf_hash_table (info);
 
-  return _bfd_elf_adjust_dynamic_copy (eh, sec);
+  if (htab->dynamic_sections_created
+      && (eh->root.type == bfd_link_hash_undefweak
+         || eh->root.type == bfd_link_hash_undefined)
+      && eh->dynindx == -1
+      && !eh->forced_local
+      && eh->type != STT_PARISC_MILLI
+      && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh)
+      && ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT)
+    return bfd_elf_link_record_dynamic_symbol (info, eh);
+  return TRUE;
 }
 
 /* Allocate space in the .plt for entries that won't have relocations.
@@ -1938,9 +1851,6 @@ allocate_plt_static (struct elf_link_hash_entry *eh, void *inf)
   if (eh->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (eh->root.type == bfd_link_hash_warning)
-    eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
-
   info = (struct bfd_link_info *) inf;
   hh = hppa_elf_hash_entry (eh);
   htab = hppa_link_hash_table (info);
@@ -1950,32 +1860,27 @@ allocate_plt_static (struct elf_link_hash_entry *eh, void *inf)
   if (htab->etab.dynamic_sections_created
       && eh->plt.refcount > 0)
     {
-      /* Make sure this symbol is output as a dynamic symbol.
-        Undefined weak syms won't yet be marked as dynamic.  */
-      if (eh->dynindx == -1
-         && !eh->forced_local
-         && eh->type != STT_PARISC_MILLI)
-       {
-         if (! bfd_elf_link_record_dynamic_symbol (info, eh))
-           return FALSE;
-       }
+      if (!ensure_undef_dynamic (info, eh))
+       return FALSE;
 
-      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, eh))
+      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), eh))
        {
          /* Allocate these later.  From this point on, h->plabel
             means that the plt entry is only used by a plabel.
             We'll be using a normal plt entry for this symbol, so
             clear the plabel indicator.  */
-         
+
          hh->plabel = 0;
        }
       else if (hh->plabel)
        {
          /* Make an entry in the .plt section for plabel references
             that won't have a .plt entry for other reasons.  */
-         sec = htab->splt;
+         sec = htab->etab.splt;
          eh->plt.offset = sec->size;
          sec->size += PLT_ENTRY_SIZE;
+         if (bfd_link_pic (info))
+           htab->etab.srelplt->size += sizeof (Elf32_External_Rela);
        }
       else
        {
@@ -1993,6 +1898,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.  */
 
@@ -2008,75 +1946,76 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
   if (eh->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (eh->root.type == bfd_link_hash_warning)
-    eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
-
   info = inf;
   htab = hppa_link_hash_table (info);
   if (htab == NULL)
     return FALSE;
 
   hh = hppa_elf_hash_entry (eh);
-  
+
   if (htab->etab.dynamic_sections_created
       && eh->plt.offset != (bfd_vma) -1
       && !hh->plabel
       && eh->plt.refcount > 0)
     {
       /* Make an entry in the .plt section.  */
-      sec = htab->splt;
+      sec = htab->etab.splt;
       eh->plt.offset = sec->size;
       sec->size += PLT_ENTRY_SIZE;
 
       /* We also need to make an entry in the .rela.plt section.  */
-      htab->srelplt->size += sizeof (Elf32_External_Rela);
+      htab->etab.srelplt->size += sizeof (Elf32_External_Rela);
       htab->need_plt_stub = 1;
     }
 
   if (eh->got.refcount > 0)
     {
-      /* Make sure this symbol is output as a dynamic symbol.
-        Undefined weak syms won't yet be marked as dynamic.  */
-      if (eh->dynindx == -1
-         && !eh->forced_local
-         && eh->type != STT_PARISC_MILLI)
-       {
-         if (! bfd_elf_link_record_dynamic_symbol (info, eh))
-           return FALSE;
-       }
+      unsigned int need;
+
+      if (!ensure_undef_dynamic (info, eh))
+       return FALSE;
 
-      sec = htab->sgot;
+      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
-         && (info->shared
+         && (bfd_link_pic (info)
              || (eh->dynindx != -1
-                 && !eh->forced_local)))
+                 && !SYMBOL_REFERENCES_LOCAL (info, eh)))
+         && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
        {
-         htab->srelgot->size += sizeof (Elf32_External_Rela);
-         if ((hh->tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
-           htab->srelgot->size += 2 * sizeof (Elf32_External_Rela);
-         else if ((hh->tls_type & GOT_TLS_GD) == GOT_TLS_GD)
-           htab->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;
+    {
+      eh->non_got_ref = 0;
+      return TRUE;
+    }
 
   /* If this is a -Bsymbolic shared link, then we need to discard all
      space allocated for dynamic pc-relative relocs against symbols
      defined in a regular object.  For the normal shared case, discard
      space for relocs that have become local due to symbol visibility
      changes.  */
-  if (info->shared)
+  if (bfd_link_pic (info))
     {
 #if RELATIVE_DYNRELOCS
       if (SYMBOL_CALLS_LOCAL (info, eh))
@@ -2095,58 +2034,37 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
        }
 #endif
 
-      /* Also discard relocs on undefined weak syms with non-default
-        visibility.  */
-      if (hh->dyn_relocs != NULL
-         && eh->root.type == bfd_link_hash_undefweak)
+      if (hh->dyn_relocs != NULL)
        {
-         if (ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT)
-           hh->dyn_relocs = NULL;
-
-         /* Make sure undefined weak symbols are output as a dynamic
-            symbol in PIEs.  */
-         else if (eh->dynindx == -1
-                  && !eh->forced_local)
-           {
-             if (! bfd_elf_link_record_dynamic_symbol (info, eh))
-               return FALSE;
-           }
+         if (!ensure_undef_dynamic (info, eh))
+           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->non_got_ref
+         && !eh->def_regular
+         && !ELF_COMMON_DEF_P (eh))
        {
-         /* Make sure this symbol is output as a dynamic symbol.
-            Undefined weak syms won't yet be marked as dynamic.  */
-         if (eh->dynindx == -1
-             && !eh->forced_local
-             && eh->type != STT_PARISC_MILLI)
+         if (!ensure_undef_dynamic (info, eh))
+           return FALSE;
+
+         if (eh->dynindx == -1)
            {
-             if (! bfd_elf_link_record_dynamic_symbol (info, eh))
-               return FALSE;
+             eh->non_got_ref = 0;
+             hh->dyn_relocs = NULL;
            }
-
-         /* If that succeeded, we know we'll be keeping all the
-            relocs.  */
-         if (eh->dynindx != -1)
-           goto keep;
        }
-
-      hh->dyn_relocs = NULL;
-      return TRUE;
-
-    keep: ;
+      else
+       {
+         eh->non_got_ref = 0;
+         hh->dyn_relocs = NULL;
+       }
     }
 
   /* Finally, allocate space.  */
@@ -2170,9 +2088,6 @@ static bfd_boolean
 clobber_millicode_symbols (struct elf_link_hash_entry *eh,
                           struct bfd_link_info *info)
 {
-  if (eh->root.type == bfd_link_hash_warning)
-    eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
-
   if (eh->type == STT_PARISC_MILLI
       && !eh->forced_local)
     {
@@ -2181,31 +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;
 
-  if (eh->root.type == bfd_link_hash_warning)
-    eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
+  if (eh->root.type == bfd_link_hash_indirect)
+    return TRUE;
 
-  hh = hppa_elf_hash_entry (eh);
-  for (hdh_p = hh->dyn_relocs; hdh_p != NULL; hdh_p = hdh_p->hdh_next)
+  sec = readonly_dynrelocs (eh);
+  if (sec != NULL)
     {
-      asection *sec = hdh_p->sec->output_section;
+      struct bfd_link_info *info = (struct bfd_link_info *) inf;
 
-      if (sec != NULL && (sec->flags & SEC_READONLY) != 0)
-       {
-         struct bfd_link_info *info = inf;
+      info->flags |= DF_TEXTREL;
+      info->callbacks->minfo
+       (_("%B: dynamic relocation in read-only section `%A'\n"),
+        sec->owner, sec);
 
-         info->flags |= DF_TEXTREL;
-
-         /* Not an error, just cut short the traversal.  */
-         return FALSE;
-       }
+      /* Not an error, just cut short the traversal.  */
+      return FALSE;
     }
   return TRUE;
 }
@@ -2233,9 +2146,9 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (htab->etab.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (info->executable)
+      if (bfd_link_executable (info) && !info->nointerp)
        {
-         sec = bfd_get_section_by_name (dynobj, ".interp");
+         sec = bfd_get_linker_section (dynobj, ".interp");
          if (sec == NULL)
            abort ();
          sec->size = sizeof ELF_DYNAMIC_INTERPRETER;
@@ -2250,7 +2163,7 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* Set up .got and .plt offsets for local syms, and space for local
      dynamic relocs.  */
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     {
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
@@ -2299,26 +2212,23 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = hppa_elf_local_got_tls_type (ibfd);
-      sec = htab->sgot;
-      srel = htab->srelgot;
+      sec = htab->etab.sgot;
+      srel = htab->etab.srelgot;
       for (; local_got < end_local_got; ++local_got)
        {
          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;
-             if (info->shared) 
-               {
-                 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);
-               }
+             need = got_entries_needed (*local_tls_type);
+             sec->size += need;
+             if (bfd_link_pic (info))
+               {
+                 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;
@@ -2336,15 +2246,15 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
       else
        {
-         sec = htab->splt;
-         srel = htab->srelplt;
+         sec = htab->etab.splt;
+         srel = htab->etab.srelplt;
          for (; local_plt < end_local_plt; ++local_plt)
            {
              if (*local_plt > 0)
                {
                  *local_plt = sec->size;
                  sec->size += PLT_ENTRY_SIZE;
-                 if (info->shared)
+                 if (bfd_link_pic (info))
                    srel->size += sizeof (Elf32_External_Rela);
                }
              else
@@ -2352,14 +2262,14 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
            }
        }
     }
-  
+
   if (htab->tls_ldm_got.refcount > 0)
     {
-      /* Allocate 2 got entries and 1 dynamic reloc for 
+      /* Allocate 2 got entries and 1 dynamic reloc for
          R_PARISC_TLS_DTPMOD32 relocs.  */
-      htab->tls_ldm_got.offset = htab->sgot->size;
-      htab->sgot->size += (GOT_ENTRY_SIZE * 2);
-      htab->srelgot->size += sizeof (Elf32_External_Rela);
+      htab->tls_ldm_got.offset = htab->etab.sgot->size;
+      htab->etab.sgot->size += (GOT_ENTRY_SIZE * 2);
+      htab->etab.srelgot->size += sizeof (Elf32_External_Rela);
     }
   else
     htab->tls_ldm_got.offset = -1;
@@ -2382,25 +2292,26 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       if ((sec->flags & SEC_LINKER_CREATED) == 0)
        continue;
 
-      if (sec == htab->splt)
+      if (sec == htab->etab.splt)
        {
          if (htab->need_plt_stub)
            {
              /* Make space for the plt stub at the end of the .plt
                 section.  We want this stub right at the end, up
                 against the .got section.  */
-             int gotalign = bfd_section_alignment (dynobj, htab->sgot);
+             int gotalign = bfd_section_alignment (dynobj, htab->etab.sgot);
              int pltalign = bfd_section_alignment (dynobj, sec);
              bfd_size_type mask;
 
              if (gotalign > pltalign)
-               bfd_set_section_alignment (dynobj, sec, gotalign);
+               (void) bfd_set_section_alignment (dynobj, sec, gotalign);
              mask = ((bfd_size_type) 1 << gotalign) - 1;
              sec->size = (sec->size + sizeof (plt_stub) + mask) & ~mask;
            }
        }
-      else if (sec == htab->sgot
-              || sec == htab->sdynbss)
+      else if (sec == htab->etab.sgot
+              || sec == htab->etab.sdynbss
+              || sec == htab->etab.sdynrelro)
        ;
       else if (CONST_STRNEQ (bfd_get_section_name (dynobj, sec), ".rela"))
        {
@@ -2408,7 +2319,7 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
            {
              /* Remember whether there are any reloc sections other
                 than .rela.plt.  */
-             if (sec != htab->srelplt)
+             if (sec != htab->etab.srelplt)
                relocs = TRUE;
 
              /* We use the reloc_count field as a counter if we need
@@ -2464,13 +2375,13 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         must add the entries now so that we get the correct size for
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
-      if (info->executable)
+      if (bfd_link_executable (info))
        {
          if (!add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
        }
 
-      if (htab->srelplt->size != 0)
+      if (htab->etab.srelplt->size != 0)
        {
          if (!add_dynamic_entry (DT_PLTRELSZ, 0)
              || !add_dynamic_entry (DT_PLTREL, DT_RELA)
@@ -2488,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)
            {
@@ -2513,7 +2424,7 @@ elf32_hppa_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
 {
   bfd *input_bfd;
   unsigned int bfd_count;
-  int top_id, top_index;
+  unsigned int top_id, top_index;
   asection *section;
   asection **input_list, **list;
   bfd_size_type amt;
@@ -2525,7 +2436,7 @@ elf32_hppa_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
   /* Count the number of input BFDs and find the top input section id.  */
   for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
        input_bfd != NULL;
-       input_bfd = input_bfd->link_next)
+       input_bfd = input_bfd->link.next)
     {
       bfd_count += 1;
       for (section = input_bfd->sections;
@@ -2716,7 +2627,7 @@ get_local_syms (bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *info)
      export stubs.  */
   for (bfd_indx = 0;
        input_bfd != NULL;
-       input_bfd = input_bfd->link_next, bfd_indx++)
+       input_bfd = input_bfd->link.next, bfd_indx++)
     {
       Elf_Internal_Shdr *symtab_hdr;
 
@@ -2740,7 +2651,7 @@ get_local_syms (bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *info)
 
       all_local_syms[bfd_indx] = local_syms;
 
-      if (info->shared && htab->multi_subspace)
+      if (bfd_link_pic (info) && htab->multi_subspace)
        {
          struct elf_link_hash_entry **eh_syms;
          struct elf_link_hash_entry **eh_symend;
@@ -2800,9 +2711,9 @@ get_local_syms (bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *info)
                    }
                  else
                    {
-                     (*_bfd_error_handler) (_("%B: duplicate export stub %s"),
-                                            input_bfd,
-                                            stub_name);
+                     /* xgettext:c-format */
+                     _bfd_error_handler (_("%B: duplicate export stub %s"),
+                                         input_bfd, stub_name);
                    }
                }
            }
@@ -2890,7 +2801,7 @@ elf32_hppa_size_stubs
 
       for (input_bfd = info->input_bfds, bfd_indx = 0;
           input_bfd != NULL;
-          input_bfd = input_bfd->link_next, bfd_indx++)
+          input_bfd = input_bfd->link.next, bfd_indx++)
        {
          Elf_Internal_Shdr *symtab_hdr;
          asection *section;
@@ -3012,7 +2923,7 @@ elf32_hppa_size_stubs
                        }
                      else if (hh->eh.root.type == bfd_link_hash_undefweak)
                        {
-                         if (! info->shared)
+                         if (! bfd_link_pic (info))
                            continue;
                        }
                      else if (hh->eh.root.type == bfd_link_hash_undefined)
@@ -3064,7 +2975,7 @@ elf32_hppa_size_stubs
                  hsh->target_value = sym_value;
                  hsh->target_section = sym_sec;
                  hsh->stub_type = stub_type;
-                 if (info->shared)
+                 if (bfd_link_pic (info))
                    {
                      if (stub_type == hppa_stub_import)
                        hsh->stub_type = hppa_stub_import_shared;
@@ -3089,7 +3000,8 @@ elf32_hppa_size_stubs
       for (stub_sec = htab->stub_bfd->sections;
           stub_sec != NULL;
           stub_sec = stub_sec->next)
-       stub_sec->size = 0;
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+         stub_sec->size = 0;
 
       bfd_hash_traverse (&htab->bstab, hppa_size_one_stub, htab);
 
@@ -3115,13 +3027,8 @@ elf32_hppa_set_gp (bfd *abfd, struct bfd_link_info *info)
   struct bfd_link_hash_entry *h;
   asection *sec = NULL;
   bfd_vma gp_val = 0;
-  struct elf32_hppa_link_hash_table *htab;
 
-  htab = hppa_link_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  h = bfd_link_hash_lookup (&htab->etab.root, "$global$", FALSE, FALSE, FALSE);
+  h = bfd_link_hash_lookup (info->hash, "$global$", FALSE, FALSE, FALSE);
 
   if (h != NULL
       && (h->type == bfd_link_hash_defined
@@ -3184,10 +3091,13 @@ elf32_hppa_set_gp (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  if (sec != NULL && sec->output_section != NULL)
-    gp_val += sec->output_section->vma + sec->output_offset;
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+    {
+      if (sec != NULL && sec->output_section != NULL)
+       gp_val += sec->output_section->vma + sec->output_offset;
 
-  elf_gp (abfd) = gp_val;
+      elf_gp (abfd) = gp_val;
+    }
   return TRUE;
 }
 
@@ -3211,16 +3121,15 @@ elf32_hppa_build_stubs (struct bfd_link_info *info)
   for (stub_sec = htab->stub_bfd->sections;
        stub_sec != NULL;
        stub_sec = stub_sec->next)
-    {
-      bfd_size_type size;
-
-      /* Allocate memory to hold the linker stubs.  */
-      size = stub_sec->size;
-      stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
-      if (stub_sec->contents == NULL && size != 0)
-       return FALSE;
-      stub_sec->size = 0;
-    }
+    if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
+       && stub_sec->size != 0)
+      {
+       /* Allocate memory to hold the linker stubs.  */
+       stub_sec->contents = bfd_zalloc (htab->stub_bfd, stub_sec->size);
+       if (stub_sec->contents == NULL)
+         return FALSE;
+       stub_sec->size = 0;
+      }
 
   /* Build the stubs as directed by the stub hash table.  */
   table = &htab->bstab;
@@ -3230,7 +3139,7 @@ elf32_hppa_build_stubs (struct bfd_link_info *info)
 }
 
 /* Return the base vma address which should be subtracted from the real
-   address when resolving a dtpoff relocation.  
+   address when resolving a dtpoff relocation.
    This is PT_TLS segment p_vaddr.  */
 
 static bfd_vma
@@ -3252,9 +3161,9 @@ tpoff (struct bfd_link_info *info, bfd_vma address)
   /* If tls_sec is NULL, we should have signalled an error already.  */
   if (htab->tls_sec == NULL)
     return 0;
-  /* hppa TLS ABI is variant I and static TLS block start just after 
+  /* hppa TLS ABI is variant I and static TLS block start just after
      tcbhead structure which has 2 pointer fields.  */
-  return (address - htab->tls_sec->vma 
+  return (address - htab->tls_sec->vma
          + align_power ((bfd_vma) 8, htab->tls_sec->alignment_power));
 }
 
@@ -3263,13 +3172,22 @@ tpoff (struct bfd_link_info *info, bfd_vma address)
 static bfd_boolean
 elf32_hppa_final_link (bfd *abfd, struct bfd_link_info *info)
 {
+  struct stat buf;
+
   /* Invoke the regular ELF linker to do all the work.  */
   if (!bfd_elf_final_link (abfd, info))
     return FALSE;
 
   /* If we're producing a final executable, sort the contents of the
      unwind section.  */
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
+    return TRUE;
+
+  /* Do not attempt to sort non-regular files.  This is here
+     especially for configure scripts and kernel builds which run
+     tests with "ld [...] -o /dev/null".  */
+  if (stat (abfd->filename, &buf) != 0
+      || !S_ISREG(buf.st_mode))
     return TRUE;
 
   return elf_hppa_sort_unwind (abfd);
@@ -3333,7 +3251,7 @@ final_link_relocate (asection *input_section,
   bfd_signed_vma addend = rela->r_addend;
   bfd_vma location;
   struct elf32_hppa_stub_hash_entry *hsh = NULL;
-  int val;  
+  int val;
 
   if (r_type == R_PARISC_NONE)
     return bfd_reloc_ok;
@@ -3347,15 +3265,21 @@ final_link_relocate (asection *input_section,
 
   /* If we are not building a shared library, convert DLTIND relocs to
      DPREL relocs.  */
-  if (!info->shared)
+  if (!bfd_link_pic (info))
     {
       switch (r_type)
        {
          case R_PARISC_DLTIND21L:
+         case R_PARISC_TLS_GD21L:
+         case R_PARISC_TLS_LDM21L:
+         case R_PARISC_TLS_IE21L:
            r_type = R_PARISC_DPREL21L;
            break;
 
          case R_PARISC_DLTIND14R:
+         case R_PARISC_TLS_GD14R:
+         case R_PARISC_TLS_LDM14R:
+         case R_PARISC_TLS_IE14R:
            r_type = R_PARISC_DPREL14R;
            break;
 
@@ -3378,7 +3302,7 @@ final_link_relocate (asection *input_section,
              && hh->eh.plt.offset != (bfd_vma) -1
              && hh->eh.dynindx != -1
              && !hh->plabel
-             && (info->shared
+             && (bfd_link_pic (info)
                  || !hh->eh.def_regular
                  || hh->eh.root.type == bfd_link_hash_defweak)))
        {
@@ -3421,53 +3345,49 @@ final_link_relocate (asection *input_section,
     case R_PARISC_DPREL21L:
     case R_PARISC_DPREL14R:
     case R_PARISC_DPREL14F:
-    case R_PARISC_TLS_GD21L:
-    case R_PARISC_TLS_LDM21L:
-    case R_PARISC_TLS_IE21L:
       /* Convert instructions that use the linkage table pointer (r19) to
         instructions that use the global data pointer (dp).  This is the
         most efficient way of using PIC code in an incomplete executable,
         but the user must follow the standard runtime conventions for
         accessing data for this to work.  */
-      if (orig_r_type == R_PARISC_DLTIND21L
-         || (!info->shared
-             && (r_type == R_PARISC_TLS_GD21L
-                 || r_type == R_PARISC_TLS_LDM21L
-                 || r_type == R_PARISC_TLS_IE21L)))
-       {
-         /* Convert addil instructions if the original reloc was a
-            DLTIND21L.  GCC sometimes uses a register other than r19 for
-            the operation, so we must convert any addil instruction
-            that uses this relocation.  */
-         if ((insn & 0xfc000000) == ((int) OP_ADDIL << 26))
-           insn = ADDIL_DP;
-         else
-           /* We must have a ldil instruction.  It's too hard to find
-              and convert the associated add instruction, so issue an
-              error.  */
-           (*_bfd_error_handler)
-             (_("%B(%A+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link"),
-              input_bfd,
-              input_section,
-              (long) offset,
-              howto->name,
-              insn);
-       }
-      else if (orig_r_type == R_PARISC_DLTIND14F)
+      if (orig_r_type != r_type)
        {
-         /* This must be a format 1 load/store.  Change the base
-            register to dp.  */
-         insn = (insn & 0xfc1ffff) | (27 << 21);
+         if (r_type == R_PARISC_DPREL21L)
+           {
+             /* GCC sometimes uses a register other than r19 for the
+                operation, so we must convert any addil instruction
+                that uses this relocation.  */
+             if ((insn & 0xfc000000) == ((int) OP_ADDIL << 26))
+               insn = ADDIL_DP;
+             else
+               /* We must have a ldil instruction.  It's too hard to find
+                  and convert the associated add instruction, so issue an
+                  error.  */
+               _bfd_error_handler
+                 /* xgettext:c-format */
+                 (_("%B(%A+%#Lx): %s fixup for insn %#x is not supported in a non-shared link"),
+                  input_bfd,
+                  input_section,
+                  offset,
+                  howto->name,
+                  insn);
+           }
+         else if (r_type == R_PARISC_DPREL14F)
+           {
+             /* This must be a format 1 load/store.  Change the base
+                register to dp.  */
+             insn = (insn & 0xfc1ffff) | (27 << 21);
+           }
        }
 
-    /* For all the DP relative relocations, we need to examine the symbol's
-       section.  If it has no section or if it's a code section, then
-       "data pointer relative" makes no sense.  In that case we don't
-       adjust the "value", and for 21 bit addil instructions, we change the
-       source addend register from %dp to %r0.  This situation commonly
-       arises for undefined weak symbols and when a variable's "constness"
-       is declared differently from the way the variable is defined.  For
-       instance: "extern int foo" with foo defined as "const int foo".  */
+      /* For all the DP relative relocations, we need to examine the symbol's
+        section.  If it has no section or if it's a code section, then
+        "data pointer relative" makes no sense.  In that case we don't
+        adjust the "value", and for 21 bit addil instructions, we change the
+        source addend register from %dp to %r0.  This situation commonly
+        arises for undefined weak symbols and when a variable's "constness"
+        is declared differently from the way the variable is defined.  For
+        instance: "extern int foo" with foo defined as "const int foo".  */
       if (sym_sec == NULL || (sym_sec->flags & SEC_CODE) != 0)
        {
          if ((insn & ((0x3f << 26) | (0x1f << 21)))
@@ -3484,6 +3404,9 @@ final_link_relocate (asection *input_section,
     case R_PARISC_DLTIND21L:
     case R_PARISC_DLTIND14R:
     case R_PARISC_DLTIND14F:
+    case R_PARISC_TLS_GD21L:
+    case R_PARISC_TLS_LDM21L:
+    case R_PARISC_TLS_IE21L:
     case R_PARISC_TLS_GD14R:
     case R_PARISC_TLS_LDM14R:
     case R_PARISC_TLS_IE14R:
@@ -3606,11 +3529,12 @@ final_link_relocate (asection *input_section,
   if (max_branch_offset != 0
       && value + addend + max_branch_offset >= 2*max_branch_offset)
     {
-      (*_bfd_error_handler)
-       (_("%B(%A+0x%lx): cannot reach %s, recompile with -ffunction-sections"),
+      _bfd_error_handler
+       /* xgettext:c-format */
+       (_("%B(%A+%#Lx): cannot reach %s, recompile with -ffunction-sections"),
         input_bfd,
         input_section,
-        (long) offset,
+        offset,
         hsh->bh_root.string);
       bfd_set_error (bfd_error_bad_value);
       return bfd_reloc_notsupported;
@@ -3712,15 +3636,16 @@ elf32_hppa_relocate_section (bfd *output_bfd,
       else
        {
          struct elf_link_hash_entry *eh;
-         bfd_boolean unresolved_reloc;
+         bfd_boolean unresolved_reloc, ignored;
          struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rela,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   eh, sym_sec, relocation,
-                                  unresolved_reloc, warned_undef);
+                                  unresolved_reloc, warned_undef,
+                                  ignored);
 
-         if (!info->relocatable
+         if (!bfd_link_relocatable (info)
              && relocation == 0
              && eh->root.type != bfd_link_hash_defined
              && eh->root.type != bfd_link_hash_defweak
@@ -3730,30 +3655,22 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                  && ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT
                  && eh->type == STT_PARISC_MILLI)
                {
-                 if (! info->callbacks->undefined_symbol
-                     (info, eh_name (eh), input_bfd,
-                      input_section, rela->r_offset, FALSE))
-                   return FALSE;
+                 (*info->callbacks->undefined_symbol)
+                   (info, eh_name (eh), input_bfd,
+                    input_section, rela->r_offset, FALSE);
                  warned_undef = TRUE;
                }
            }
          hh = hppa_elf_hash_entry (eh);
        }
 
-      if (sym_sec != NULL && elf_discarded_section (sym_sec))
-       {
-         /* For relocs against symbols from removed linkonce
-            sections, or sections discarded by a linker script,
-            we just want the section contents zeroed.  Avoid any
-            special processing.  */
-         _bfd_clear_contents (elf_hppa_howto_table + r_type, input_bfd,
-                              contents + rela->r_offset);
-         rela->r_info = 0;
-         rela->r_addend = 0;
-         continue;
-       }
+      if (sym_sec != NULL && discarded_section (sym_sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rela, 1, relend,
+                                        elf_hppa_howto_table + r_type, 0,
+                                        contents);
 
-      if (info->relocatable)
+      if (bfd_link_relocatable (info))
        continue;
 
       /* Do any required modifications to the relocation value, and
@@ -3767,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.  */
@@ -3777,8 +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, info->shared,
-                                                      &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
@@ -3791,7 +3715,7 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                    else
                      {
                        hh->eh.got.offset |= 1;
-                       do_got = 1;
+                       do_got = TRUE;
                      }
                  }
              }
@@ -3811,24 +3735,24 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                else
                  {
                    local_got_offsets[r_symndx] |= 1;
-                   do_got = 1;
+                   do_got = TRUE;
                  }
              }
 
            if (do_got)
              {
-               if (info->shared)
+               if (reloc)
                  {
                    /* Output a dynamic relocation for this GOT entry.
                       In this case it is relative to the base of the
                       object because the symbol index is zero.  */
                    Elf_Internal_Rela outrel;
                    bfd_byte *loc;
-                   asection *sec = htab->srelgot;
+                   asection *sec = htab->etab.srelgot;
 
                    outrel.r_offset = (off
-                                      + htab->sgot->output_offset
-                                      + htab->sgot->output_section->vma);
+                                      + htab->etab.sgot->output_offset
+                                      + htab->etab.sgot->output_section->vma);
                    outrel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
                    outrel.r_addend = relocation;
                    loc = sec->contents;
@@ -3837,7 +3761,7 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                  }
                else
                  bfd_put_32 (output_bfd, relocation,
-                             htab->sgot->contents + off);
+                             htab->etab.sgot->contents + off);
              }
 
            if (off >= (bfd_vma) -2)
@@ -3845,8 +3769,8 @@ elf32_hppa_relocate_section (bfd *output_bfd,
 
            /* Add the base of the GOT to the relocation value.  */
            relocation = (off
-                         + htab->sgot->output_offset
-                         + htab->sgot->output_section->vma);
+                         + htab->etab.sgot->output_offset
+                         + htab->etab.sgot->output_section->vma);
          }
          break;
 
@@ -3869,7 +3793,8 @@ elf32_hppa_relocate_section (bfd *output_bfd,
              if (hh != NULL)
                {
                  off = hh->eh.plt.offset;
-                 if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared,
+                 if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (1,
+                                                        bfd_link_pic (info),
                                                         &hh->eh))
                    {
                      /* In a non-shared link, adjust_dynamic_symbols
@@ -3908,17 +3833,17 @@ elf32_hppa_relocate_section (bfd *output_bfd,
 
              if (do_plt)
                {
-                 if (info->shared)
+                 if (bfd_link_pic (info))
                    {
                      /* Output a dynamic IPLT relocation for this
                         PLT entry.  */
                      Elf_Internal_Rela outrel;
                      bfd_byte *loc;
-                     asection *s = htab->srelplt;
+                     asection *s = htab->etab.srelplt;
 
                      outrel.r_offset = (off
-                                        + htab->splt->output_offset
-                                        + htab->splt->output_section->vma);
+                                        + htab->etab.splt->output_offset
+                                        + htab->etab.splt->output_section->vma);
                      outrel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT);
                      outrel.r_addend = relocation;
                      loc = s->contents;
@@ -3929,10 +3854,10 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                    {
                      bfd_put_32 (output_bfd,
                                  relocation,
-                                 htab->splt->contents + off);
+                                 htab->etab.splt->contents + off);
                      bfd_put_32 (output_bfd,
-                                 elf_gp (htab->splt->output_section->owner),
-                                 htab->splt->contents + off + 4);
+                                 elf_gp (htab->etab.splt->output_section->owner),
+                                 htab->etab.splt->contents + off + 4);
                    }
                }
 
@@ -3950,13 +3875,13 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                      && hh->eh.root.type != bfd_link_hash_undefined))
                {
                  relocation = (off
-                               + htab->splt->output_offset
-                               + htab->splt->output_section->vma
+                               + htab->etab.splt->output_offset
+                               + htab->etab.splt->output_section->vma
                                + 2);
                }
              plabel = 1;
            }
-         /* Fall through and possibly emit a dynamic relocation.  */
+         /* Fall through.  */
 
        case R_PARISC_DIR17F:
        case R_PARISC_DIR17R:
@@ -3975,28 +3900,18 @@ 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.  */
-         if ((info->shared
-              && (hh == NULL
-                  || ELF_ST_VISIBILITY (hh->eh.other) == STV_DEFAULT
-                  || hh->eh.root.type != bfd_link_hash_undefweak)
+            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)))
-             || (!info->shared
+             || (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.non_got_ref))
            {
              Elf_Internal_Rela outrel;
              bfd_boolean skip;
@@ -4015,7 +3930,7 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                      || outrel.r_offset == (bfd_vma) -2);
              outrel.r_offset += (input_section->output_offset
                                  + input_section->output_section->vma);
-                     
+
              if (skip)
                {
                  memset (&outrel, 0, sizeof (outrel));
@@ -4024,8 +3939,8 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                       && hh->eh.dynindx != -1
                       && (plabel
                           || !IS_ABSOLUTE_RELOC (r_type)
-                          || !info->shared
-                          || !info->symbolic
+                          || !bfd_link_pic (info)
+                          || !SYMBOLIC_BIND (info, &hh->eh)
                           || !hh->eh.def_regular))
                {
                  outrel.r_info = ELF32_R_INFO (hh->eh.dynindx, r_type);
@@ -4077,12 +3992,12 @@ elf32_hppa_relocate_section (bfd *output_bfd,
              bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
            }
          break;
-         
+
        case R_PARISC_TLS_LDM21L:
        case R_PARISC_TLS_LDM14R:
          {
            bfd_vma off;
-       
+
            off = htab->tls_ldm_got.offset;
            if (off & 1)
              off &= ~1;
@@ -4091,13 +4006,13 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                Elf_Internal_Rela outrel;
                bfd_byte *loc;
 
-               outrel.r_offset = (off 
-                                  + htab->sgot->output_section->vma
-                                  + htab->sgot->output_offset);
+               outrel.r_offset = (off
+                                  + htab->etab.sgot->output_section->vma
+                                  + htab->etab.sgot->output_offset);
                outrel.r_addend = 0;
                outrel.r_info = ELF32_R_INFO (0, R_PARISC_TLS_DTPMOD32);
-               loc = htab->srelgot->contents; 
-               loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
+               loc = htab->etab.srelgot->contents;
+               loc += htab->etab.srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
 
                bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
                htab->tls_ldm_got.offset |= 1;
@@ -4105,8 +4020,8 @@ elf32_hppa_relocate_section (bfd *output_bfd,
 
            /* Add the base of the GOT to the relocation value.  */
            relocation = (off
-                         + htab->sgot->output_offset
-                         + htab->sgot->output_section->vma);
+                         + htab->etab.sgot->output_offset
+                         + htab->etab.sgot->output_section->vma);
 
            break;
          }
@@ -4128,15 +4043,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, info->shared, &hh->eh)
-                   && (!info->shared
-                       || !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;
              }
@@ -4162,44 +4079,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 ((info->shared || 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->srelgot->contents; 
-                   /* FIXME (CAO): Should this be reloc_count++ ? */
-                   loc += htab->srelgot->reloc_count * sizeof (Elf32_External_Rela);
+                   loc = htab->etab.srelgot->contents;
+                   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->sgot->output_section->vma
-                                          + htab->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->sgot->contents + cur_off);
                        bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
-                       htab->srelgot->reloc_count++;
+                       htab->etab.srelgot->reloc_count++;
                        loc += sizeof (Elf32_External_Rela);
-
-                       if (indx == 0)
-                         bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
-                                     htab->sgot->contents + cur_off + 4);
-                       else
-                         {
-                           bfd_put_32 (output_bfd, 0,
-                                       htab->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->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
                      {
@@ -4209,37 +4123,36 @@ elf32_hppa_relocate_section (bfd *output_bfd,
                           symbol binding locally.  Mark it as belonging
                           to module 1, the executable.  */
                        bfd_put_32 (output_bfd, 1,
-                                   htab->sgot->contents + cur_off);
-                       bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
-                                   htab->sgot->contents + cur_off + 4);
+                                   htab->etab.sgot->contents + cur_off);
+                       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->sgot->output_section->vma
-                                          + htab->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->srelgot->reloc_count++;
+                       htab->etab.srelgot->reloc_count++;
                        loc += sizeof (Elf32_External_Rela);
                      }
                    else
                      bfd_put_32 (output_bfd, tpoff (info, relocation),
-                                 htab->sgot->contents + cur_off);
-
+                                 htab->etab.sgot->contents + cur_off);
                    cur_off += 4;
                  }
 
@@ -4249,6 +4162,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)
@@ -4256,8 +4198,8 @@ elf32_hppa_relocate_section (bfd *output_bfd,
 
            /* Add the base of the GOT to the relocation value.  */
            relocation = (off
-                         + htab->sgot->output_offset
-                         + htab->sgot->output_section->vma);
+                         + htab->etab.sgot->output_offset
+                         + htab->etab.sgot->output_section->vma);
 
            break;
          }
@@ -4299,11 +4241,12 @@ elf32_hppa_relocate_section (bfd *output_bfd,
        {
          if (rstatus == bfd_reloc_notsupported || !warned_undef)
            {
-             (*_bfd_error_handler)
-               (_("%B(%A+0x%lx): cannot handle %s for %s"),
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%B(%A+%#Lx): cannot handle %s for %s"),
                 input_bfd,
                 input_section,
-                (long) rela->r_offset,
+                rela->r_offset,
                 howto->name,
                 sym_name);
              bfd_set_error (bfd_error_bad_value);
@@ -4311,12 +4254,9 @@ elf32_hppa_relocate_section (bfd *output_bfd,
            }
        }
       else
-       {
-         if (!((*info->callbacks->reloc_overflow)
-               (info, (hh ? &hh->eh.root : NULL), sym_name, howto->name,
-                (bfd_vma) 0, input_bfd, input_section, rela->r_offset)))
-           return FALSE;
-       }
+       (*info->callbacks->reloc_overflow)
+         (info, (hh ? &hh->eh.root : NULL), sym_name, howto->name,
+          (bfd_vma) 0, input_bfd, input_section, rela->r_offset);
     }
 
   return TRUE;
@@ -4365,8 +4305,8 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
 
       /* Create a dynamic IPLT relocation for this entry.  */
       rela.r_offset = (eh->plt.offset
-                     + htab->splt->output_offset
-                     + htab->splt->output_section->vma);
+                     + htab->etab.splt->output_offset
+                     + htab->etab.splt->output_section->vma);
       if (eh->dynindx != -1)
        {
          rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_IPLT);
@@ -4380,9 +4320,9 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
          rela.r_addend = value;
        }
 
-      loc = htab->srelplt->contents;
-      loc += htab->srelplt->reloc_count++ * sizeof (Elf32_External_Rela);
-      bfd_elf32_swap_reloca_out (htab->splt->output_section->owner, &rela, loc);
+      loc = htab->etab.srelplt->contents;
+      loc += htab->etab.srelplt->reloc_count++ * sizeof (Elf32_External_Rela);
+      bfd_elf32_swap_reloca_out (htab->etab.splt->output_section->owner, &rela, loc);
 
       if (!eh->def_regular)
        {
@@ -4393,43 +4333,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->sgot->output_offset
-                     + htab->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 (info->shared
-         && (info->symbolic || 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->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->srelgot->contents;
-      loc += htab->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)
@@ -4443,21 +4389,21 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
                 || eh->root.type == bfd_link_hash_defweak)))
        abort ();
 
-      sec = htab->srelbss;
-
       rela.r_offset = (eh->root.u.def.value
                      + eh->root.u.def.section->output_offset
                      + eh->root.u.def.section->output_section->vma);
       rela.r_addend = 0;
       rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_COPY);
+      if (eh->root.u.def.section == htab->etab.sdynrelro)
+       sec = htab->etab.sreldynrelro;
+      else
+       sec = htab->etab.srelbss;
       loc = sec->contents + sec->reloc_count++ * sizeof (Elf32_External_Rela);
       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
     }
 
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
-  if (eh_name (eh)[0] == '_'
-      && (strcmp (eh_name (eh), "_DYNAMIC") == 0
-         || eh == htab->etab.hgot))
+  if (eh == htab->etab.hdynamic || eh == htab->etab.hgot)
     {
       sym->st_shndx = SHN_ABS;
     }
@@ -4469,7 +4415,9 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
    dynamic linker, before writing them out.  */
 
 static enum elf_reloc_type_class
-elf32_hppa_reloc_type_class (const Elf_Internal_Rela *rela)
+elf32_hppa_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                            const asection *rel_sec ATTRIBUTE_UNUSED,
+                            const Elf_Internal_Rela *rela)
 {
   /* Handle TLS relocs first; we don't want them to be marked
      relative by the "if (ELF32_R_SYM (rela->r_info) == STN_UNDEF)"
@@ -4505,6 +4453,7 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
   bfd *dynobj;
   struct elf32_hppa_link_hash_table *htab;
   asection *sdyn;
+  asection * sgot;
 
   htab = hppa_link_hash_table (info);
   if (htab == NULL)
@@ -4512,7 +4461,13 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
 
   dynobj = htab->etab.dynobj;
 
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sgot = htab->etab.sgot;
+  /* A broken linker script might have discarded the dynamic sections.
+     Catch this here so that we do not seg-fault later on.  */
+  if (sgot != NULL && bfd_is_abs_section (sgot->output_section))
+    return FALSE;
+
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (htab->etab.dynamic_sections_created)
     {
@@ -4541,77 +4496,57 @@ elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_JMPREL:
-             s = htab->srelplt;
+             s = htab->etab.srelplt;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_PLTRELSZ:
-             s = htab->srelplt;
+             s = htab->etab.srelplt;
              dyn.d_un.d_val = s->size;
              break;
-
-           case DT_RELASZ:
-             /* Don't count procedure linkage table relocs in the
-                overall reloc count.  */
-             s = htab->srelplt;
-             if (s == NULL)
-               continue;
-             dyn.d_un.d_val -= s->size;
-             break;
-
-           case DT_RELA:
-             /* We may not be using the standard ELF linker script.
-                If .rela.plt is the first .rela section, we adjust
-                DT_RELA to not include it.  */
-             s = htab->srelplt;
-             if (s == NULL)
-               continue;
-             if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset)
-               continue;
-             dyn.d_un.d_ptr += s->size;
-             break;
            }
 
          bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
        }
     }
 
-  if (htab->sgot != NULL && htab->sgot->size != 0)
+  if (sgot != NULL && sgot->size != 0)
     {
       /* Fill in the first entry in the global offset table.
         We use it to point to our dynamic section, if we have one.  */
       bfd_put_32 (output_bfd,
                  sdyn ? sdyn->output_section->vma + sdyn->output_offset : 0,
-                 htab->sgot->contents);
+                 sgot->contents);
 
       /* The second entry is reserved for use by the dynamic linker.  */
-      memset (htab->sgot->contents + GOT_ENTRY_SIZE, 0, GOT_ENTRY_SIZE);
+      memset (sgot->contents + GOT_ENTRY_SIZE, 0, GOT_ENTRY_SIZE);
 
       /* Set .got entry size.  */
-      elf_section_data (htab->sgot->output_section)
+      elf_section_data (sgot->output_section)
        ->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
     }
 
-  if (htab->splt != NULL && htab->splt->size != 0)
+  if (htab->etab.splt != NULL && htab->etab.splt->size != 0)
     {
-      /* Set plt entry size.  */
-      elf_section_data (htab->splt->output_section)
-       ->this_hdr.sh_entsize = PLT_ENTRY_SIZE;
+      /* Set plt entry size to 0 instead of PLT_ENTRY_SIZE, since we add the
+        plt stubs and as such the section does not hold a table of fixed-size
+        entries.  */
+      elf_section_data (htab->etab.splt->output_section)->this_hdr.sh_entsize = 0;
 
       if (htab->need_plt_stub)
        {
          /* Set up the .plt stub.  */
-         memcpy (htab->splt->contents
-                 + htab->splt->size - sizeof (plt_stub),
+         memcpy (htab->etab.splt->contents
+                 + htab->etab.splt->size - sizeof (plt_stub),
                  plt_stub, sizeof (plt_stub));
 
-         if ((htab->splt->output_offset
-              + htab->splt->output_section->vma
-              + htab->splt->size)
-             != (htab->sgot->output_offset
-                 + htab->sgot->output_section->vma))
+         if ((htab->etab.splt->output_offset
+              + htab->etab.splt->output_section->vma
+              + htab->etab.splt->size)
+             != (sgot->output_offset
+                 + sgot->output_section->vma))
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
                (_(".got section not immediately after .plt section"));
              return FALSE;
            }
@@ -4642,10 +4577,10 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
 /* Stuff for the BFD linker.  */
 #define bfd_elf32_bfd_final_link            elf32_hppa_final_link
 #define bfd_elf32_bfd_link_hash_table_create elf32_hppa_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_free   elf32_hppa_link_hash_table_free
 #define elf_backend_adjust_dynamic_symbol    elf32_hppa_adjust_dynamic_symbol
 #define elf_backend_copy_indirect_symbol     elf32_hppa_copy_indirect_symbol
 #define elf_backend_check_relocs            elf32_hppa_check_relocs
+#define elf_backend_relocs_compatible       _bfd_elf_relocs_compatible
 #define elf_backend_create_dynamic_sections  elf32_hppa_create_dynamic_sections
 #define elf_backend_fake_sections           elf_hppa_fake_sections
 #define elf_backend_relocate_section        elf32_hppa_relocate_section
@@ -4655,12 +4590,10 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
 #define elf_backend_size_dynamic_sections    elf32_hppa_size_dynamic_sections
 #define elf_backend_init_index_section      _bfd_elf_init_1_index_section
 #define elf_backend_gc_mark_hook            elf32_hppa_gc_mark_hook
-#define elf_backend_gc_sweep_hook           elf32_hppa_gc_sweep_hook
 #define elf_backend_grok_prstatus           elf32_hppa_grok_prstatus
 #define elf_backend_grok_psinfo                     elf32_hppa_grok_psinfo
 #define elf_backend_object_p                elf32_hppa_object_p
 #define elf_backend_final_write_processing   elf_hppa_final_write_processing
-#define elf_backend_post_process_headers     _bfd_elf_set_osabi
 #define elf_backend_get_symbol_type         elf32_hppa_elf_get_symbol_type
 #define elf_backend_reloc_type_class        elf32_hppa_reloc_type_class
 #define elf_backend_action_discarded        elf_hppa_action_discarded
@@ -4672,9 +4605,12 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
 #define elf_backend_plt_readonly            0
 #define elf_backend_want_plt_sym            0
 #define elf_backend_got_header_size         8
+#define elf_backend_want_dynrelro           1
 #define elf_backend_rela_normal                     1
+#define elf_backend_dtrel_excludes_plt      1
+#define elf_backend_no_page_alias           1
 
-#define TARGET_BIG_SYM         bfd_elf32_hppa_vec
+#define TARGET_BIG_SYM         hppa_elf32_vec
 #define TARGET_BIG_NAME                "elf32-hppa"
 #define ELF_ARCH               bfd_arch_hppa
 #define ELF_TARGET_ID          HPPA32_ELF_DATA
@@ -4686,18 +4622,18 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
 #include "elf32-target.h"
 
 #undef TARGET_BIG_SYM
-#define TARGET_BIG_SYM         bfd_elf32_hppa_linux_vec
+#define TARGET_BIG_SYM         hppa_elf32_linux_vec
 #undef TARGET_BIG_NAME
 #define TARGET_BIG_NAME                "elf32-hppa-linux"
 #undef ELF_OSABI
-#define ELF_OSABI              ELFOSABI_LINUX
+#define ELF_OSABI              ELFOSABI_GNU
 #undef elf32_bed
 #define elf32_bed              elf32_hppa_linux_bed
 
 #include "elf32-target.h"
 
 #undef TARGET_BIG_SYM
-#define TARGET_BIG_SYM         bfd_elf32_hppa_nbsd_vec
+#define TARGET_BIG_SYM         hppa_elf32_nbsd_vec
 #undef TARGET_BIG_NAME
 #define TARGET_BIG_NAME                "elf32-hppa-netbsd"
 #undef ELF_OSABI
This page took 0.060428 seconds and 4 git commands to generate.