]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf64-hppa.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / elf64-hppa.c
index 2e66c92bfb5389891dffbe200b917417f04f2e1f..50782fe2c4c02b49362e45e9a4f098d7a50db339 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for HPPA 64-bit ELF
-   Copyright (C) 1999-2018 Free Software Foundation, Inc.
+   Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -117,8 +117,6 @@ struct elf64_hppa_link_hash_table
   /* Shortcuts to get to the various linker defined sections.  */
   asection *dlt_sec;
   asection *dlt_rel_sec;
-  asection *plt_sec;
-  asection *plt_rel_sec;
   asection *opd_sec;
   asection *opd_rel_sec;
   asection *other_rel_sec;
@@ -147,8 +145,9 @@ struct elf64_hppa_link_hash_table
 };
 
 #define hppa_link_hash_table(p) \
-  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
-  == HPPA64_ELF_DATA ? ((struct elf64_hppa_link_hash_table *) ((p)->hash)) : NULL)
+  ((is_elf_hash_table ((p)->hash)                                      \
+    && elf_hash_table_id (elf_hash_table (p)) == HPPA64_ELF_DATA)      \
+   ? (struct elf64_hppa_link_hash_table *) (p)->hash : NULL)
 
 #define hppa_elf_hash_entry(ent) \
   ((struct elf64_hppa_link_hash_entry *)(ent))
@@ -169,9 +168,6 @@ static struct bfd_link_hash_table *elf64_hppa_hash_table_create
 static bfd_boolean elf64_hppa_object_p
   (bfd *);
 
-static void elf64_hppa_post_process_headers
-  (bfd *, struct bfd_link_info *);
-
 static bfd_boolean elf64_hppa_create_dynamic_sections
   (bfd *, struct bfd_link_info *);
 
@@ -292,7 +288,7 @@ static struct bfd_link_hash_table*
 elf64_hppa_hash_table_create (bfd *abfd)
 {
   struct elf64_hppa_link_hash_table *htab;
-  bfd_size_type amt = sizeof (*htab);
+  size_t amt = sizeof (*htab);
 
   htab = bfd_zmalloc (amt);
   if (htab == NULL)
@@ -307,6 +303,7 @@ elf64_hppa_hash_table_create (bfd *abfd)
       return NULL;
     }
 
+  htab->root.dt_pltgot_required = TRUE;
   htab->text_segment_base = (bfd_vma) -1;
   htab->data_segment_base = (bfd_vma) -1;
 
@@ -386,7 +383,9 @@ elf64_hppa_section_from_shdr (bfd *abfd,
   if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
     return FALSE;
 
-  return TRUE;
+  return ((hdr->sh_flags & SHF_PARISC_SHORT) == 0
+         || bfd_set_section_flags (hdr->bfd_section,
+                                   hdr->bfd_section->flags | SEC_SMALL_DATA));
 }
 
 /* SEC is a section containing relocs for an input BFD when linking; return
@@ -422,7 +421,7 @@ get_reloc_section (bfd *abfd,
                                                  | SEC_LINKER_CREATED
                                                  | SEC_READONLY));
       if (srel == NULL
-         || !bfd_set_section_alignment (dynobj, srel, 3))
+         || !bfd_set_section_alignment (srel, 3))
        return FALSE;
     }
 
@@ -535,8 +534,7 @@ elf64_hppa_check_relocs (bfd *abfd,
 
         ?!? Note we leak the last section_syms array.  Presumably we
         could free it in one of the later routines in this file.  */
-      if (hppa_info->section_syms)
-       free (hppa_info->section_syms);
+      free (hppa_info->section_syms);
 
       /* Read this BFD's local symbols.  */
       if (symtab_hdr->sh_info != 0)
@@ -804,7 +802,7 @@ elf64_hppa_check_relocs (bfd *abfd,
 
       if (need_entry & NEED_PLT)
        {
-         if (! hppa_info->plt_sec
+         if (! hppa_info->root.splt
              && ! get_plt (abfd, info, hppa_info))
            goto err_out;
 
@@ -1120,16 +1118,18 @@ allocate_global_data_opd (struct elf_link_hash_entry *eh, void *data)
 /* HP requires the EI_OSABI field to be filled in.  The assignment to
    EI_ABIVERSION may not be strictly necessary.  */
 
-static void
-elf64_hppa_post_process_headers (bfd *abfd,
-                        struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
+static bfd_boolean
+elf64_hppa_init_file_header (bfd *abfd, struct bfd_link_info *info)
 {
-  Elf_Internal_Ehdr * i_ehdrp;
+  Elf_Internal_Ehdr *i_ehdrp;
 
-  i_ehdrp = elf_elfheader (abfd);
+  if (!_bfd_elf_init_file_header (abfd, info))
+    return FALSE;
 
+  i_ehdrp = elf_elfheader (abfd);
   i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
   i_ehdrp->e_ident[EI_ABIVERSION] = 1;
+  return TRUE;
 }
 
 /* Create function descriptor section (.opd).  This section is called .opd
@@ -1159,7 +1159,7 @@ get_opd (bfd *abfd,
                                                 | SEC_IN_MEMORY
                                                 | SEC_LINKER_CREATED));
       if (!opd
-         || !bfd_set_section_alignment (abfd, opd, 3))
+         || !bfd_set_section_alignment (opd, 3))
        {
          BFD_ASSERT (0);
          return FALSE;
@@ -1181,7 +1181,7 @@ get_plt (bfd *abfd,
   asection *plt;
   bfd *dynobj;
 
-  plt = hppa_info->plt_sec;
+  plt = hppa_info->root.splt;
   if (!plt)
     {
       dynobj = hppa_info->root.dynobj;
@@ -1195,13 +1195,13 @@ get_plt (bfd *abfd,
                                                 | SEC_IN_MEMORY
                                                 | SEC_LINKER_CREATED));
       if (!plt
-         || !bfd_set_section_alignment (abfd, plt, 3))
+         || !bfd_set_section_alignment (plt, 3))
        {
          BFD_ASSERT (0);
          return FALSE;
        }
 
-      hppa_info->plt_sec = plt;
+      hppa_info->root.splt = plt;
     }
 
   return TRUE;
@@ -1231,7 +1231,7 @@ get_dlt (bfd *abfd,
                                                 | SEC_IN_MEMORY
                                                 | SEC_LINKER_CREATED));
       if (!dlt
-         || !bfd_set_section_alignment (abfd, dlt, 3))
+         || !bfd_set_section_alignment (dlt, 3))
        {
          BFD_ASSERT (0);
          return FALSE;
@@ -1267,7 +1267,7 @@ get_stub (bfd *abfd,
                                                  | SEC_READONLY
                                                  | SEC_LINKER_CREATED));
       if (!stub
-         || !bfd_set_section_alignment (abfd, stub, 3))
+         || !bfd_set_section_alignment (stub, 3))
        {
          BFD_ASSERT (0);
          return FALSE;
@@ -1347,7 +1347,7 @@ elf64_hppa_create_dynamic_sections (bfd *abfd,
                                           | SEC_READONLY
                                           | SEC_LINKER_CREATED));
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, 3))
+      || !bfd_set_section_alignment (s, 3))
     return FALSE;
   hppa_info->dlt_rel_sec = s;
 
@@ -1358,9 +1358,9 @@ elf64_hppa_create_dynamic_sections (bfd *abfd,
                                           | SEC_READONLY
                                           | SEC_LINKER_CREATED));
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, 3))
+      || !bfd_set_section_alignment (s, 3))
     return FALSE;
-  hppa_info->plt_rel_sec = s;
+  hppa_info->root.srelplt = s;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".rela.data",
                                          (SEC_ALLOC | SEC_LOAD
@@ -1369,7 +1369,7 @@ elf64_hppa_create_dynamic_sections (bfd *abfd,
                                           | SEC_READONLY
                                           | SEC_LINKER_CREATED));
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, 3))
+      || !bfd_set_section_alignment (s, 3))
     return FALSE;
   hppa_info->other_rel_sec = s;
 
@@ -1380,7 +1380,7 @@ elf64_hppa_create_dynamic_sections (bfd *abfd,
                                           | SEC_READONLY
                                           | SEC_LINKER_CREATED));
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, 3))
+      || !bfd_set_section_alignment (s, 3))
     return FALSE;
   hppa_info->opd_rel_sec = s;
 
@@ -1454,7 +1454,7 @@ allocate_dynrel_entries (struct elf_link_hash_entry *eh, void *data)
       else if (shared)
        t = 2 * sizeof (Elf64_External_Rela);
 
-      hppa_info->plt_rel_sec->size += t;
+      hppa_info->root.srelplt->size += t;
     }
 
   return TRUE;
@@ -1528,9 +1528,7 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
   bfd *dynobj;
   bfd *ibfd;
   asection *sec;
-  bfd_boolean plt;
   bfd_boolean relocs;
-  bfd_boolean reltext;
 
   hppa_info = hppa_link_hash_table (info);
   if (hppa_info == NULL)
@@ -1653,8 +1651,8 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
        }
       else
        {
-         sec = hppa_info->plt_sec;
-         srel = hppa_info->plt_rel_sec;
+         sec = hppa_info->root.splt;
+         srel = hppa_info->root.srelplt;
          for (; local_plt < end_local_plt; ++local_plt)
            {
              if (*local_plt > 0)
@@ -1707,12 +1705,12 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
       hppa_info->dlt_sec->size = data.ofs;
     }
 
-  if (hppa_info->plt_sec)
+  if (hppa_info->root.splt)
     {
-      data.ofs = hppa_info->plt_sec->size;
+      data.ofs = hppa_info->root.splt->size;
       elf_link_hash_traverse (&hppa_info->root,
                              allocate_global_data_plt, &data);
-      hppa_info->plt_sec->size = data.ofs;
+      hppa_info->root.splt->size = data.ofs;
     }
 
   if (hppa_info->stub_sec)
@@ -1738,9 +1736,7 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
                            allocate_dynrel_entries, &data);
 
   /* The sizes of all the sections are set.  Allocate memory for them.  */
-  plt = FALSE;
   relocs = FALSE;
-  reltext = FALSE;
   for (sec = dynobj->sections; sec != NULL; sec = sec->next)
     {
       const char *name;
@@ -1750,12 +1746,12 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
 
       /* It's OK to base decisions on the section name, because none
         of the dynobj section names depend upon the input files.  */
-      name = bfd_get_section_name (dynobj, sec);
+      name = bfd_section_name (sec);
 
       if (strcmp (name, ".plt") == 0)
        {
          /* Remember whether there is a PLT.  */
-         plt = sec->size != 0;
+         ;
        }
       else if (strcmp (name, ".opd") == 0
               || CONST_STRNEQ (name, ".dlt")
@@ -1768,29 +1764,10 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
        {
          if (sec->size != 0)
            {
-             asection *target;
-
              /* Remember whether there are any reloc sections other
                 than .rela.plt.  */
              if (strcmp (name, ".rela.plt") != 0)
-               {
-                 const char *outname;
-
-                 relocs = TRUE;
-
-                 /* If this relocation section applies to a read only
-                    section, then we probably need a DT_TEXTREL
-                    entry.  The entries in the .rela.plt section
-                    really apply to the .got section, which we
-                    created ourselves and so know is not readonly.  */
-                 outname = bfd_get_section_name (output_bfd,
-                                                 sec->output_section);
-                 target = bfd_get_section_by_name (output_bfd, outname + 4);
-                 if (target != NULL
-                     && (target->flags & SEC_READONLY) != 0
-                     && (target->flags & SEC_ALLOC) != 0)
-                   reltext = TRUE;
-               }
+               relocs = TRUE;
 
              /* We use the reloc_count field as a counter if we need
                 to copy relocs into the output file.  */
@@ -1843,8 +1820,7 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
 #define add_dynamic_entry(TAG, VAL) \
   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
-      if (!add_dynamic_entry (DT_HP_DLD_FLAGS, 0)
-         || !add_dynamic_entry (DT_PLTGOT, 0))
+      if (!add_dynamic_entry (DT_HP_DLD_FLAGS, 0))
        return FALSE;
 
       /* Add some entries to the .dynamic section.  We fill in the
@@ -1854,8 +1830,7 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
         dynamic linker and used by the debugger.  */
       if (! bfd_link_pic (info))
        {
-         if (!add_dynamic_entry (DT_DEBUG, 0)
-             || !add_dynamic_entry (DT_HP_DLD_HOOK, 0)
+         if (!add_dynamic_entry (DT_HP_DLD_HOOK, 0)
              || !add_dynamic_entry (DT_HP_LOAD_MAP, 0))
            return FALSE;
        }
@@ -1864,33 +1839,10 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
         Required by HPUX 11.00 patch PHSS_26559.  */
       if (!add_dynamic_entry (DT_FLAGS, (info)->flags))
        return FALSE;
-
-      if (plt)
-       {
-         if (!add_dynamic_entry (DT_PLTRELSZ, 0)
-             || !add_dynamic_entry (DT_PLTREL, DT_RELA)
-             || !add_dynamic_entry (DT_JMPREL, 0))
-           return FALSE;
-       }
-
-      if (relocs)
-       {
-         if (!add_dynamic_entry (DT_RELA, 0)
-             || !add_dynamic_entry (DT_RELASZ, 0)
-             || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
-           return FALSE;
-       }
-
-      if (reltext)
-       {
-         if (!add_dynamic_entry (DT_TEXTREL, 0))
-           return FALSE;
-         info->flags |= DF_TEXTREL;
-       }
     }
 #undef add_dynamic_entry
 
-  return TRUE;
+  return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs);
 }
 
 /* Called after we have output the symbol into the dynamic symbol
@@ -1951,9 +1903,9 @@ elf64_hppa_finish_dynamic_symbol (bfd *output_bfd,
     return FALSE;
 
   stub = hppa_info->stub_sec;
-  splt = hppa_info->plt_sec;
+  splt = hppa_info->root.splt;
   sopd = hppa_info->opd_sec;
-  spltrel = hppa_info->plt_rel_sec;
+  spltrel = hppa_info->root.srelplt;
 
   /* Incredible.  It is actually necessary to NOT use the symbol's real
      value when building the dynamic symbol table for a shared library.
@@ -2011,7 +1963,7 @@ elf64_hppa_finish_dynamic_symbol (bfd *output_bfd,
         in the output_offset of the PLT section.  */
 
       bfd_put_64 (splt->owner, value, splt->contents + hh->plt_offset);
-      value = _bfd_get_gp_value (splt->output_section->owner);
+      value = _bfd_get_gp_value (info->output_bfd);
       bfd_put_64 (splt->owner, value, splt->contents + hh->plt_offset + 0x8);
 
       /* Create a dynamic IPLT relocation for this entry.
@@ -2027,7 +1979,7 @@ elf64_hppa_finish_dynamic_symbol (bfd *output_bfd,
 
       loc = spltrel->contents;
       loc += spltrel->reloc_count++ * sizeof (Elf64_External_Rela);
-      bfd_elf64_swap_reloca_out (splt->output_section->owner, &rel, loc);
+      bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc);
     }
 
   /* Initialize an external call stub entry if requested.  */
@@ -2143,7 +2095,7 @@ elf64_hppa_finalize_opd (struct elf_link_hash_entry *eh, void *data)
       bfd_put_64 (sopd->owner, value, sopd->contents + hh->opd_offset + 16);
 
       /* The last word is our local __gp value.  */
-      value = _bfd_get_gp_value (sopd->output_section->owner);
+      value = _bfd_get_gp_value (info->output_bfd);
       bfd_put_64 (sopd->owner, value, sopd->contents + hh->opd_offset + 24);
     }
 
@@ -2220,7 +2172,7 @@ elf64_hppa_finalize_opd (struct elf_link_hash_entry *eh, void *data)
 
       loc = sopdrel->contents;
       loc += sopdrel->reloc_count++ * sizeof (Elf64_External_Rela);
-      bfd_elf64_swap_reloca_out (sopd->output_section->owner, &rel, loc);
+      bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc);
     }
   return TRUE;
 }
@@ -2315,7 +2267,7 @@ elf64_hppa_finalize_dlt (struct elf_link_hash_entry *eh, void *data)
 
       loc = sdltrel->contents;
       loc += sdltrel->reloc_count++ * sizeof (Elf64_External_Rela);
-      bfd_elf64_swap_reloca_out (sdlt->output_section->owner, &rel, loc);
+      bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc);
     }
   return TRUE;
 }
@@ -2431,8 +2383,7 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
          loc = hppa_info->other_rel_sec->contents;
          loc += (hppa_info->other_rel_sec->reloc_count++
                  * sizeof (Elf64_External_Rela));
-         bfd_elf64_swap_reloca_out (hppa_info->other_rel_sec->output_section->owner,
-                                    &rel, loc);
+         bfd_elf64_swap_reloca_out (info->output_bfd, &rel, loc);
        }
     }
 
@@ -2534,13 +2485,13 @@ elf64_hppa_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_JMPREL:
-             s = hppa_info->plt_rel_sec;
+             s = hppa_info->root.srelplt;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
            case DT_PLTRELSZ:
-             s = hppa_info->plt_rel_sec;
+             s = hppa_info->root.srelplt;
              dyn.d_un.d_val = s->size;
              bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
@@ -2565,7 +2516,7 @@ elf64_hppa_finish_dynamic_sections (bfd *output_bfd,
              /* There is some question about whether or not the size of
                 the PLT relocs should be included here.  HP's tools do
                 it, so we'll emulate them.  */
-             s = hppa_info->plt_rel_sec;
+             s = hppa_info->root.srelplt;
              dyn.d_un.d_val += s->size;
              bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
@@ -2983,7 +2934,7 @@ elf_hppa_final_link (bfd *abfd, struct bfd_link_info *info)
             that order) and set __gp to the base address of whichever
             section is found first.  */
 
-         sec = hppa_info->plt_sec;
+         sec = hppa_info->root.splt;
          if (sec && ! (sec->flags & SEC_EXCLUDE))
            gp_val = (sec->output_offset
                      + sec->output_section->vma
@@ -3041,7 +2992,7 @@ elf_hppa_final_link (bfd *abfd, struct bfd_link_info *info)
   /* 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
+  if (stat (bfd_get_filename (abfd), &buf) != 0
       || !S_ISREG(buf.st_mode))
     return TRUE;
 
@@ -3381,8 +3332,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
                                (hppa_info->opd_sec->contents + off + 16));
 
                    /* The last word is our local __gp value.  */
-                   value = _bfd_get_gp_value
-                             (hppa_info->opd_sec->output_section->owner);
+                   value = _bfd_get_gp_value (info->output_bfd);
                    bfd_put_64 (hppa_info->opd_sec->owner, value,
                                (hppa_info->opd_sec->contents + off + 24));
                  }
@@ -3533,8 +3483,8 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
           to the start of the DLT, so we have to compute the absolute
           address, then subtract out the value of __gp.  */
        value = (hh->plt_offset
-                + hppa_info->plt_sec->output_offset
-                + hppa_info->plt_sec->output_section->vma);
+                + hppa_info->root.splt->output_offset
+                + hppa_info->root.splt->output_section->vma);
        value -= _bfd_get_gp_value (output_bfd);
 
        /* All PLTOFF relocations are basically the same at this point,
@@ -3556,33 +3506,12 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
 
     case R_PARISC_LTOFF_FPTR32:
       {
-       /* We may still need to create the FPTR itself if it was for
-          a local symbol.  */
-       if (hh == NULL)
-         {
-           /* The first two words of an .opd entry are zero.  */
-           memset (hppa_info->opd_sec->contents + hh->opd_offset, 0, 16);
-
-           /* The next word is the address of the function.  */
-           bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
-                       (hppa_info->opd_sec->contents
-                        + hh->opd_offset + 16));
-
-           /* The last word is our local __gp value.  */
-           value = _bfd_get_gp_value
-                     (hppa_info->opd_sec->output_section->owner);
-           bfd_put_64 (hppa_info->opd_sec->owner, value,
-                       hppa_info->opd_sec->contents + hh->opd_offset + 24);
-
-           /* The DLT value is the address of the .opd entry.  */
-           value = (hh->opd_offset
-                    + hppa_info->opd_sec->output_offset
-                    + hppa_info->opd_sec->output_section->vma);
-
-           bfd_put_64 (hppa_info->dlt_sec->owner,
-                       value,
-                       hppa_info->dlt_sec->contents + hh->dlt_offset);
-         }
+       /* FIXME: There used to be code here to create the FPTR itself if
+          the relocation was against a local symbol.  But the code could
+          never have worked.  If the assert below is ever triggered then
+          the code will need to be reinstated and fixed so that it does
+          what is needed.  */
+       BFD_ASSERT (hh != NULL);
 
        /* We want the value of the DLT offset for this symbol, not
           the symbol's actual address.  Note that __gp may not point
@@ -3612,8 +3541,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
                         + hh->opd_offset + 16));
 
            /* The last word is our local __gp value.  */
-           value = _bfd_get_gp_value
-                     (hppa_info->opd_sec->output_section->owner);
+           value = _bfd_get_gp_value (info->output_bfd);
            bfd_put_64 (hppa_info->opd_sec->owner, value,
                        hppa_info->opd_sec->contents + hh->opd_offset + 24);
 
@@ -3739,8 +3667,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
                            (hppa_info->opd_sec->contents + off + 16));
 
                /* The last word is our local __gp value.  */
-               value = _bfd_get_gp_value
-                         (hppa_info->opd_sec->output_section->owner);
+               value = _bfd_get_gp_value (info->output_bfd);
                bfd_put_64 (hppa_info->opd_sec->owner, value,
                            hppa_info->opd_sec->contents + off + 24);
              }
@@ -3762,7 +3689,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
       }
 
     case R_PARISC_SECREL32:
-      if (sym_sec)
+      if (sym_sec && sym_sec->output_section)
        value -= sym_sec->output_section->vma;
       bfd_put_32 (input_bfd, value + addend, hit_data);
       return bfd_reloc_ok;
@@ -3907,13 +3834,14 @@ elf64_hppa_relocate_section (bfd *output_bfd,
          else if (!bfd_link_relocatable (info))
            {
              bfd_boolean err;
-             err = (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
-                    || ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT);
-             (*info->callbacks->undefined_symbol) (info,
-                                                   eh->root.root.string,
-                                                   input_bfd,
-                                                   input_section,
-                                                   rel->r_offset, err);
+
+             err = (info->unresolved_syms_in_objects == RM_DIAGNOSE
+                    && !info->warn_unresolved_syms)
+               || ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT;
+
+             info->callbacks->undefined_symbol
+               (info, eh->root.root.string, input_bfd,
+                input_section, rel->r_offset, err);
            }
 
          if (!bfd_link_relocatable (info)
@@ -3925,7 +3853,7 @@ elf64_hppa_relocate_section (bfd *output_bfd,
              if (info->unresolved_syms_in_objects == RM_IGNORE
                  && ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT
                  && eh->type == STT_PARISC_MILLI)
-               (*info->callbacks->undefined_symbol)
+               info->callbacks->undefined_symbol
                  (info, eh_name (eh), input_bfd,
                   input_section, rel->r_offset, FALSE);
            }
@@ -3963,7 +3891,7 @@ elf64_hppa_relocate_section (bfd *output_bfd,
                    if (sym_name == NULL)
                      return FALSE;
                    if (*sym_name == '\0')
-                     sym_name = bfd_section_name (input_bfd, sym_sec);
+                     sym_name = bfd_section_name (sym_sec);
                  }
 
                (*info->callbacks->reloc_overflow)
@@ -3979,13 +3907,13 @@ elf64_hppa_relocate_section (bfd *output_bfd,
 
 static const struct bfd_elf_special_section elf64_hppa_special_sections[] =
 {
+  { STRING_COMMA_LEN (".tbss"),         0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_HP_TLS },
   { STRING_COMMA_LEN (".fini"),         0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { STRING_COMMA_LEN (".init"),         0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { STRING_COMMA_LEN (".plt"),  0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
   { STRING_COMMA_LEN (".dlt"),  0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
   { STRING_COMMA_LEN (".sdata"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
   { STRING_COMMA_LEN (".sbss"),         0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
-  { STRING_COMMA_LEN (".tbss"),         0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_HP_TLS },
   { NULL,                   0,  0, 0,            0 }
 };
 
@@ -4050,7 +3978,7 @@ const struct elf_size_info hppa64_elf_size_info =
 
 #define elf_backend_create_dynamic_sections \
                                        elf64_hppa_create_dynamic_sections
-#define elf_backend_post_process_headers       elf64_hppa_post_process_headers
+#define elf_backend_init_file_header   elf64_hppa_init_file_header
 
 #define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
 
@@ -4113,5 +4041,7 @@ const struct elf_size_info hppa64_elf_size_info =
 #define ELF_OSABI                      ELFOSABI_GNU
 #undef elf64_bed
 #define elf64_bed                      elf64_hppa_linux_bed
+#undef elf_backend_special_sections
+#define elf_backend_special_sections   (elf64_hppa_special_sections + 1)
 
 #include "elf64-target.h"