* elfxx-mips.c (_bfd_mips_elf_merge_private_bfd_data): Improve
[deliverable/binutils-gdb.git] / bfd / elf32-hppa.c
index 4dc7e9b16d989339ddb5aa96fe42453a751386ef..b204c57df462d85056fe7cefd193256574266e3a 100644 (file)
@@ -1,6 +1,6 @@
 /* BFD back-end for HP PA-RISC ELF files.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001,
-   2002 Free Software Foundation, Inc.
+   2002, 2003 Free Software Foundation, Inc.
 
    Original code by
        Center for Software Science
@@ -8,21 +8,21 @@
        University of Utah
    Largely rewritten by Alan Modra <alan@linuxcare.com.au>
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -111,7 +111,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
    :           ldw -24(%sp),%rp                ; restore the original rp
    :           ldsid (%rp),%r1
    :           mtsp %r1,%sr0
-   :           be,n 0(%sr0,%rp)                ; inter-space return  */
+   :           be,n 0(%sr0,%rp)                ; inter-space return.  */
 
 #define PLT_ENTRY_SIZE 8
 #define GOT_ENTRY_SIZE 4
@@ -310,68 +310,69 @@ static enum elf32_hppa_stub_type hppa_type_of_stub
   PARAMS ((asection *, const Elf_Internal_Rela *,
           struct elf32_hppa_link_hash_entry *, bfd_vma));
 
-static boolean hppa_build_one_stub
+static bfd_boolean hppa_build_one_stub
   PARAMS ((struct bfd_hash_entry *, PTR));
 
-static boolean hppa_size_one_stub
+static bfd_boolean hppa_size_one_stub
   PARAMS ((struct bfd_hash_entry *, PTR));
 
 /* BFD and elf backend functions.  */
-static boolean elf32_hppa_object_p PARAMS ((bfd *));
+static bfd_boolean elf32_hppa_object_p PARAMS ((bfd *));
 
-static boolean elf32_hppa_add_symbol_hook
+static bfd_boolean elf32_hppa_add_symbol_hook
   PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
           const char **, flagword *, asection **, bfd_vma *));
 
-static boolean elf32_hppa_create_dynamic_sections
+static bfd_boolean elf32_hppa_create_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
 static void elf32_hppa_copy_indirect_symbol
-  PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *));
+  PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
+          struct elf_link_hash_entry *));
 
-static boolean elf32_hppa_check_relocs
+static bfd_boolean elf32_hppa_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *,
           asection *, const Elf_Internal_Rela *));
 
 static asection *elf32_hppa_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
 
-static boolean elf32_hppa_gc_sweep_hook
+static bfd_boolean elf32_hppa_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *,
           asection *, const Elf_Internal_Rela *));
 
 static void elf32_hppa_hide_symbol
-  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean));
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
 
-static boolean elf32_hppa_adjust_dynamic_symbol
+static bfd_boolean elf32_hppa_adjust_dynamic_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 
-static boolean mark_PIC_calls
+static bfd_boolean mark_PIC_calls
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
-static boolean allocate_plt_static
+static bfd_boolean allocate_plt_static
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
-static boolean allocate_dynrelocs
+static bfd_boolean allocate_dynrelocs
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
-static boolean readonly_dynrelocs
+static bfd_boolean readonly_dynrelocs
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
-static boolean clobber_millicode_symbols
+static bfd_boolean clobber_millicode_symbols
   PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));
 
-static boolean elf32_hppa_size_dynamic_sections
+static bfd_boolean elf32_hppa_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
 static void group_sections
-  PARAMS ((struct elf32_hppa_link_hash_table *, bfd_size_type, boolean));
+  PARAMS ((struct elf32_hppa_link_hash_table *, bfd_size_type, bfd_boolean));
 
 static int get_local_syms
   PARAMS ((bfd *, bfd *, struct bfd_link_info *));
 
-static boolean elf32_hppa_final_link
+static bfd_boolean elf32_hppa_final_link
   PARAMS ((bfd *, struct bfd_link_info *));
 
 static void hppa_record_segment_addr
@@ -382,18 +383,18 @@ static bfd_reloc_status_type final_link_relocate
           bfd_vma, struct elf32_hppa_link_hash_table *, asection *,
           struct elf32_hppa_link_hash_entry *));
 
-static boolean elf32_hppa_relocate_section
+static bfd_boolean elf32_hppa_relocate_section
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
           bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 
-static boolean elf32_hppa_finish_dynamic_symbol
+static bfd_boolean elf32_hppa_finish_dynamic_symbol
   PARAMS ((bfd *, struct bfd_link_info *,
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
 
 static enum elf_reloc_type_class elf32_hppa_reloc_type_class
   PARAMS ((const Elf_Internal_Rela *));
 
-static boolean elf32_hppa_finish_dynamic_sections
+static bfd_boolean elf32_hppa_finish_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 
 static void elf32_hppa_post_process_headers
@@ -613,7 +614,7 @@ hppa_get_stub_entry (input_section, sym_sec, hash, rel, htab)
        return NULL;
 
       stub_entry = hppa_stub_hash_lookup (&htab->stub_hash_table,
-                                         stub_name, false, false);
+                                         stub_name, FALSE, FALSE);
       if (hash != NULL)
        hash->stub_cache = stub_entry;
 
@@ -643,16 +644,18 @@ hppa_add_stub (stub_name, section, htab)
       stub_sec = htab->stub_group[link_sec->id].stub_sec;
       if (stub_sec == NULL)
        {
+         size_t namelen;
          bfd_size_type len;
          char *s_name;
 
-         len = strlen (link_sec->name) + sizeof (STUB_SUFFIX);
+         namelen = strlen (link_sec->name);
+         len = namelen + sizeof (STUB_SUFFIX);
          s_name = bfd_alloc (htab->stub_bfd, len);
          if (s_name == NULL)
            return NULL;
 
-         strcpy (s_name, link_sec->name);
-         strcpy (s_name + len - sizeof (STUB_SUFFIX), STUB_SUFFIX);
+         memcpy (s_name, link_sec->name, namelen);
+         memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
          stub_sec = (*htab->add_stub_section) (s_name, link_sec);
          if (stub_sec == NULL)
            return NULL;
@@ -663,7 +666,7 @@ hppa_add_stub (stub_name, section, htab)
 
   /* Enter this entry into the linker stub hash table.  */
   stub_entry = hppa_stub_hash_lookup (&htab->stub_hash_table, stub_name,
-                                     true, false);
+                                     TRUE, FALSE);
   if (stub_entry == NULL)
     {
       (*_bfd_error_handler) (_("%s: cannot create stub entry %s"),
@@ -773,7 +776,7 @@ hppa_type_of_stub (input_sec, rel, hash, destination)
 #define LDW_R1_DLT     LDW_R1_DP
 #endif
 
-static boolean
+static bfd_boolean
 hppa_build_one_stub (gen_entry, in_arg)
      struct bfd_hash_entry *gen_entry;
      PTR in_arg;
@@ -957,7 +960,7 @@ hppa_build_one_stub (gen_entry, in_arg)
             (long) stub_entry->stub_offset,
             stub_entry->root.string);
          bfd_set_error (bfd_error_bad_value);
-         return false;
+         return FALSE;
        }
 
       val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_fsel) >> 2;
@@ -982,11 +985,11 @@ hppa_build_one_stub (gen_entry, in_arg)
 
     default:
       BFD_FAIL ();
-      return false;
+      return FALSE;
     }
 
   stub_sec->_raw_size += size;
-  return true;
+  return TRUE;
 }
 
 #undef LDIL_R1
@@ -1014,7 +1017,7 @@ hppa_build_one_stub (gen_entry, in_arg)
 /* As above, but don't actually build the stub.  Just bump offset so
    we know stub section sizes.  */
 
-static boolean
+static bfd_boolean
 hppa_size_one_stub (gen_entry, in_arg)
      struct bfd_hash_entry *gen_entry;
      PTR in_arg;
@@ -1042,13 +1045,13 @@ hppa_size_one_stub (gen_entry, in_arg)
     }
 
   stub_entry->stub_sec->_raw_size += size;
-  return true;
+  return TRUE;
 }
 
 /* Return nonzero if ABFD represents an HPPA ELF32 file.
    Additionally we set the default architecture and machine.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_object_p (abfd)
      bfd *abfd;
 {
@@ -1059,12 +1062,12 @@ elf32_hppa_object_p (abfd)
   if (strcmp (bfd_get_target (abfd), "elf32-hppa-linux") == 0)
     {
       if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX)
-       return false;
+       return FALSE;
     }
   else
     {
       if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX)
-       return false;
+       return FALSE;
     }
 
   flags = i_ehdrp->e_flags;
@@ -1079,13 +1082,13 @@ elf32_hppa_object_p (abfd)
     case EFA_PARISC_2_0 | EF_PARISC_WIDE:
       return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);
     }
-  return true;
+  return TRUE;
 }
 
 /* Undo the generic ELF code's subtraction of section->vma from the
    value of each external symbol.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      bfd *abfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
@@ -1096,13 +1099,13 @@ elf32_hppa_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      bfd_vma *valp;
 {
   *valp += (*secp)->vma;
-  return true;
+  return TRUE;
 }
 
 /* Create the .plt and .got sections, and set up our hash table
    short-cuts to various dynamic sections.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_create_dynamic_sections (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -1112,11 +1115,11 @@ elf32_hppa_create_dynamic_sections (abfd, info)
   /* Don't try to create the .plt and .got twice.  */
   htab = hppa_link_hash_table (info);
   if (htab->splt != NULL)
-    return true;
+    return TRUE;
 
   /* Call the generic code to do most of the work.  */
   if (! _bfd_elf_create_dynamic_sections (abfd, info))
-    return false;
+    return FALSE;
 
   htab->splt = bfd_get_section_by_name (abfd, ".plt");
   htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
@@ -1132,18 +1135,19 @@ elf32_hppa_create_dynamic_sections (abfd, info)
                                   | SEC_LINKER_CREATED
                                   | SEC_READONLY))
       || ! bfd_set_section_alignment (abfd, htab->srelgot, 2))
-    return false;
+    return FALSE;
 
   htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
   htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
 
-  return true;
+  return TRUE;
 }
 
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
 
 static void
-elf32_hppa_copy_indirect_symbol (dir, ind)
+elf32_hppa_copy_indirect_symbol (bed, dir, ind)
+     struct elf_backend_data *bed;
      struct elf_link_hash_entry *dir, *ind;
 {
   struct elf32_hppa_link_hash_entry *edir, *eind;
@@ -1187,7 +1191,7 @@ elf32_hppa_copy_indirect_symbol (dir, ind)
       eind->dyn_relocs = NULL;
     }
 
-  _bfd_elf_link_hash_copy_indirect (dir, ind);
+  _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
 }
 
 /* Look through the relocs for a section during the first phase, and
@@ -1195,7 +1199,7 @@ elf32_hppa_copy_indirect_symbol (dir, ind)
    table, and dynamic reloc sections.  At this point we haven't
    necessarily read all the input files.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_check_relocs (abfd, info, sec, relocs)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -1211,7 +1215,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
   asection *stubreloc;
 
   if (info->relocateable)
-    return true;
+    return TRUE;
 
   htab = hppa_link_hash_table (info);
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -1337,7 +1341,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                 bfd_archive_filename (abfd),
                 elf_hppa_howto_table[r_type].name);
              bfd_set_error (bfd_error_bad_value);
-             return false;
+             return FALSE;
            }
          /* Fall through.  */
 
@@ -1370,7 +1374,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
        case R_PARISC_GNU_VTINHERIT:
          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec,
                                               &h->elf, rel->r_offset))
-           return false;
+           return FALSE;
          continue;
 
          /* This relocation describes which C++ vtable entries are actually
@@ -1378,7 +1382,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
        case R_PARISC_GNU_VTENTRY:
          if (!_bfd_elf32_gc_record_vtentry (abfd, sec,
                                             &h->elf, rel->r_addend))
-           return false;
+           return FALSE;
          continue;
 
        default:
@@ -1395,7 +1399,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
              if (htab->elf.dynobj == NULL)
                htab->elf.dynobj = abfd;
              if (!elf32_hppa_create_dynamic_sections (htab->elf.dynobj, info))
-               return false;
+               return FALSE;
            }
 
          if (h != NULL)
@@ -1421,7 +1425,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                  local_got_refcounts = ((bfd_signed_vma *)
                                         bfd_zalloc (abfd, size));
                  if (local_got_refcounts == NULL)
-                   return false;
+                   return FALSE;
                  elf_local_got_refcounts (abfd) = local_got_refcounts;
                }
              local_got_refcounts[r_symndx] += 1;
@@ -1468,7 +1472,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                      local_got_refcounts = ((bfd_signed_vma *)
                                             bfd_zalloc (abfd, size));
                      if (local_got_refcounts == NULL)
-                       return false;
+                       return FALSE;
                      elf_local_got_refcounts (abfd) = local_got_refcounts;
                    }
                  local_plt_refcounts = (local_got_refcounts
@@ -1549,7 +1553,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                        (_("Could not find relocation section for %s"),
                         sec->name);
                      bfd_set_error (bfd_error_bad_value);
-                     return false;
+                     return FALSE;
                    }
 
                  if (htab->elf.dynobj == NULL)
@@ -1569,7 +1573,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                      if (sreloc == NULL
                          || !bfd_set_section_flags (dynobj, sreloc, flags)
                          || !bfd_set_section_alignment (dynobj, sreloc, 2))
-                       return false;
+                       return FALSE;
                    }
 
                  elf_section_data (sec)->sreloc = sreloc;
@@ -1591,7 +1595,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
                                                 sec, r_symndx);
                  if (s == NULL)
-                   return false;
+                   return FALSE;
 
                  head = ((struct elf32_hppa_dyn_reloc_entry **)
                          &elf_section_data (s)->local_dynrel);
@@ -1604,7 +1608,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                       bfd_alloc (htab->elf.dynobj,
                                  (bfd_size_type) sizeof *p));
                  if (p == NULL)
-                   return false;
+                   return FALSE;
                  p->next = *head;
                  *head = p;
                  p->sec = sec;
@@ -1623,15 +1627,15 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
        }
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Return the section that should be marked against garbage collection
    for a given relocation.  */
 
 static asection *
-elf32_hppa_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+elf32_hppa_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -1661,9 +1665,7 @@ elf32_hppa_gc_mark_hook (abfd, info, rel, h, sym)
        }
     }
   else
-    {
-      return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
   return NULL;
 }
@@ -1671,7 +1673,7 @@ elf32_hppa_gc_mark_hook (abfd, info, rel, h, sym)
 /* Update the got and plt entry reference counts for the section being
    removed.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs)
      bfd *abfd;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
@@ -1683,10 +1685,6 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs)
   bfd_signed_vma *local_got_refcounts;
   bfd_signed_vma *local_plt_refcounts;
   const Elf_Internal_Rela *rel, *relend;
-  unsigned long r_symndx;
-  struct elf_link_hash_entry *h;
-  struct elf32_hppa_link_hash_table *htab;
-  bfd *dynobj;
 
   elf_section_data (sec)->local_dynrel = NULL;
 
@@ -1696,114 +1694,83 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs)
   local_plt_refcounts = local_got_refcounts;
   if (local_plt_refcounts != NULL)
     local_plt_refcounts += symtab_hdr->sh_info;
-  htab = hppa_link_hash_table (info);
-  dynobj = htab->elf.dynobj;
-  if (dynobj == NULL)
-    return true;
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; rel++)
-    switch ((unsigned int) ELF32_R_TYPE (rel->r_info))
-      {
-      case R_PARISC_DLTIND14F:
-      case R_PARISC_DLTIND14R:
-      case R_PARISC_DLTIND21L:
-       r_symndx = ELF32_R_SYM (rel->r_info);
-       if (r_symndx >= symtab_hdr->sh_info)
-         {
-           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-           if (h->got.refcount > 0)
-             h->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_PCREL12F:
-      case R_PARISC_PCREL17C:
-      case R_PARISC_PCREL17F:
-      case R_PARISC_PCREL22F:
-       r_symndx = ELF32_R_SYM (rel->r_info);
-       if (r_symndx >= symtab_hdr->sh_info)
-         {
-           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-           if (h->plt.refcount > 0)
-             h->plt.refcount -= 1;
-         }
-       break;
-
-      case R_PARISC_PLABEL14R:
-      case R_PARISC_PLABEL21L:
-      case R_PARISC_PLABEL32:
-       r_symndx = ELF32_R_SYM (rel->r_info);
-       if (r_symndx >= symtab_hdr->sh_info)
-         {
-           struct elf32_hppa_link_hash_entry *eh;
-           struct elf32_hppa_dyn_reloc_entry **pp;
-           struct elf32_hppa_dyn_reloc_entry *p;
-
-           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
-           if (h->plt.refcount > 0)
-             h->plt.refcount -= 1;
+    {
+      unsigned long r_symndx;
+      unsigned int r_type;
+      struct elf_link_hash_entry *h = NULL;
 
-           eh = (struct elf32_hppa_link_hash_entry *) h;
+      r_symndx = ELF32_R_SYM (rel->r_info);
+      if (r_symndx >= symtab_hdr->sh_info)
+       {
+         struct elf32_hppa_link_hash_entry *eh;
+         struct elf32_hppa_dyn_reloc_entry **pp;
+         struct elf32_hppa_dyn_reloc_entry *p;
 
-           for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
-             if (p->sec == sec)
-               {
-#if RELATIVE_DYNRELOCS
-                 if (!IS_ABSOLUTE_RELOC (rtype))
-                   p->relative_count -= 1;
-#endif
-                 p->count -= 1;
-                 if (p->count == 0)
-                   *pp = p->next;
-                 break;
-               }
-         }
-       else if (local_plt_refcounts != NULL)
-         {
-           if (local_plt_refcounts[r_symndx] > 0)
-             local_plt_refcounts[r_symndx] -= 1;
-         }
-       break;
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         eh = (struct elf32_hppa_link_hash_entry *) h;
 
-      case R_PARISC_DIR32:
-       r_symndx = ELF32_R_SYM (rel->r_info);
-       if (r_symndx >= symtab_hdr->sh_info)
-         {
-           struct elf32_hppa_link_hash_entry *eh;
-           struct elf32_hppa_dyn_reloc_entry **pp;
-           struct elf32_hppa_dyn_reloc_entry *p;
+         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
+           if (p->sec == sec)
+             {
+               /* Everything must go for SEC.  */
+               *pp = p->next;
+               break;
+             }
+       }
 
-           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+      r_type = ELF32_R_TYPE (rel->r_info);
+      switch (r_type)
+       {
+       case R_PARISC_DLTIND14F:
+       case R_PARISC_DLTIND14R:
+       case R_PARISC_DLTIND21L:
+         if (h != NULL)
+           {
+             if (h->got.refcount > 0)
+               h->got.refcount -= 1;
+           }
+         else if (local_got_refcounts != NULL)
+           {
+             if (local_got_refcounts[r_symndx] > 0)
+               local_got_refcounts[r_symndx] -= 1;
+           }
+         break;
 
-           eh = (struct elf32_hppa_link_hash_entry *) h;
+       case R_PARISC_PCREL12F:
+       case R_PARISC_PCREL17C:
+       case R_PARISC_PCREL17F:
+       case R_PARISC_PCREL22F:
+         if (h != NULL)
+           {
+             if (h->plt.refcount > 0)
+               h->plt.refcount -= 1;
+           }
+         break;
 
-           for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
-             if (p->sec == sec)
-               {
-#if RELATIVE_DYNRELOCS
-                 if (!IS_ABSOLUTE_RELOC (R_PARISC_DIR32))
-                   p->relative_count -= 1;
-#endif
-                 p->count -= 1;
-                 if (p->count == 0)
-                   *pp = p->next;
-                 break;
-               }
-         }
-       break;
+       case R_PARISC_PLABEL14R:
+       case R_PARISC_PLABEL21L:
+       case R_PARISC_PLABEL32:
+         if (h != NULL)
+           {
+             if (h->plt.refcount > 0)
+               h->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;
-      }
+       default:
+         break;
+       }
+    }
 
-  return true;
+  return TRUE;
 }
 
 /* Our own version of hide_symbol, so that we can keep plt entries for
@@ -1813,7 +1780,7 @@ static void
 elf32_hppa_hide_symbol (info, h, force_local)
      struct bfd_link_info *info;
      struct elf_link_hash_entry *h;
-     boolean force_local;
+     bfd_boolean force_local;
 {
   if (force_local)
     {
@@ -1850,7 +1817,7 @@ elf32_hppa_hide_symbol (info, h, force_local)
    change the definition to something the rest of the link can
    understand.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_adjust_dynamic_symbol (info, h)
      struct bfd_link_info *info;
      struct elf_link_hash_entry *h;
@@ -1894,7 +1861,7 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
            }
        }
 
-      return true;
+      return TRUE;
     }
   else
     h->plt.offset = (bfd_vma) -1;
@@ -1909,7 +1876,7 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
        abort ();
       h->root.u.def.section = h->weakdef->root.u.def.section;
       h->root.u.def.value = h->weakdef->root.u.def.value;
-      return true;
+      return TRUE;
     }
 
   /* This is a reference to a symbol defined by a dynamic object which
@@ -1920,12 +1887,12 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
      For such cases we need not do anything here; the relocations will
      be handled correctly by relocate_section.  */
   if (info->shared)
-    return true;
+    return TRUE;
 
   /* If there are no references to this symbol that do not use the
      GOT, we don't need to generate a copy reloc.  */
   if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0)
-    return true;
+    return TRUE;
 
   eh = (struct elf32_hppa_link_hash_entry *) h;
   for (p = eh->dyn_relocs; p != NULL; p = p->next)
@@ -1940,7 +1907,7 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
   if (p == NULL)
     {
       h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
-      return true;
+      return TRUE;
     }
 
   /* We must allocate the symbol in our .dynbss section, which will
@@ -1978,7 +1945,7 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
   if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s))
     {
       if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two))
-       return false;
+       return FALSE;
     }
 
   /* Define the symbol as being at this point in the section.  */
@@ -1988,14 +1955,14 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
   /* Increment the section size to make room for the symbol.  */
   s->_raw_size += h->size;
 
-  return true;
+  return TRUE;
 }
 
 /* Called via elf_link_hash_traverse to create .plt entries for an
    application that uses statically linked PIC functions.  Similar to
    the first part of elf32_hppa_adjust_dynamic_symbol.  */
 
-static boolean
+static bfd_boolean
 mark_PIC_calls (h, inf)
      struct elf_link_hash_entry *h;
      PTR inf ATTRIBUTE_UNUSED;
@@ -2010,19 +1977,19 @@ mark_PIC_calls (h, inf)
     {
       h->plt.offset = (bfd_vma) -1;
       h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
-      return true;
+      return TRUE;
     }
 
   h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
   ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;
 
-  return true;
+  return TRUE;
 }
 
 /* Allocate space in the .plt for entries that won't have relocations.
    ie. pic_call and plabel entries.  */
 
-static boolean
+static bfd_boolean
 allocate_plt_static (h, inf)
      struct elf_link_hash_entry *h;
      PTR inf;
@@ -2032,7 +1999,7 @@ allocate_plt_static (h, inf)
   asection *s;
 
   if (h->root.type == bfd_link_hash_indirect)
-    return true;
+    return TRUE;
 
   if (h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
@@ -2058,7 +2025,7 @@ allocate_plt_static (h, inf)
          && h->type != STT_PARISC_MILLI)
        {
          if (! bfd_elf32_link_record_dynamic_symbol (info, h))
-           return false;
+           return FALSE;
        }
 
       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
@@ -2090,13 +2057,13 @@ allocate_plt_static (h, inf)
       h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Allocate space in .plt, .got and associated reloc sections for
    global syms.  */
 
-static boolean
+static bfd_boolean
 allocate_dynrelocs (h, inf)
      struct elf_link_hash_entry *h;
      PTR inf;
@@ -2108,7 +2075,7 @@ allocate_dynrelocs (h, inf)
   struct elf32_hppa_dyn_reloc_entry *p;
 
   if (h->root.type == bfd_link_hash_indirect)
-    return true;
+    return TRUE;
 
   if (h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
@@ -2139,7 +2106,7 @@ allocate_dynrelocs (h, inf)
          && h->type != STT_PARISC_MILLI)
        {
          if (! bfd_elf32_link_record_dynamic_symbol (info, h))
-           return false;
+           return FALSE;
        }
 
       s = htab->sgot;
@@ -2158,7 +2125,7 @@ allocate_dynrelocs (h, inf)
 
   eh = (struct elf32_hppa_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
-    return true;
+    return TRUE;
 
   /* If this is a -Bsymbolic shared link, then we need to discard all
      space allocated for dynamic pc-relative relocs against symbols
@@ -2205,7 +2172,7 @@ allocate_dynrelocs (h, inf)
              && h->type != STT_PARISC_MILLI)
            {
              if (! bfd_elf32_link_record_dynamic_symbol (info, h))
-               return false;
+               return FALSE;
            }
 
          /* If that succeeded, we know we'll be keeping all the
@@ -2215,7 +2182,7 @@ allocate_dynrelocs (h, inf)
        }
 
       eh->dyn_relocs = NULL;
-      return true;
+      return TRUE;
 
     keep: ;
     }
@@ -2227,7 +2194,7 @@ allocate_dynrelocs (h, inf)
       sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela);
     }
 
-  return true;
+  return TRUE;
 }
 
 /* This function is called via elf_link_hash_traverse to force
@@ -2237,7 +2204,7 @@ allocate_dynrelocs (h, inf)
    for all dynamic symbols.  Arguably, this is a bug in
    elf_adjust_dynamic_symbol.  */
 
-static boolean
+static bfd_boolean
 clobber_millicode_symbols (h, info)
      struct elf_link_hash_entry *h;
      struct bfd_link_info *info;
@@ -2248,14 +2215,14 @@ clobber_millicode_symbols (h, info)
   if (h->type == STT_PARISC_MILLI
       && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
     {
-      elf32_hppa_hide_symbol (info, h, true);
+      elf32_hppa_hide_symbol (info, h, TRUE);
     }
-  return true;
+  return TRUE;
 }
 
 /* Find any dynamic relocs that apply to read-only sections.  */
 
-static boolean
+static bfd_boolean
 readonly_dynrelocs (h, inf)
      struct elf_link_hash_entry *h;
      PTR inf;
@@ -2278,15 +2245,15 @@ readonly_dynrelocs (h, inf)
          info->flags |= DF_TEXTREL;
 
          /* Not an error, just cut short the traversal.  */
-         return false;
+         return FALSE;
        }
     }
-  return true;
+  return TRUE;
 }
 
 /* Set the sizes of the dynamic sections.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_size_dynamic_sections (output_bfd, info)
      bfd *output_bfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info;
@@ -2295,7 +2262,7 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
   bfd *dynobj;
   bfd *ibfd;
   asection *s;
-  boolean relocs;
+  bfd_boolean relocs;
 
   htab = hppa_link_hash_table (info);
   dynobj = htab->elf.dynobj;
@@ -2431,7 +2398,7 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */
-  relocs = false;
+  relocs = FALSE;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LINKER_CREATED) == 0)
@@ -2463,7 +2430,7 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
              /* Remember whether there are any reloc sections other
                 than .rela.plt.  */
              if (s != htab->srelplt)
-               relocs = true;
+               relocs = TRUE;
 
              /* We use the reloc_count field as a counter if we need
                 to copy relocs into the output file.  */
@@ -2495,7 +2462,7 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
         we may not fill in all the reloc sections.  */
       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
       if (s->contents == NULL && s->_raw_size != 0)
-       return false;
+       return FALSE;
     }
 
   if (htab->elf.dynamic_sections_created)
@@ -2508,7 +2475,7 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
   bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
 
       if (!add_dynamic_entry (DT_PLTGOT, 0))
-       return false;
+       return FALSE;
 
       /* Add some entries to the .dynamic section.  We fill in the
         values later, in elf32_hppa_finish_dynamic_sections, but we
@@ -2518,7 +2485,7 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
       if (!info->shared)
        {
          if (!add_dynamic_entry (DT_DEBUG, 0))
-           return false;
+           return FALSE;
        }
 
       if (htab->srelplt->_raw_size != 0)
@@ -2526,7 +2493,7 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
          if (!add_dynamic_entry (DT_PLTRELSZ, 0)
              || !add_dynamic_entry (DT_PLTREL, DT_RELA)
              || !add_dynamic_entry (DT_JMPREL, 0))
-           return false;
+           return FALSE;
        }
 
       if (relocs)
@@ -2534,7 +2501,7 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
          if (!add_dynamic_entry (DT_RELA, 0)
              || !add_dynamic_entry (DT_RELASZ, 0)
              || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
-           return false;
+           return FALSE;
 
          /* If any dynamic relocs apply to a read-only section,
             then we need a DT_TEXTREL entry.  */
@@ -2545,20 +2512,20 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
          if ((info->flags & DF_TEXTREL) != 0)
            {
              if (!add_dynamic_entry (DT_TEXTREL, 0))
-               return false;
+               return FALSE;
            }
        }
     }
 #undef add_dynamic_entry
 
-  return true;
+  return TRUE;
 }
 
 /* External entry points for sizing and building linker stubs.  */
 
 /* Set up various things so that we can make a list of input sections
    for each output section included in the link.  Returns -1 on error,
-   0 when no stubs will be needed, and 1 on success. */
+   0 when no stubs will be needed, and 1 on success.  */
 
 int
 elf32_hppa_setup_section_lists (output_bfd, info)
@@ -2671,7 +2638,7 @@ static void
 group_sections (htab, stub_group_size, stubs_always_before_branch)
      struct elf32_hppa_link_hash_table *htab;
      bfd_size_type stub_group_size;
-     boolean stubs_always_before_branch;
+     bfd_boolean stubs_always_before_branch;
 {
   asection **list = htab->input_list + htab->top_index;
   do
@@ -2684,12 +2651,15 @@ group_sections (htab, stub_group_size, stubs_always_before_branch)
          asection *curr;
          asection *prev;
          bfd_size_type total;
+         bfd_boolean big_sec;
 
          curr = tail;
          if (tail->_cooked_size)
            total = tail->_cooked_size;
          else
            total = tail->_raw_size;
+         big_sec = total >= stub_group_size;
+
          while ((prev = PREV_SEC (curr)) != NULL
                 && ((total += curr->output_offset - prev->output_offset)
                     < stub_group_size))
@@ -2717,8 +2687,11 @@ group_sections (htab, stub_group_size, stubs_always_before_branch)
          while (tail != curr && (tail = prev) != NULL);
 
          /* But wait, there's more!  Input sections up to 240000
-            bytes before the stub section can be handled by it too.  */
-         if (!stubs_always_before_branch)
+            bytes before the stub section can be handled by it too.
+            Don't do this if we have a really large section after the
+            stubs, as adding more stubs increases the chance that
+            branches may not reach into the stub section.  */
+         if (!stubs_always_before_branch && !big_sec)
            {
              total = 0;
              while (prev != NULL
@@ -2770,68 +2743,26 @@ get_local_syms (output_bfd, input_bfd, info)
        input_bfd = input_bfd->link_next, bfd_indx++)
     {
       Elf_Internal_Shdr *symtab_hdr;
-      Elf_Internal_Shdr *shndx_hdr;
-      Elf_Internal_Sym *isym;
-      Elf32_External_Sym *ext_syms, *esym, *end_sy;
-      Elf_External_Sym_Shndx *shndx_buf, *shndx;
-      bfd_size_type sec_size;
 
       /* We'll need the symbol table in a second.  */
       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
       if (symtab_hdr->sh_info == 0)
        continue;
 
-      /* We need an array of the local symbols attached to the input bfd.
-        Unfortunately, we're going to have to read & swap them in.  */
-      sec_size = symtab_hdr->sh_info;
-      sec_size *= sizeof (Elf_Internal_Sym);
-      local_syms = (Elf_Internal_Sym *) bfd_malloc (sec_size);
+      /* We need an array of the local symbols attached to the input bfd.  */
+      local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
       if (local_syms == NULL)
-       return -1;
-
-      all_local_syms[bfd_indx] = local_syms;
-      sec_size = symtab_hdr->sh_info;
-      sec_size *= sizeof (Elf32_External_Sym);
-      ext_syms = (Elf32_External_Sym *) bfd_malloc (sec_size);
-      if (ext_syms == NULL)
-       return -1;
-
-      if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-         || bfd_bread ((PTR) ext_syms, sec_size, input_bfd) != sec_size)
        {
-       error_ret_free_ext_syms:
-         free (ext_syms);
-         return -1;
-       }
-
-      shndx_buf = NULL;
-      shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr;
-      if (shndx_hdr->sh_size != 0)
-       {
-         sec_size = symtab_hdr->sh_info;
-         sec_size *= sizeof (Elf_External_Sym_Shndx);
-         shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (sec_size);
-         if (shndx_buf == NULL)
-           goto error_ret_free_ext_syms;
-
-         if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
-             || bfd_bread ((PTR) shndx_buf, sec_size, input_bfd) != sec_size)
-           {
-             free (shndx_buf);
-             goto error_ret_free_ext_syms;
-           }
+         local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+                                            symtab_hdr->sh_info, 0,
+                                            NULL, NULL, NULL);
+         /* Cache them for elf_link_input_bfd.  */
+         symtab_hdr->contents = (unsigned char *) local_syms;
        }
+      if (local_syms == NULL)
+       return -1;
 
-      /* Swap the local symbols in.  */
-      for (esym = ext_syms, end_sy = esym + symtab_hdr->sh_info,
-            isym = local_syms, shndx = shndx_buf;
-          esym < end_sy;
-          esym++, isym++, shndx = (shndx ? shndx + 1 : NULL))
-       bfd_elf32_swap_symbol_in (input_bfd, esym, shndx, isym);
-
-      /* Now we can free the external symbols.  */
-      free (shndx_buf);
-      free (ext_syms);
+      all_local_syms[bfd_indx] = local_syms;
 
       if (info->shared && htab->multi_subspace)
        {
@@ -2879,7 +2810,7 @@ get_local_syms (output_bfd, input_bfd, info)
                  stub_name = hash->elf.root.root.string;
                  stub_entry = hppa_stub_hash_lookup (&htab->stub_hash_table,
                                                      stub_name,
-                                                     false, false);
+                                                     FALSE, FALSE);
                  if (stub_entry == NULL)
                    {
                      stub_entry = hppa_add_stub (stub_name, sec, htab);
@@ -2912,21 +2843,20 @@ get_local_syms (output_bfd, input_bfd, info)
    PC-relative calls to a target that is unreachable with a "bl"
    instruction.  */
 
-boolean
+bfd_boolean
 elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
                       add_stub_section, layout_sections_again)
      bfd *output_bfd;
      bfd *stub_bfd;
      struct bfd_link_info *info;
-     boolean multi_subspace;
+     bfd_boolean multi_subspace;
      bfd_signed_vma group_size;
      asection * (*add_stub_section) PARAMS ((const char *, asection *));
      void (*layout_sections_again) PARAMS ((void));
 {
   bfd_size_type stub_group_size;
-  boolean stubs_always_before_branch;
-  boolean stub_changed;
-  boolean ret = 0;
+  bfd_boolean stubs_always_before_branch;
+  bfd_boolean stub_changed;
   struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info);
 
   /* Stash our params away.  */
@@ -2942,11 +2872,22 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
   if (stub_group_size == 1)
     {
       /* Default values.  */
-      stub_group_size = 7680000;
-      if (htab->has_17bit_branch || htab->multi_subspace)
-       stub_group_size = 240000;
-      if (htab->has_12bit_branch)
-       stub_group_size = 7500;
+      if (stubs_always_before_branch)
+       {
+         stub_group_size = 7680000;
+         if (htab->has_17bit_branch || htab->multi_subspace)
+           stub_group_size = 240000;
+         if (htab->has_12bit_branch)
+           stub_group_size = 7500;
+       }
+      else
+       {
+         stub_group_size = 6971392;
+         if (htab->has_17bit_branch || htab->multi_subspace)
+           stub_group_size = 217856;
+         if (htab->has_12bit_branch)
+           stub_group_size = 6808;
+       }
     }
 
   group_sections (htab, stub_group_size, stubs_always_before_branch);
@@ -2956,14 +2897,14 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
     default:
       if (htab->all_local_syms)
        goto error_ret_free_local;
-      return false;
+      return FALSE;
 
     case 0:
-      stub_changed = false;
+      stub_changed = FALSE;
       break;
 
     case 1:
-      stub_changed = true;
+      stub_changed = TRUE;
       break;
     }
 
@@ -2993,10 +2934,7 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
               section != NULL;
               section = section->next)
            {
-             Elf_Internal_Shdr *input_rel_hdr;
-             Elf32_External_Rela *external_relocs, *erelaend, *erela;
              Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
-             bfd_size_type amt;
 
              /* If there aren't any relocs, then there's nothing more
                 to do.  */
@@ -3010,47 +2948,13 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
                  || section->output_section->owner != output_bfd)
                continue;
 
-             /* Allocate space for the external relocations.  */
-             amt = section->reloc_count;
-             amt *= sizeof (Elf32_External_Rela);
-             external_relocs = (Elf32_External_Rela *) bfd_malloc (amt);
-             if (external_relocs == NULL)
-               {
-                 goto error_ret_free_local;
-               }
-
-             /* Likewise for the internal relocations.  */
-             amt = section->reloc_count;
-             amt *= sizeof (Elf_Internal_Rela);
-             internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
+             /* Get the relocs.  */
+             internal_relocs
+               = _bfd_elf32_link_read_relocs (input_bfd, section, NULL,
+                                              (Elf_Internal_Rela *) NULL,
+                                              info->keep_memory);
              if (internal_relocs == NULL)
-               {
-                 free (external_relocs);
-                 goto error_ret_free_local;
-               }
-
-             /* Read in the external relocs.  */
-             input_rel_hdr = &elf_section_data (section)->rel_hdr;
-             if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0
-                 || bfd_bread ((PTR) external_relocs,
-                               input_rel_hdr->sh_size,
-                               input_bfd) != input_rel_hdr->sh_size)
-               {
-                 free (external_relocs);
-               error_ret_free_internal:
-                 free (internal_relocs);
-                 goto error_ret_free_local;
-               }
-
-             /* Swap in the relocs.  */
-             erela = external_relocs;
-             erelaend = erela + section->reloc_count;
-             irela = internal_relocs;
-             for (; erela < erelaend; erela++, irela++)
-               bfd_elf32_swap_reloca_in (input_bfd, erela, irela);
-
-             /* We're done with the external relocs, free them.  */
-             free (external_relocs);
+               goto error_ret_free_local;
 
              /* Now examine each relocation.  */
              irela = internal_relocs;
@@ -3073,7 +2977,10 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
                  if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
                    {
                      bfd_set_error (bfd_error_bad_value);
-                     goto error_ret_free_internal;
+                   error_ret_free_internal:
+                     if (elf_section_data (section)->relocs == NULL)
+                       free (internal_relocs);
+                     goto error_ret_free_local;
                    }
 
                  /* Only look for stubs on call instructions.  */
@@ -3164,7 +3071,7 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
 
                  stub_entry = hppa_stub_hash_lookup (&htab->stub_hash_table,
                                                      stub_name,
-                                                     false, false);
+                                                     FALSE, FALSE);
                  if (stub_entry != NULL)
                    {
                      /* The proper stub has already been created.  */
@@ -3176,7 +3083,7 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
                  if (stub_entry == NULL)
                    {
                      free (stub_name);
-                     goto error_ret_free_local;
+                     goto error_ret_free_internal;
                    }
 
                  stub_entry->target_value = sym_value;
@@ -3190,11 +3097,12 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
                        stub_entry->stub_type = hppa_stub_long_branch_shared;
                    }
                  stub_entry->h = hash;
-                 stub_changed = true;
+                 stub_changed = TRUE;
                }
 
              /* We're done with the internal relocs, free them.  */
-             free (internal_relocs);
+             if (elf_section_data (section)->relocs == NULL)
+               free (internal_relocs);
            }
        }
 
@@ -3215,24 +3123,21 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
 
       /* Ask the linker to do its stuff.  */
       (*htab->layout_sections_again) ();
-      stub_changed = false;
+      stub_changed = FALSE;
     }
 
-  ret = true;
+  free (htab->all_local_syms);
+  return TRUE;
 
  error_ret_free_local:
-  while (htab->bfd_count-- > 0)
-    if (htab->all_local_syms[htab->bfd_count])
-      free (htab->all_local_syms[htab->bfd_count]);
   free (htab->all_local_syms);
-
-  return ret;
+  return FALSE;
 }
 
 /* For a final link, this function is called after we have sized the
    stubs to provide a value for __gp.  */
 
-boolean
+bfd_boolean
 elf32_hppa_set_gp (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -3243,7 +3148,7 @@ elf32_hppa_set_gp (abfd, info)
   struct elf32_hppa_link_hash_table *htab;
 
   htab = hppa_link_hash_table (info);
-  h = bfd_link_hash_lookup (&htab->elf.root, "$global$", false, false, false);
+  h = bfd_link_hash_lookup (&htab->elf.root, "$global$", FALSE, FALSE, FALSE);
 
   if (h != NULL
       && (h->type == bfd_link_hash_defined
@@ -3319,7 +3224,7 @@ elf32_hppa_set_gp (abfd, info)
     gp_val += sec->output_section->vma + sec->output_offset;
 
   elf_gp (abfd) = gp_val;
-  return true;
+  return TRUE;
 }
 
 /* Build all the stubs associated with the current output file.  The
@@ -3328,7 +3233,7 @@ elf32_hppa_set_gp (abfd, info)
    functions here.  This function is called via hppaelf_finish in the
    linker.  */
 
-boolean
+bfd_boolean
 elf32_hppa_build_stubs (info)
      struct bfd_link_info *info;
 {
@@ -3348,7 +3253,7 @@ elf32_hppa_build_stubs (info)
       size = stub_sec->_raw_size;
       stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, size);
       if (stub_sec->contents == NULL && size != 0)
-       return false;
+       return FALSE;
       stub_sec->_raw_size = 0;
     }
 
@@ -3356,19 +3261,19 @@ elf32_hppa_build_stubs (info)
   table = &htab->stub_hash_table;
   bfd_hash_traverse (table, hppa_build_one_stub, info);
 
-  return true;
+  return TRUE;
 }
 
 /* Perform a final link.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_final_link (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
   /* Invoke the regular ELF linker to do all the work.  */
   if (!bfd_elf32_bfd_final_link (abfd, info))
-    return false;
+    return FALSE;
 
   /* If we're producing a final executable, sort the contents of the
      unwind section.  */
@@ -3493,15 +3398,14 @@ final_link_relocate (input_section, contents, rel, value, htab, sym_sec, h)
     case R_PARISC_DPREL14R:
     case R_PARISC_DPREL14F:
     /* For all the DP relative relocations, we need to examine the symbol's
-       section.  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 when a variable's "constness"
+       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)
-       break;
-      if ((sym_sec->flags & SEC_CODE) != 0)
+      if (sym_sec == NULL || (sym_sec->flags & SEC_CODE) != 0)
        {
          if ((insn & ((0x3f << 26) | (0x1f << 21)))
              == (((int) OP_ADDIL << 26) | (27 << 21)))
@@ -3671,7 +3575,7 @@ final_link_relocate (input_section, contents, rel, value, htab, sym_sec, h)
 
 /* Relocate an HPPA ELF section.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                             contents, relocs, local_syms, local_sections)
      bfd *output_bfd;
@@ -3689,6 +3593,9 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
+  if (info->relocateable)
+    return TRUE;
+
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
   htab = hppa_link_hash_table (info);
@@ -3707,44 +3614,25 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
       bfd_vma relocation;
       bfd_reloc_status_type r;
       const char *sym_name;
-      boolean plabel;
-      boolean warned_undef;
+      bfd_boolean plabel;
+      bfd_boolean warned_undef;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
        {
          bfd_set_error (bfd_error_bad_value);
-         return false;
+         return FALSE;
        }
       if (r_type == (unsigned int) R_PARISC_GNU_VTENTRY
          || r_type == (unsigned int) R_PARISC_GNU_VTINHERIT)
        continue;
 
-      r_symndx = ELF32_R_SYM (rel->r_info);
-
-      if (info->relocateable)
-       {
-         /* This is a relocatable link.  We don't have to change
-            anything, unless the reloc is against a section symbol,
-            in which case we have to adjust according to where the
-            section symbol winds up in the output section.  */
-         if (r_symndx < symtab_hdr->sh_info)
-           {
-             sym = local_syms + r_symndx;
-             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-               {
-                 sym_sec = local_sections[r_symndx];
-                 rel->r_addend += sym_sec->output_offset;
-               }
-           }
-         continue;
-       }
-
       /* This is a final link.  */
+      r_symndx = ELF32_R_SYM (rel->r_info);
       h = NULL;
       sym = NULL;
       sym_sec = NULL;
-      warned_undef = false;
+      warned_undef = FALSE;
       if (r_symndx < symtab_hdr->sh_info)
        {
          /* This is a local symbol, h defaults to NULL.  */
@@ -3782,22 +3670,19 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                   && ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
                   && h->elf.type != STT_PARISC_MILLI)
            {
-             if (info->symbolic && !info->allow_shlib_undefined)
-               {
-                 if (!((*info->callbacks->undefined_symbol)
-                       (info, h->elf.root.root.string, input_bfd,
-                        input_section, rel->r_offset, false)))
-                   return false;
-                 warned_undef = true;
-               }
+             if (!((*info->callbacks->undefined_symbol)
+                   (info, h->elf.root.root.string, input_bfd,
+                    input_section, rel->r_offset, FALSE)))
+               return FALSE;
+             warned_undef = TRUE;
            }
          else
            {
              if (!((*info->callbacks->undefined_symbol)
                    (info, h->elf.root.root.string, input_bfd,
-                    input_section, rel->r_offset, true)))
-               return false;
-             warned_undef = true;
+                    input_section, rel->r_offset, TRUE)))
+               return FALSE;
+             warned_undef = TRUE;
            }
        }
 
@@ -3812,13 +3697,13 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_PARISC_DLTIND21L:
          {
            bfd_vma off;
-           boolean do_got = 0;
+           bfd_boolean do_got = 0;
 
            /* Relocation is to the entry for this symbol in the
               global offset table.  */
            if (h != NULL)
              {
-               boolean dyn;
+               bfd_boolean dyn;
 
                off = h->elf.got.offset;
                dyn = htab->elf.dynamic_sections_created;
@@ -3867,16 +3752,16 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                       In this case it is relative to the base of the
                       object because the symbol index is zero.  */
                    Elf_Internal_Rela outrel;
-                   asection *srelgot = htab->srelgot;
-                   Elf32_External_Rela *loc;
+                   bfd_byte *loc;
+                   asection *s = htab->srelgot;
 
                    outrel.r_offset = (off
                                       + htab->sgot->output_offset
                                       + htab->sgot->output_section->vma);
                    outrel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
                    outrel.r_addend = relocation;
-                   loc = (Elf32_External_Rela *) srelgot->contents;
-                   loc += srelgot->reloc_count++;
+                   loc = s->contents;
+                   loc += s->reloc_count++ * sizeof (Elf32_External_Rela);
                    bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
                  }
                else
@@ -3907,7 +3792,7 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
          if (htab->elf.dynamic_sections_created)
            {
              bfd_vma off;
-             boolean do_plt = 0;
+             bfd_boolean do_plt = 0;
 
              /* If we have a global symbol with a PLT slot, then
                 redirect this relocation to it.  */
@@ -3957,16 +3842,16 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                      /* Output a dynamic IPLT relocation for this
                         PLT entry.  */
                      Elf_Internal_Rela outrel;
-                     asection *srelplt = htab->srelplt;
-                     Elf32_External_Rela *loc;
+                     bfd_byte *loc;
+                     asection *s = htab->srelplt;
 
                      outrel.r_offset = (off
                                         + htab->splt->output_offset
                                         + htab->splt->output_section->vma);
                      outrel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT);
                      outrel.r_addend = relocation;
-                     loc = (Elf32_External_Rela *) srelplt->contents;
-                     loc += srelplt->reloc_count++;
+                     loc = s->contents;
+                     loc += s->reloc_count++ * sizeof (Elf32_External_Rela);
                      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
                    }
                  else
@@ -4049,9 +3934,9 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                      || h->elf.root.type == bfd_link_hash_undefined)))
            {
              Elf_Internal_Rela outrel;
-             boolean skip;
+             bfd_boolean skip;
              asection *sreloc;
-             Elf32_External_Rela *loc;
+             bfd_byte *loc;
 
              /* When generating a shared object, these relocations
                 are copied into the output file to be resolved at run
@@ -4120,8 +4005,8 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
              if (sreloc == NULL)
                abort ();
 
-             loc = (Elf32_External_Rela *) sreloc->contents;
-             loc += sreloc->reloc_count++;
+             loc = sreloc->contents;
+             loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
              bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
            }
          break;
@@ -4144,7 +4029,7 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                                                      symtab_hdr->sh_link,
                                                      sym->st_name);
          if (sym_name == NULL)
-           return false;
+           return FALSE;
          if (*sym_name == '\0')
            sym_name = bfd_section_name (input_bfd, sym_sec);
        }
@@ -4163,7 +4048,7 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                 howto->name,
                 sym_name);
              bfd_set_error (bfd_error_bad_value);
-             return false;
+             return FALSE;
            }
        }
       else
@@ -4171,17 +4056,17 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
          if (!((*info->callbacks->reloc_overflow)
                (info, sym_name, howto->name, (bfd_vma) 0,
                 input_bfd, input_section, rel->r_offset)))
-           return false;
+           return FALSE;
        }
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
      bfd *output_bfd;
      struct bfd_link_info *info;
@@ -4219,7 +4104,7 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
       if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
        {
          Elf_Internal_Rela rel;
-         Elf32_External_Rela *loc;
+         bfd_byte *loc;
 
          /* Create a dynamic IPLT relocation for this entry.  */
          rel.r_offset = (h->plt.offset
@@ -4238,8 +4123,8 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
              rel.r_addend = value;
            }
 
-         loc = (Elf32_External_Rela *) htab->srelplt->contents;
-         loc += htab->srelplt->reloc_count++;
+         loc = htab->srelplt->contents;
+         loc += htab->srelplt->reloc_count++ * sizeof (Elf32_External_Rela);
          bfd_elf32_swap_reloca_out (htab->splt->output_section->owner,
                                     &rel, loc);
        }
@@ -4264,7 +4149,7 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
   if (h->got.offset != (bfd_vma) -1)
     {
       Elf_Internal_Rela rel;
-      Elf32_External_Rela *loc;
+      bfd_byte *loc;
 
       /* This symbol has an entry in the global offset table.  Set it
         up.  */
@@ -4297,8 +4182,8 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
          rel.r_addend = 0;
        }
 
-      loc = (Elf32_External_Rela *) htab->srelgot->contents;
-      loc += htab->srelgot->reloc_count++;
+      loc = htab->srelgot->contents;
+      loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
       bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
     }
 
@@ -4306,7 +4191,7 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
     {
       asection *s;
       Elf_Internal_Rela rel;
-      Elf32_External_Rela *loc;
+      bfd_byte *loc;
 
       /* This symbol needs a copy reloc.  Set it up.  */
 
@@ -4322,7 +4207,7 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
                      + h->root.u.def.section->output_section->vma);
       rel.r_addend = 0;
       rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_COPY);
-      loc = (Elf32_External_Rela *) s->contents + s->reloc_count++;
+      loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
       bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
     }
 
@@ -4334,7 +4219,7 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
       sym->st_shndx = SHN_ABS;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Used to decide how to sort relocs in an optimal manner for the
@@ -4360,7 +4245,7 @@ elf32_hppa_reloc_type_class (rela)
 
 /* Finish up the dynamic sections.  */
 
-static boolean
+static bfd_boolean
 elf32_hppa_finish_dynamic_sections (output_bfd, info)
      bfd *output_bfd;
      struct bfd_link_info *info;
@@ -4407,23 +4292,28 @@ elf32_hppa_finish_dynamic_sections (output_bfd, info)
 
            case DT_PLTRELSZ:
              s = htab->srelplt;
-             if (s->_cooked_size != 0)
-               dyn.d_un.d_val = s->_cooked_size;
-             else
-               dyn.d_un.d_val = s->_raw_size;
+             dyn.d_un.d_val = s->_raw_size;
              break;
 
            case DT_RELASZ:
              /* Don't count procedure linkage table relocs in the
                 overall reloc count.  */
-             if (htab->srelplt != NULL)
-               {
-                 s = htab->srelplt->output_section;
-                 if (s->_cooked_size != 0)
-                   dyn.d_un.d_val -= s->_cooked_size;
-                 else
-                   dyn.d_un.d_val -= s->_raw_size;
-               }
+             s = htab->srelplt;
+             if (s == NULL)
+               continue;
+             dyn.d_un.d_val -= s->_raw_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->_raw_size;
              break;
            }
 
@@ -4470,12 +4360,12 @@ elf32_hppa_finish_dynamic_sections (output_bfd, info)
            {
              (*_bfd_error_handler)
                (_(".got section not immediately after .plt section"));
-             return false;
+             return FALSE;
            }
        }
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Tweak the OSABI field of the elf header.  */
@@ -4548,6 +4438,7 @@ elf32_hppa_elf_get_symbol_type (elf_sym, type)
 #define elf_backend_plt_readonly            0
 #define elf_backend_want_plt_sym            0
 #define elf_backend_got_header_size         8
+#define elf_backend_rela_normal                     1
 
 #define TARGET_BIG_SYM         bfd_elf32_hppa_vec
 #define TARGET_BIG_NAME                "elf32-hppa"
This page took 0.06025 seconds and 4 git commands to generate.