]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf32-hppa.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / bfd / elf32-hppa.c
index d362b5839687e6b38a32e88f6d9d5a01de033576..784c699971b79d8774526b6f4787e7d7b731fb74 100644 (file)
@@ -1,5 +1,6 @@
 /* BFD back-end for HP PA-RISC ELF files.
-   Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+   Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 1997
+   Free Software Foundation, Inc.
 
    Written by
 
@@ -21,15 +22,23 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "obstack.h"
-#include "libelf.h"
+#include "elf-bfd.h"
 
+/* The internal type of a symbol table extension entry.  */
+typedef unsigned long symext_entryS;
+
+/* The external type of a symbol table extension entry.  */
+#define ELF32_PARISC_SX_SIZE (4)
+#define ELF32_PARISC_SX_GET(bfd, addr) bfd_h_get_32 ((bfd), (addr))
+#define ELF32_PARISC_SX_PUT(bfd, val, addr) \
+  bfd_h_put_32 ((bfd), (val), (addr))
 
 /* HPPA symbol table extension entry types */
 enum elf32_hppa_symextn_types
@@ -58,10 +67,6 @@ enum elf32_hppa_symextn_types
 
 #define SYMEXTN_SECTION_NAME ".PARISC.symext"
 
-/* FIXME.  Are these external?  (For example used by GAS?).  If so the
-   names need to change to avoid namespace pollution, if not they should
-   be moved into elf32-hppa.c.  */
-typedef unsigned long symext_entryS;
 struct symext_chain
   {
     symext_entryS entry;
@@ -160,8 +165,6 @@ struct elf32_hppa_link_hash_table
   int global_sym_defined;
 };
 
-typedef unsigned int symextn_entry;
-
 /* FIXME.  */
 #define ARGUMENTS      0
 #define RETURN_VALUE   1
@@ -207,17 +210,17 @@ static unsigned long hppa_elf_relocate_insn
 static bfd_reloc_status_type hppa_elf_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd*, char **));
 
-static CONST reloc_howto_type * elf_hppa_reloc_type_lookup
+static reloc_howto_type * elf_hppa_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 
 static boolean elf32_hppa_set_section_contents
   PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type));
 
-static void elf_info_to_howto
+static void elf32_hppa_info_to_howto
   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
 
 static boolean elf32_hppa_backend_symbol_table_processing
-  PARAMS ((bfd *, elf_symbol_type *, int));
+  PARAMS ((bfd *, elf_symbol_type *, unsigned int));
 
 static void elf32_hppa_backend_begin_write_processing
   PARAMS ((bfd *, struct bfd_link_info *));
@@ -232,14 +235,14 @@ static void add_entry_to_symext_chain
 static void
 elf_hppa_tc_make_sections PARAMS ((bfd *, symext_chainS *));
 
-static boolean hppa_elf_is_local_label PARAMS ((bfd *, asymbol *));
+static boolean hppa_elf_is_local_label_name PARAMS ((bfd *, const char *));
 
 static boolean elf32_hppa_add_symbol_hook
   PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
           const char **, flagword *, asection **, bfd_vma *));
 
 static bfd_reloc_status_type elf32_hppa_bfd_final_link_relocate
-  PARAMS ((const reloc_howto_type *, bfd *, bfd *, asection *,
+  PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *,
           bfd_byte *, bfd_vma, bfd_vma, bfd_vma, struct bfd_link_info *,
           asection *, const char *, int));
 
@@ -272,7 +275,7 @@ elf32_hppa_build_one_stub PARAMS ((struct bfd_hash_entry *, PTR));
 static boolean
 elf32_hppa_read_symext_info
   PARAMS ((bfd *, Elf_Internal_Shdr *, struct elf32_hppa_args_hash_table *,
-          Elf_Internal_Sym *, boolean, boolean));
+          Elf_Internal_Sym *));
 
 static unsigned int elf32_hppa_size_of_stub
   PARAMS ((unsigned int, unsigned int, bfd_vma, bfd_vma, const char *));
@@ -294,7 +297,9 @@ static boolean elf32_hppa_link_output_symbol_hook
 static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
 {
   {R_PARISC_NONE, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_NONE"},
-  {R_PARISC_DIR32, 0, 0, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR32"},
+  /* The values in DIR32 are to placate the check in
+     _bfd_stab_section_find_nearest_line.  */
+  {R_PARISC_DIR32, 0, 2, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR32", false, 0, 0xffffffff, false},
   {R_PARISC_DIR21L, 0, 0, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR21L"},
   {R_PARISC_DIR17R, 0, 0, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR17R"},
   {R_PARISC_DIR17F, 0, 0, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR17F"},
@@ -494,10 +499,10 @@ static CONST arg_reloc_type ret_mismatches[6][6] =
 /* Misc static crud for symbol extension records.  */
 static symext_chainS *symext_rootP;
 static symext_chainS *symext_lastP;
-static int symext_chain_size;
+static bfd_size_type symext_chain_size;
 
 /* FIXME: We should be able to try this static variable!  */
-static symext_entryS *symextn_contents;
+static bfd_byte *symextn_contents;
 
 
 /* For linker stub hash tables.  */
@@ -573,10 +578,7 @@ elf32_hppa_stub_hash_newfunc (entry, table, string)
           bfd_hash_allocate (table,
                              sizeof (struct elf32_hppa_stub_hash_entry)));
   if (ret == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
 
   /* Call the allocation method of the superclass.  */
   ret = ((struct elf32_hppa_stub_hash_entry *)
@@ -628,10 +630,7 @@ elf32_hppa_args_hash_newfunc (entry, table, string)
           bfd_hash_allocate (table,
                              sizeof (struct elf32_hppa_args_hash_entry)));
   if (ret == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
 
   /* Call the allocation method of the superclass.  */
   ret = ((struct elf32_hppa_args_hash_entry *)
@@ -657,10 +656,7 @@ elf32_hppa_link_hash_table_create (abfd)
   ret = ((struct elf32_hppa_link_hash_table *)
         bfd_alloc (abfd, sizeof (struct elf32_hppa_link_hash_table)));
   if (ret == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
                                      _bfd_elf_link_hash_newfunc))
     {
@@ -782,8 +778,8 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
   for (; rel < relend; rel++)
     {
       int r_type;
-      const reloc_howto_type *howto;
-      long r_symndx;
+      reloc_howto_type *howto;
+      unsigned long r_symndx;
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sym_sec;
@@ -839,14 +835,18 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
 
          indx = r_symndx - symtab_hdr->sh_info;
          h = elf_sym_hashes (input_bfd)[indx];
-         if (h->root.type == bfd_link_hash_defined)
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+         if (h->root.type == bfd_link_hash_defined
+             || h->root.type == bfd_link_hash_defweak)
            {
              sym_sec = h->root.u.def.section;
              relocation = (h->root.u.def.value
                            + sym_sec->output_offset
                            + sym_sec->output_section->vma);
            }
-         else if (h->root.type == bfd_link_hash_weak)
+         else if (h->root.type == bfd_link_hash_undefweak)
            relocation = 0;
          else
            {
@@ -854,7 +854,7 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
                    (info, h->root.root.string, input_bfd,
                     input_section, rel->r_offset)))
                return false;
-             relocation = 0;
+             break;
            }
        }
 
@@ -862,9 +862,9 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
        sym_name = h->root.root.string;
       else
        {
-         sym_name = elf_string_from_elf_section (input_bfd,
-                                                 symtab_hdr->sh_link,
-                                                 sym->st_name);
+         sym_name = bfd_elf_string_from_elf_section (input_bfd,
+                                                     symtab_hdr->sh_link,
+                                                     sym->st_name);
          if (sym_name == NULL)
            return false;
          if (*sym_name == '\0')
@@ -888,6 +888,16 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
        {
          switch (r)
            {
+           /* This can happen for DP relative relocs if $global$ is
+              undefined.  This is a panic situation so we don't try
+              to continue.  */
+           case bfd_reloc_undefined:
+           case bfd_reloc_notsupported:
+             if (!((*info->callbacks->undefined_symbol)
+                   (info, "$global$", input_bfd,
+                    input_section, rel->r_offset)))
+               return false;
+             return false;
            case bfd_reloc_dangerous:
              {
                /* We use this return value to indicate that we performed
@@ -932,24 +942,26 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
    relocation with modifications based on format and field.  */
 
 elf32_hppa_reloc_type **
-hppa_elf_gen_reloc_type (abfd, base_type, format, field)
+hppa_elf_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
      bfd *abfd;
      elf32_hppa_reloc_type base_type;
      int format;
      int field;
+     int ignore;
+     asymbol *sym;
 {
   elf32_hppa_reloc_type *finaltype;
   elf32_hppa_reloc_type **final_types;
 
   /* Allocate slots for the BFD relocation.  */
-  final_types = (elf32_hppa_reloc_type **)
-    bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type *) * 2);
+  final_types = ((elf32_hppa_reloc_type **)
+                bfd_alloc (abfd, sizeof (elf32_hppa_reloc_type *) * 2));
   if (final_types == NULL)
     return NULL;
 
   /* Allocate space for the relocation itself.  */
-  finaltype = (elf32_hppa_reloc_type *)
-    bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type));
+  finaltype = ((elf32_hppa_reloc_type *)
+              bfd_alloc (abfd, sizeof (elf32_hppa_reloc_type)));
   if (finaltype == NULL)
     return NULL;
 
@@ -1154,14 +1166,14 @@ elf32_hppa_set_section_contents (abfd, section, location, offset, count)
   if (!strcmp (section->name, ".PARISC.symextn") && !symext_chain_size)
     return true;
   else
-    return bfd_elf32_set_section_contents (abfd, section, location,
-                                          offset, count);
+    return _bfd_elf_set_section_contents (abfd, section, location,
+                                         offset, count);
 }
 
 /* Translate from an elf into field into a howto relocation pointer.  */
 
 static void
-elf_info_to_howto (abfd, cache_ptr, dst)
+elf32_hppa_info_to_howto (abfd, cache_ptr, dst)
      bfd *abfd;
      arelent *cache_ptr;
      Elf32_Internal_Rela *dst;
@@ -1213,7 +1225,7 @@ static bfd_reloc_status_type
 elf32_hppa_bfd_final_link_relocate (howto, input_bfd, output_bfd,
                                    input_section, contents, offset, value,
                                    addend, info, sym_sec, sym_name, is_local)
-     const reloc_howto_type *howto;
+     reloc_howto_type *howto;
      bfd *input_bfd;
      bfd *output_bfd;
      asection *input_section;
@@ -1230,7 +1242,7 @@ elf32_hppa_bfd_final_link_relocate (howto, input_bfd, output_bfd,
   unsigned long r_type = howto->type;
   unsigned long r_format = howto->bitsize;
   unsigned long r_field = e_fsel;
-  bfd_byte *hit_data = contents + offset + input_section->vma;
+  bfd_byte *hit_data = contents + offset;
   boolean r_pcrel = howto->pc_relative;
 
   insn = bfd_get_32 (input_bfd, hit_data);
@@ -1250,9 +1262,14 @@ elf32_hppa_bfd_final_link_relocate (howto, input_bfd, output_bfd,
       if (h == NULL)
        return bfd_reloc_notsupported;
 
+      /* If $global$ isn't a defined symbol, then we're still in deep
+        trouble.  */
+      if (h->root.type != bfd_link_hash_defined)
+       return bfd_reloc_undefined;
+
       sec = h->root.u.def.section;
       elf32_hppa_hash_table (info)->global_value = (h->root.u.def.value
-                                                   + sec->vma
+                                                   + sec->output_section->vma
                                                    + sec->output_offset);
       elf32_hppa_hash_table (info)->global_sym_defined = 1;
     }
@@ -1286,7 +1303,11 @@ elf32_hppa_bfd_final_link_relocate (howto, input_bfd, output_bfd,
     case R_PARISC_DPREL21L:
       r_field = e_lrsel;
       if (sym_sec->flags & SEC_CODE)
-       insn &= ~0x03e00000;
+       {
+         if ((insn & 0xfc000000) >> 26 == 0xa
+              && (insn & 0x03e00000) >> 21 == 0x1b)
+           insn &= ~0x03e00000;
+       }
       else
        value -= elf32_hppa_hash_table (info)->global_value;
       goto do_basic_type_1;
@@ -1334,12 +1355,9 @@ elf32_hppa_bfd_final_link_relocate (howto, input_bfd, output_bfd,
        len = strlen (sym_name) + 1;
        if (is_local)
          len += 9;
-       new_name = malloc (len);
+       new_name = bfd_malloc (len);
        if (!new_name)
-         {
-           bfd_set_error (bfd_error_no_memory);
-           return bfd_reloc_notsupported;
-         }
+         return bfd_reloc_notsupported;
        strcpy (new_name, sym_name);
 
        /* Local symbols have unique IDs.  */
@@ -1381,12 +1399,9 @@ elf32_hppa_bfd_final_link_relocate (howto, input_bfd, output_bfd,
 
            len = strlen (new_name);
            len += 23;
-           stub_name = malloc (len);
+           stub_name = bfd_malloc (len);
            if (!stub_name)
-             {
-               bfd_set_error (bfd_error_no_memory);
-               return bfd_reloc_notsupported;
-             }
+             return bfd_reloc_notsupported;
            elf32_hppa_name_of_stub (caller_args, callee_args,
                                     location, value, stub_name);
            strcat (stub_name, new_name);
@@ -1523,7 +1538,7 @@ do_basic_type_1:
 /* Return the address of the howto table entry to perform the CODE
    relocation for an ARCH machine.  */
 
-static CONST reloc_howto_type *
+static reloc_howto_type *
 elf_hppa_reloc_type_lookup (abfd, code)
      bfd *abfd;
      bfd_reloc_code_real_type code;
@@ -1539,11 +1554,11 @@ elf_hppa_reloc_type_lookup (abfd, code)
 /* Return true if SYM represents a local label symbol.  */
 
 static boolean
-hppa_elf_is_local_label (abfd, sym)
+hppa_elf_is_local_label_name (abfd, name)
      bfd *abfd;
-     asymbol *sym;
+     const char *name;
 {
-  return (sym->name[0] == 'L' && sym->name[1] == '$');
+  return (name[0] == 'L' && name[1] == '$');
 }
 
 /* Do any backend specific processing when beginning to write an object
@@ -1585,7 +1600,7 @@ elf32_hppa_backend_begin_write_processing (abfd, info)
            continue;
 
          /* Yup.  This function symbol needs an entry.  */
-         symext_chain_size += 2 * sizeof (symext_entryS);
+         symext_chain_size += 2 * ELF32_PARISC_SX_SIZE;
        }
     }
   else if (info->relocateable == true)
@@ -1621,9 +1636,9 @@ elf32_hppa_size_symext (gen_entry, in_args)
      struct bfd_hash_entry *gen_entry;
      PTR in_args;
 {
-  unsigned int *sizep = (unsigned int *)in_args;
+  bfd_size_type *sizep = (bfd_size_type *)in_args;
 
-  *sizep += 2 * sizeof (symext_entryS);
+  *sizep += 2 * ELF32_PARISC_SX_SIZE;
   return true;
 }
 
@@ -1665,12 +1680,9 @@ elf32_hppa_link_output_symbol_hook (abfd, info, name, sym, section)
   if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
     len += 9;
 
-  new_name = malloc (len);
+  new_name = bfd_malloc (len);
   if (new_name == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   strcpy (new_name, name);
   if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
@@ -1701,7 +1713,7 @@ elf32_hppa_backend_final_write_processing (abfd, linker)
      boolean linker;
 {
   asection *symextn_sec;
-  unsigned int i, *symtab_map = (unsigned int *) elf_sym_extra (abfd);
+  unsigned int i;
 
   /* Now build the symbol extension section.  */
   if (symext_chain_size == 0)
@@ -1729,7 +1741,7 @@ elf32_hppa_backend_final_write_processing (abfd, linker)
 
          /* Add this symbol's information to the chain.  */
          add_entry_to_symext_chain (abfd, symbol->tc_data.hppa_arg_reloc,
-                                    symtab_map[i], &symext_rootP,
+                                    symbol->symbol.udata.i, &symext_rootP,
                                     &symext_lastP);
        }
     }
@@ -1764,10 +1776,7 @@ add_entry_to_symext_chain (abfd, arg_reloc, sym_idx, symext_root, symext_last)
   /* Allocate memory and initialize this entry.  */
   symextP = (symext_chainS *) bfd_alloc (abfd, sizeof (symext_chainS) * 2);
   if (!symextP)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      abort();                 /* FIXME */
-    }
+    abort();                   /* FIXME */
 
   symextP[0].entry = ELF32_PARISC_SX_WORD (PARISC_SXT_SYMNDX, sym_idx);
   symextP[0].next = &symextP[1];
@@ -1804,17 +1813,15 @@ elf_hppa_tc_make_sections (abfd, symext_root)
 
   /* Grab some memory for the contents of the symbol extension section
      itself.  */
-  symextn_contents = (symext_entryS *) bfd_zalloc (abfd,
-                                                  symextn_sec->_raw_size);
+  symextn_contents = (bfd_byte *) bfd_zalloc (abfd,
+                                             symextn_sec->_raw_size);
   if (!symextn_contents)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      abort();                 /* FIXME */
-    }
+    abort();                   /* FIXME */
 
   /* Fill in the contents of the symbol extension chain.  */
   for (i = 0, symextP = symext_root; symextP; symextP = symextP->next, ++i)
-    symextn_contents[i] = symextP->entry;
+    ELF32_PARISC_SX_PUT (abfd, (bfd_vma) symextP->entry,
+                        symextn_contents + i * ELF32_PARISC_SX_SIZE);
 
   return;
 }
@@ -1827,7 +1834,7 @@ static boolean
 elf32_hppa_backend_symbol_table_processing (abfd, esyms,symcnt)
      bfd *abfd;
      elf_symbol_type *esyms;
-     int symcnt;
+     unsigned int symcnt;
 {
   Elf32_Internal_Shdr *symextn_hdr =
     bfd_elf_find_section (abfd, SYMEXTN_SECTION_NAME);
@@ -1847,26 +1854,25 @@ elf32_hppa_backend_symbol_table_processing (abfd, esyms,symcnt)
   /* Allocate a buffer of the appropriate size for the symextn section.  */
   symextn_hdr->contents = bfd_zalloc(abfd,symextn_hdr->sh_size);
   if (!symextn_hdr->contents)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
-  symextn_hdr->size = symextn_hdr->sh_size;
+    return false;
 
   /* Read in the symextn section.  */
   if (bfd_seek (abfd, symextn_hdr->sh_offset, SEEK_SET) == -1)
     return false;
-  if (bfd_read ((PTR) symextn_hdr->contents, 1, symextn_hdr->size, abfd)
-      != symextn_hdr->size)
+  if (bfd_read ((PTR) symextn_hdr->contents, 1, symextn_hdr->sh_size, abfd)
+      != symextn_hdr->sh_size)
     return false;
 
   /* Parse entries in the symbol extension section, updating the symtab
      entries as we go */
-  for (i = 0; i < symextn_hdr->size / sizeof(symext_entryS); i++)
+  for (i = 0; i < symextn_hdr->sh_size / ELF32_PARISC_SX_SIZE; i++)
     {
-      symext_entryS *seP = ((symext_entryS *)symextn_hdr->contents) + i;
-      unsigned int se_value = ELF32_PARISC_SX_VAL (*seP);
-      unsigned int se_type = ELF32_PARISC_SX_TYPE (*seP);
+      symext_entryS se =
+       ELF32_PARISC_SX_GET (abfd,
+                            ((unsigned char *)symextn_hdr->contents
+                             + i * ELF32_PARISC_SX_SIZE));
+      unsigned int se_value = ELF32_PARISC_SX_VAL (se);
+      unsigned int se_type = ELF32_PARISC_SX_TYPE (se);
 
       switch (se_type)
        {
@@ -1899,17 +1905,14 @@ elf32_hppa_backend_symbol_table_processing (abfd, esyms,symcnt)
    if DO_LOCALS is true; likewise for globals when DO_GLOBALS is true.  */
 
 static boolean
-elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
-                            local_syms, do_locals, do_globals)
+elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table, local_syms)
      bfd *input_bfd;
      Elf_Internal_Shdr *symtab_hdr;
      struct elf32_hppa_args_hash_table *args_hash_table;
      Elf_Internal_Sym *local_syms;
-     boolean do_locals;
-     boolean do_globals;
 {
   asection *symextn_sec;
-  symextn_entry *contents;
+  bfd_byte *contents;
   unsigned int i, n_entries, current_index = 0;
 
   /* Get the symbol extension section for this BFD.  If no section exists
@@ -1926,12 +1929,9 @@ elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
       return true;
     }
 
-  contents = (symextn_entry *) malloc (symextn_sec->_raw_size);
+  contents = (bfd_byte *) bfd_malloc ((size_t) symextn_sec->_raw_size);
   if (contents == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   /* How gross.  We turn off SEC_HAS_CONTENTS for the input symbol extension
      sections to keep the generic ELF/BFD code from trying to do anything
@@ -1950,10 +1950,11 @@ elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
      sections (see above).  */
   symextn_sec->flags &= ~SEC_HAS_CONTENTS;
 
-  n_entries = symextn_sec->_raw_size / sizeof (symextn_entry);
+  n_entries = symextn_sec->_raw_size / ELF32_PARISC_SX_SIZE;
   for (i = 0; i < n_entries; i++)
     {
-      symextn_entry entry = contents[i];
+      symext_entryS entry =
+       ELF32_PARISC_SX_GET (input_bfd, contents + i * ELF32_PARISC_SX_SIZE);
       unsigned int value = ELF32_PARISC_SX_VAL (entry);
       unsigned int type = ELF32_PARISC_SX_TYPE (entry);
       struct elf32_hppa_args_hash_entry *args_hash;
@@ -1974,8 +1975,7 @@ elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
          break;
 
        case PARISC_SXT_ARG_RELOC:
-         if (current_index < symtab_hdr->sh_info
-             && do_locals)
+         if (current_index < symtab_hdr->sh_info)
            {
              Elf_Internal_Shdr *hdr;
              char *new_name;
@@ -1985,14 +1985,13 @@ elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
 
              hdr = elf_elfsections (input_bfd)[local_syms[current_index].st_shndx];
              sym_sec = hdr->bfd_section;
-             sym_name = elf_string_from_elf_section (input_bfd,
+             sym_name = bfd_elf_string_from_elf_section (input_bfd,
                                                      symtab_hdr->sh_link,
                                        local_syms[current_index].st_name);
              len = strlen (sym_name) + 10;
-             new_name = malloc (len);
+             new_name = bfd_malloc (len);
              if (new_name == NULL)
                {
-                 bfd_set_error (bfd_error_no_memory);
                  free (contents);
                  return false;
                }
@@ -2013,8 +2012,7 @@ elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
              args_hash->arg_bits = value;
              break;
            }
-         else if (current_index >= symtab_hdr->sh_info
-                  && do_globals)
+         else if (current_index >= symtab_hdr->sh_info)
            {
              struct elf_link_hash_entry *h;
 
@@ -2481,10 +2479,7 @@ elf32_hppa_build_stubs (stub_bfd, info)
   size = bfd_section_size (stub_bfd, stub_sec);
   stub_sec->contents = (unsigned char *) bfd_zalloc (stub_bfd, size);
   if (stub_sec->contents == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   table = elf32_hppa_hash_table(info)->stub_hash_table;
   table->location = stub_sec->contents;
 
@@ -2508,21 +2503,19 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
      struct bfd_link_info *link_info;
 {
   bfd *input_bfd;
-  asection *section, *stub_sec;
+  asection *section, *stub_sec = 0;
   Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Sym *local_syms, *isym;
+  Elf_Internal_Sym *local_syms, *isym, **all_local_syms;
   Elf32_External_Sym *ext_syms, *esym;
+  unsigned int i, index, bfd_count = 0;
   struct elf32_hppa_stub_hash_table *stub_hash_table = 0;
   struct elf32_hppa_args_hash_table *args_hash_table = 0;
 
   /* Create and initialize the stub hash table.  */
   stub_hash_table = ((struct elf32_hppa_stub_hash_table *)
-                    malloc (sizeof (struct elf32_hppa_stub_hash_table)));
+                    bfd_malloc (sizeof (struct elf32_hppa_stub_hash_table)));
   if (!stub_hash_table)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   if (!elf32_hppa_stub_hash_table_init (stub_hash_table, stub_bfd,
                                        elf32_hppa_stub_hash_newfunc))
@@ -2530,12 +2523,9 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
 
   /* Likewise for the argument location hash table.  */
   args_hash_table = ((struct elf32_hppa_args_hash_table *)
-                    malloc (sizeof (struct elf32_hppa_args_hash_table)));
+                    bfd_malloc (sizeof (struct elf32_hppa_args_hash_table)));
   if (!args_hash_table)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   if (!elf32_hppa_args_hash_table_init (args_hash_table,
                                        elf32_hppa_args_hash_newfunc))
@@ -2545,33 +2535,28 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
   elf32_hppa_hash_table(link_info)->stub_hash_table = stub_hash_table;
   elf32_hppa_hash_table(link_info)->args_hash_table = args_hash_table;
 
-  /* Walk over all the input BFDs adding entries to the args hash table
-     for all the external functions.  */
+  /* Count the number of input BFDs.  */
   for (input_bfd = link_info->input_bfds;
        input_bfd != NULL;
        input_bfd = input_bfd->link_next)
-    {
-      /* We'll need the symbol table in a second.  */
-      symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-      if (symtab_hdr->sh_info == 0)
-       continue;
-
-      if (elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
-                                      NULL, false, true) == false)
-       goto error_return;
-    }
-
-  /* Magic as we know the stub bfd only has one section.  */
-  stub_sec = stub_bfd->sections;
+     bfd_count++;
+
+  /* We want to read in symbol extension records only once.  To do this
+     we need to read in the local symbols in parallel and save them for
+     later use; so hold pointers to the local symbols in an array.  */
+  all_local_syms
+    = (Elf_Internal_Sym **) bfd_malloc (sizeof (Elf_Internal_Sym *)
+                                       * bfd_count);
+  if (all_local_syms == NULL)
+    goto error_return;
+  memset (all_local_syms, 0, sizeof (Elf_Internal_Sym *) * bfd_count);
 
-  /* Now that we have argument location information for all the global
-     functions we can start looking for stubs.  */
-  for (input_bfd = link_info->input_bfds;
+  /* Walk over all the input BFDs adding entries to the args hash table
+     for all the external functions.  */
+  for (input_bfd = link_info->input_bfds, index = 0;
        input_bfd != NULL;
-       input_bfd = input_bfd->link_next)
+       input_bfd = input_bfd->link_next, index++)
     {
-      unsigned int i;
-
       /* We'll need the symbol table in a second.  */
       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
       if (symtab_hdr->sh_info == 0)
@@ -2580,21 +2565,27 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
       /* We need an array of the local symbols attached to the input bfd.
         Unfortunately, we're going to have to read & swap them in.  */
       local_syms
-       = (Elf_Internal_Sym *)malloc (symtab_hdr->sh_info
-                                     * sizeof (Elf_Internal_Sym));
+       = (Elf_Internal_Sym *) bfd_malloc (symtab_hdr->sh_info
+                                          * sizeof (Elf_Internal_Sym));
       if (local_syms == NULL)
        {
-         bfd_set_error (bfd_error_no_memory);
+         for (i = 0; i < bfd_count; i++)
+           if (all_local_syms[i])
+             free (all_local_syms[i]);
+         free (all_local_syms);
          goto error_return;
        }
+      all_local_syms[index] = local_syms;
 
       ext_syms
-       = (Elf32_External_Sym *)malloc (symtab_hdr->sh_info
-                                       * sizeof (Elf32_External_Sym));
+       = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_info
+                                            * sizeof (Elf32_External_Sym));
       if (ext_syms == NULL)
        {
-         bfd_set_error (bfd_error_no_memory);
-         free (local_syms);
+         for (i = 0; i < bfd_count; i++)
+           if (all_local_syms[i])
+             free (all_local_syms[i]);
+         free (all_local_syms);
          goto error_return;
        }
 
@@ -2604,7 +2595,10 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
                        * sizeof (Elf32_External_Sym)), input_bfd)
          != (symtab_hdr->sh_info * sizeof (Elf32_External_Sym)))
        {
-         free (local_syms);
+         for (i = 0; i < bfd_count; i++)
+           if (all_local_syms[i])
+             free (all_local_syms[i]);
+         free (all_local_syms);
          free (ext_syms);
          goto error_return;
        }
@@ -2619,19 +2613,42 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
       free (ext_syms);
 
       if (elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
-                                      local_syms, true, false) == false)
+                                      local_syms) == false)
        {
-         free (local_syms);
+         for (i = 0; i < bfd_count; i++)
+           if (all_local_syms[i])
+             free (all_local_syms[i]);
+         free (all_local_syms);
          goto error_return;
        }
+    }
 
-      /* If generating a relocateable output file, then we don't
-        have to examine the relocs.  */
-      if (link_info->relocateable)
-       {
-         free (local_syms);
-         return true;
-       }
+  /* Magic as we know the stub bfd only has one section.  */
+  stub_sec = stub_bfd->sections;
+
+  /* If generating a relocateable output file, then we don't
+     have to examine the relocs.  */
+  if (link_info->relocateable)
+    {
+      for (i = 0; i < bfd_count; i++)
+       if (all_local_syms[i])
+         free (all_local_syms[i]);
+      free (all_local_syms);
+      return true;
+    }
+
+  /* Now that we have argument location information for all the global
+     functions we can start looking for stubs.  */
+  for (input_bfd = link_info->input_bfds, index = 0;
+       input_bfd != NULL;
+       input_bfd = input_bfd->link_next, index++)
+    {
+      /* We'll need the symbol table in a second.  */
+      symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+      if (symtab_hdr->sh_info == 0)
+       continue;
+
+      local_syms = all_local_syms[index];
 
       /* Walk over each section attached to the input bfd.  */
       for (section = input_bfd->sections;
@@ -2649,22 +2666,29 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
 
          /* Allocate space for the external relocations.  */
          external_relocs
-           = (Elf32_External_Rela *) malloc (section->reloc_count * sizeof (Elf32_External_Rela));
+           = ((Elf32_External_Rela *)
+              bfd_malloc (section->reloc_count
+                          * sizeof (Elf32_External_Rela)));
          if (external_relocs == NULL)
            {
-             bfd_set_error (bfd_error_no_memory);
-             free (local_syms);
+             for (i = 0; i < bfd_count; i++)
+               if (all_local_syms[i])
+                 free (all_local_syms[i]);
+             free (all_local_syms);
              goto error_return;
            }
 
          /* Likewise for the internal relocations.  */
          internal_relocs
-           = (Elf_Internal_Rela *) malloc (section->reloc_count * sizeof (Elf_Internal_Rela));
+           = ((Elf_Internal_Rela *)
+              bfd_malloc (section->reloc_count * sizeof (Elf_Internal_Rela)));
          if (internal_relocs == NULL)
            {
-             bfd_set_error (bfd_error_no_memory);
              free (external_relocs);
-             free (local_syms);
+             for (i = 0; i < bfd_count; i++)
+               if (all_local_syms[i])
+                 free (all_local_syms[i]);
+             free (all_local_syms);
              goto error_return;
            }
 
@@ -2676,7 +2700,10 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
            {
              free (external_relocs);
              free (internal_relocs);
-             free (local_syms);
+             for (i = 0; i < bfd_count; i++)
+               if (all_local_syms[i])
+                 free (all_local_syms[i]);
+             free (all_local_syms);
              goto error_return;
            }
 
@@ -2695,7 +2722,8 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
          irelaend = irela + section->reloc_count;
          for (; irela < irelaend; irela++)
            {
-             long r_type, callee_args, caller_args, r_index, size_of_stub;
+             long r_type, callee_args, caller_args, size_of_stub;
+             unsigned long r_index;
              struct elf_link_hash_entry *hash;
              struct elf32_hppa_stub_hash_entry *stub_hash;
              struct elf32_hppa_args_hash_entry *args_hash;
@@ -2713,7 +2741,10 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
                {
                  bfd_set_error (bfd_error_bad_value);
                  free (internal_relocs);
-                 free (local_syms);
+                 for (i = 0; i < bfd_count; i++)
+                   if (all_local_syms[i])
+                     free (all_local_syms[i]);
+                 free (all_local_syms);
                  goto error_return;
                }
 
@@ -2738,9 +2769,9 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
                  sym = local_syms + r_index;
                  hdr = elf_elfsections (input_bfd)[sym->st_shndx];
                  sym_sec = hdr->bfd_section;
-                 sym_name = elf_string_from_elf_section (input_bfd,
-                                                         symtab_hdr->sh_link,
-                                                         sym->st_name);
+                 sym_name = bfd_elf_string_from_elf_section (input_bfd,
+                                                             symtab_hdr->sh_link,
+                                                             sym->st_name);
                  sym_value = (ELF_ST_TYPE (sym->st_info) == STT_SECTION
                               ? 0 : sym->st_value);
                  destination = (sym_value
@@ -2749,12 +2780,14 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
 
                  /* Tack on an ID so we can uniquely identify this local
                     symbol in the stub or arg info hash tables.  */
-                 new_name = malloc (strlen (sym_name) + 10);
+                 new_name = bfd_malloc (strlen (sym_name) + 10);
                  if (new_name == 0)
                    {
-                     bfd_set_error (bfd_error_bad_value);
                      free (internal_relocs);
-                     free (local_syms);
+                     for (i = 0; i < bfd_count; i++)
+                       if (all_local_syms[i])
+                         free (all_local_syms[i]);
+                     free (all_local_syms);
                      goto error_return;
                    }
                  sprintf (new_name, "%s_%08x", sym_name, (int)sym_sec);
@@ -2767,7 +2800,8 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
 
                  index = r_index - symtab_hdr->sh_info;
                  hash = elf_sym_hashes (input_bfd)[index];
-                 if (hash->root.type == bfd_link_hash_defined)
+                 if (hash->root.type == bfd_link_hash_defined
+                     || hash->root.type == bfd_link_hash_defweak)
                    {
                      sym_sec = hash->root.u.def.section;
                      sym_name = hash->root.root.string;
@@ -2780,7 +2814,10 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
                    {
                      bfd_set_error (bfd_error_bad_value);
                      free (internal_relocs);
-                     free (local_syms);
+                     for (i = 0; i < bfd_count; i++)
+                       if (all_local_syms[i])
+                         free (all_local_syms[i]);
+                     free (all_local_syms);
                      goto error_return;
                    }
                }
@@ -2829,18 +2866,19 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
                  len = strlen (sym_name);
                  len += 23;
 
-                 stub_name = malloc (len);
+                 stub_name = bfd_malloc (len);
                  if (!stub_name)
                    {
-                     bfd_set_error (bfd_error_no_memory);
-
                      /* Because sym_name was mallocd above for local
                         symbols.  */
                      if (r_index < symtab_hdr->sh_info)
                        free (new_name);
 
                      free (internal_relocs);
-                     free (local_syms);
+                     for (i = 0; i < bfd_count; i++)
+                       if (all_local_syms[i])
+                         free (all_local_syms[i]);
+                     free (all_local_syms);
                      goto error_return;
                    }
                  elf32_hppa_name_of_stub (caller_args, callee_args,
@@ -2873,10 +2911,12 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
                                                       stub_name, true, true);
                      if (stub_hash == NULL)
                        {
-                         bfd_set_error (bfd_error_no_memory);
                          free (stub_name);
                          free (internal_relocs);
-                         free (local_syms);
+                         for (i = 0; i < bfd_count; i++)
+                           if (all_local_syms[i])
+                             free (all_local_syms[i]);
+                         free (all_local_syms);
                          goto error_return;
                        }
 
@@ -2891,9 +2931,12 @@ elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
          /* We're done with the internal relocs, free them.  */
          free (internal_relocs);
        }
-      /* We're done with the local symbols, free them.  */
-      free (local_syms);
     }
+  /* We're done with the local symbols, free them.  */
+  for (i = 0; i < bfd_count; i++)
+    if (all_local_syms[i])
+      free (all_local_syms[i]);
+  free (all_local_syms);
   return true;
 
 error_return:
@@ -2908,15 +2951,20 @@ error_return:
       elf32_hppa_hash_table(link_info)->args_hash_table = NULL;
       free (args_hash_table);
     }
+  /* Set the size of the stub section to zero since we're never going
+     to create them.   Avoids losing when we try to get its contents
+     too.  */
+  bfd_set_section_size (stub_bfd, stub_sec, 0);
   return false;
 }
 
 /* Misc BFD support code.  */
 #define bfd_elf32_bfd_reloc_type_lookup                elf_hppa_reloc_type_lookup
-#define bfd_elf32_bfd_is_local_label           hppa_elf_is_local_label
+#define bfd_elf32_bfd_is_local_label_name      hppa_elf_is_local_label_name
 
 /* Symbol extension stuff.  */
 #define bfd_elf32_set_section_contents         elf32_hppa_set_section_contents
+#define elf_info_to_howto                      elf32_hppa_info_to_howto
 #define elf_backend_symbol_table_processing \
   elf32_hppa_backend_symbol_table_processing
 #define elf_backend_begin_write_processing \