* som.c (som_slurp_symbol_table): Set the symbol count to the
[deliverable/binutils-gdb.git] / bfd / som.c
index 214a312afd19b6924d1bf8f47f7cef6c100bb76b..a1cf4cd52ed2c8ed991f926afcccf721103320c7 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -1,5 +1,5 @@
 /* bfd back-end for HP PA-RISC SOM objects.
-   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996
    Free Software Foundation, Inc.
 
    Contributed by the Center for Software Science at the
@@ -19,7 +19,7 @@
 
    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"
@@ -167,9 +167,13 @@ static asymbol * som_make_empty_symbol PARAMS ((bfd *));
 static void som_print_symbol PARAMS ((bfd *, PTR,
                                      asymbol *, bfd_print_symbol_type));
 static boolean som_new_section_hook PARAMS ((bfd *, asection *));
+static boolean som_bfd_copy_private_symbol_data PARAMS ((bfd *, asymbol *,
+                                                         bfd *, asymbol *));
 static boolean som_bfd_copy_private_section_data PARAMS ((bfd *, asection *,
                                                          bfd *, asection *));
 static boolean som_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+#define som_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
+#define som_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
 static boolean som_bfd_is_local_label PARAMS ((bfd *, asymbol *));
 static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
                                                 file_ptr, bfd_size_type));
@@ -213,10 +217,11 @@ static unsigned char * som_reloc_call PARAMS ((bfd *, unsigned char *,
 static unsigned long som_count_spaces PARAMS ((bfd *));
 static unsigned long som_count_subspaces PARAMS ((bfd *));
 static int compare_syms PARAMS ((const void *, const void *));
+static int compare_subspaces PARAMS ((const void *, const void *));
 static unsigned long som_compute_checksum PARAMS ((bfd *));
 static boolean som_prep_headers PARAMS ((bfd *));
 static int som_sizeof_headers PARAMS ((bfd *, boolean));
-static boolean som_write_headers PARAMS ((bfd *));
+static boolean som_finish_writing PARAMS ((bfd *));
 static boolean som_build_and_write_symbol_table PARAMS ((bfd *));
 static void som_prep_for_fixups PARAMS ((bfd *, asymbol **, unsigned long));
 static boolean som_write_fixups PARAMS ((bfd *, unsigned long, unsigned int *));
@@ -251,6 +256,7 @@ static boolean som_is_space PARAMS ((asection *));
 static boolean som_is_subspace PARAMS ((asection *));
 static boolean som_is_container PARAMS ((asection *, asection *));
 static boolean som_bfd_free_cached_info PARAMS ((bfd *));
+static boolean som_bfd_link_split_section PARAMS ((bfd *, asection *));
        
 /* Map SOM section names to POSIX/BSD single-character symbol types.
 
@@ -424,8 +430,9 @@ static const struct fixup_format som_fixup_formats[256] =
   1,    "Lb4*=Mb1+L*=",        /* 0x2b */
   2,    "Lb4*=Md1+4*=",        /* 0x2c */
   3,    "Ld1+=Me1+=",  /* 0x2d */
-  /* R_RESERVED */
+  /* R_SHORT_PCREL_MODE */
   0,           "",             /* 0x2e */
+  /* R_LONG_PCREL_MODE */
   0,           "",             /* 0x2f */
   /* R_PCREL_CALL */
   0,    "L4=RD=Sb=",   /* 0x30 */
@@ -631,14 +638,21 @@ static const struct fixup_format som_fixup_formats[256] =
   1,    "P",           /* 0xd4 */
   2,    "P",           /* 0xd5 */
   3,    "P",           /* 0xd6 */
-  /* R_RESERVED */
+  /* R_SEC_STMT */
   0,   "",             /* 0xd7 */
+  /* R_N0SEL */
   0,   "",             /* 0xd8 */
+  /* R_N1SEL */
   0,   "",             /* 0xd9 */
+  /* R_LINETAB */
   0,   "",             /* 0xda */
+  /* R_LINETAB_ESC */
   0,   "",             /* 0xdb */
+  /* R_LTP_OVERRIDE */
   0,   "",             /* 0xdc */
+  /* R_COMMENT */
   0,   "",             /* 0xdd */
+  /* R_RESERVED */
   0,   "",             /* 0xde */
   0,   "",             /* 0xdf */
   0,   "",             /* 0xe0 */
@@ -713,7 +727,7 @@ static const int comp3_opcodes[] =
   -1
 };
 
-/* These apparently are not in older versions of hpux reloc.h.  */
+/* These apparently are not in older versions of hpux reloc.h (hpux7).  */
 #ifndef R_DLT_REL
 #define R_DLT_REL 0x78
 #endif
@@ -726,6 +740,39 @@ static const int comp3_opcodes[] =
 #define R_SEC_STMT 0xd7
 #endif
 
+/* And these first appeared in hpux10.  */
+#ifndef R_SHORT_PCREL_MODE
+#define R_SHORT_PCREL_MODE 0x3e
+#endif
+
+#ifndef R_LONG_PCREL_MODE
+#define R_LONG_PCREL_MODE 0x3f
+#endif
+
+#ifndef R_N0SEL
+#define R_N0SEL 0xd8
+#endif
+
+#ifndef R_N1SEL
+#define R_N1SEL 0xd9
+#endif
+
+#ifndef R_LINETAB
+#define R_LINETAB 0xda
+#endif
+
+#ifndef R_LINETAB_ESC
+#define R_LINETAB_ESC 0xdb
+#endif
+
+#ifndef R_LTP_OVERRIDE
+#define R_LTP_OVERRIDE 0xdc
+#endif
+
+#ifndef R_COMMENT
+#define R_COMMENT 0xdd
+#endif
+
 static reloc_howto_type som_hppa_howto_table[] =
 {
   {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
@@ -790,8 +837,8 @@ static reloc_howto_type som_hppa_howto_table[] =
   {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
   {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
   {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
-  {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
-  {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+  {R_SHORT_PCREL_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SHORT_PCREL_MODE"},
+  {R_LONG_PCREL_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LONG_PCREL_MODE"},
   {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
   {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
   {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
@@ -944,12 +991,12 @@ static reloc_howto_type som_hppa_howto_table[] =
   {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
   {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
   {R_SEC_STMT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SEC_STMT"},
-  {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
-  {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
-  {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
-  {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
-  {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
-  {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+  {R_N0SEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N0SEL"},
+  {R_N1SEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N1SEL"},
+  {R_LINETAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LINETAB"},
+  {R_LINETAB_ESC, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LINETAB_ESC"},
+  {R_LTP_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LTP_OVERRIDE"},
+  {R_COMMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMMENT"},
   {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
   {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
   {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
@@ -1391,21 +1438,19 @@ hppa_som_reloc (abfd, reloc_entry, symbol_in, data,
    and a field selector, return one or more appropriate SOM relocations.  */
 
 int **
-hppa_som_gen_reloc_type (abfd, base_type, format, field)
+hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
      bfd *abfd;
      int base_type;
      int format;
      enum hppa_reloc_field_selector_type_alt field;
+     int sym_diff;
 {
   int *final_type, **final_types;
 
-  final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 3);
+  final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 6);
   final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
   if (!final_types || !final_type)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
 
   /* The field selector may require additional relocations to be 
      generated.  It's impossible to know at this moment if additional
@@ -1429,10 +1474,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_rtsel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
        if (!final_types[0])
-         {
-           bfd_set_error (bfd_error_no_memory);
-           return NULL;
-         }
+         return NULL;
        if (field == e_tsel)
          *final_types[0] = R_FSEL;
        else if (field == e_ltsel)
@@ -1448,10 +1490,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_rssel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
        if (!final_types[0])
-         {
-           bfd_set_error (bfd_error_no_memory);
-           return NULL;
-         }
+         return NULL;
        *final_types[0] = R_S_MODE;
        final_types[1] = final_type;
        final_types[2] = NULL;
@@ -1462,10 +1501,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_rsel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
        if (!final_types[0])
-         {
-           bfd_set_error (bfd_error_no_memory);
-           return NULL;
-         }
+         return NULL;
        *final_types[0] = R_N_MODE;
        final_types[1] = final_type;
        final_types[2] = NULL;
@@ -1476,10 +1512,7 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_rdsel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
        if (!final_types[0])
-         {
-           bfd_set_error (bfd_error_no_memory);
-           return NULL;
-         }
+         return NULL;
        *final_types[0] = R_D_MODE;
        final_types[1] = final_type;
        final_types[2] = NULL;
@@ -1490,22 +1523,70 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_rrsel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
        if (!final_types[0])
-         {
-           bfd_set_error (bfd_error_no_memory);
-           return NULL;
-         }
+         return NULL;
        *final_types[0] = R_R_MODE;
        final_types[1] = final_type;
        final_types[2] = NULL;
        *final_type = base_type;
        break;
+
+      case e_nsel:
+       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       if (!final_types[0])
+         return NULL;
+       *final_types[0] = R_N1SEL;
+       final_types[1] = final_type;
+       final_types[2] = NULL;
+       *final_type = base_type;
+       break;
+
+      case e_nlsel:
+      case e_nlrsel:
+       final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       if (!final_types[0])
+         return NULL;
+       *final_types[0] = R_N0SEL;
+       final_types[1] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       if (!final_types[1])
+         return NULL;
+       if (field == e_nlsel)
+         *final_types[1] = R_N_MODE;
+       else
+         *final_types[1] = R_R_MODE;
+       final_types[2] = final_type;
+       final_types[3] = NULL;
+       *final_type = base_type;
+       break;
     }
   
   switch (base_type)
     {
     case R_HPPA:
+      /* The difference of two symbols needs *very* special handling.  */
+      if (sym_diff)
+       {
+         final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         if (!final_types[0] || !final_types[1] || !final_types[2])
+            return NULL;
+         if (field == e_fsel)
+           *final_types[0] = R_FSEL;
+         else if (field == e_rsel)
+           *final_types[0] = R_RSEL;
+         else if (field == e_lsel)
+           *final_types[0] = R_LSEL;
+         *final_types[1] = R_COMP2;
+         *final_types[2] = R_COMP2;
+         *final_types[3] = R_COMP1;
+         final_types[4] = final_type;
+         *final_types[4] = R_CODE_EXPR;
+         final_types[5] = NULL;
+         break;
+       }
       /* PLABELs get their own relocation type.  */
-      if (field == e_psel
+      else if (field == e_psel
          || field == e_lpsel
          || field == e_rpsel)
        {
@@ -1535,6 +1616,33 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
        *final_type = R_DATA_PLABEL;
       break;
 
+    case R_HPPA_COMPLEX:
+      /* The difference of two symbols needs *very* special handling.  */
+      if (sym_diff)
+       {
+         final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+         if (!final_types[0] || !final_types[1] || !final_types[2])
+            return NULL;
+         if (field == e_fsel)
+           *final_types[0] = R_FSEL;
+         else if (field == e_rsel)
+           *final_types[0] = R_RSEL;
+         else if (field == e_lsel)
+           *final_types[0] = R_LSEL;
+         *final_types[1] = R_COMP2;
+         *final_types[2] = R_COMP2;
+         *final_types[3] = R_COMP1;
+         final_types[4] = final_type;
+         *final_types[4] = R_CODE_EXPR;
+         final_types[5] = NULL;
+         break;
+       }
+      else
+       break;
+
     case R_HPPA_NONE:
     case R_HPPA_ABS_CALL:
     case R_HPPA_PCREL_CALL:
@@ -1571,6 +1679,9 @@ som_object_setup (abfd, file_hdrp, aux_hdrp)
      struct header *file_hdrp;
      struct som_exec_auxhdr *aux_hdrp;
 {
+  asection *section;
+  int found;
+
   /* som_mkobject will set bfd_error if som_mkobject fails.  */
   if (som_mkobject (abfd) != true)
     return 0;
@@ -1611,10 +1722,7 @@ som_object_setup (abfd, file_hdrp, aux_hdrp)
   obj_som_exec_data (abfd) = (struct som_exec_data *)
     bfd_zalloc (abfd, sizeof (struct som_exec_data ));
   if (obj_som_exec_data (abfd) == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
 
   /* The braindamaged OSF1 linker switched exec_flags and exec_entry!
 
@@ -1627,7 +1735,18 @@ som_object_setup (abfd, file_hdrp, aux_hdrp)
      The new approach examines the entry field.  If it's zero or not 4
      byte aligned then it's not a proper code address and we guess it's
      really the executable flags.  */
-  if (aux_hdrp->exec_entry == 0 || (aux_hdrp->exec_entry & 0x3) != 0)
+  found = 0;
+  for (section = abfd->sections; section; section = section->next)
+    {
+      if ((section->flags & SEC_CODE) == 0)
+       continue;
+      if (aux_hdrp->exec_entry >= section->vma
+         && aux_hdrp->exec_entry < section->vma + section->_cooked_size)
+       found = 1;
+    }
+  if (aux_hdrp->exec_entry == 0
+      || (aux_hdrp->exec_entry & 0x3) != 0
+      || ! found)
     {
       bfd_get_start_address (abfd) = aux_hdrp->exec_flags;
       obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_entry;
@@ -1638,7 +1757,7 @@ som_object_setup (abfd, file_hdrp, aux_hdrp)
       obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags;
     }
 
-  bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
+  bfd_default_set_arch_mach (abfd, bfd_arch_hppa, pa10);
   bfd_get_symcount (abfd) = file_hdrp->symbol_total;
 
   /* Initialize the saved symbol table and string table to NULL.  
@@ -1668,17 +1787,15 @@ setup_sections (abfd, file_hdr)
      struct header *file_hdr;
 {
   char *space_strings;
-  int space_index;
+  unsigned int space_index, i;
   unsigned int total_subspaces = 0;
+  asection **subspace_sections, *section;
 
   /* First, read in space names */
 
-  space_strings = malloc (file_hdr->space_strings_size);
+  space_strings = bfd_malloc (file_hdr->space_strings_size);
   if (!space_strings && file_hdr->space_strings_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
     goto error_return;
@@ -1724,6 +1841,10 @@ setup_sections (abfd, file_hdr)
                                          space.space_number) == false)
        goto error_return;
 
+      /* If the space has no subspaces, then we're done.  */
+      if (space.subspace_quantity == 0)
+       continue;
+
       /* Now, read in the first subspace for this space */
       if (bfd_seek (abfd, file_hdr->subspace_location
                    + space.subspace_index * sizeof subspace,
@@ -1779,8 +1900,17 @@ setup_sections (abfd, file_hdr)
                                                 subspace.quadrant) == false)
            goto error_return;
 
-         /* Keep an easy mapping between subspaces and sections.  */
-         subspace_asect->target_index = total_subspaces++;
+         /* Keep an easy mapping between subspaces and sections. 
+            Note we do not necessarily read the subspaces in the
+            same order in which they appear in the object file.
+
+            So to make the target index come out correctly, we
+            store the location of the subspace header in target
+            index, then sort using the location of the subspace
+            header as the key.  Then we can assign correct
+            subspace indices.  */
+         total_subspaces++;
+         subspace_asect->target_index = bfd_tell (abfd) - sizeof (subspace);
 
          /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
             by the access_control_bits in the subspace header.  */
@@ -1873,13 +2003,43 @@ setup_sections (abfd, file_hdr)
       space_asect->_raw_size = save_subspace.file_loc_init_value
        - space_asect->filepos + save_subspace.initialization_length;
     }
+  /* Now that we've read in all the subspace records, we need to assign
+     a target index to each subspace.  */
+  subspace_sections = (asection **) bfd_malloc (total_subspaces
+                                               * sizeof (asection *));
+  if (subspace_sections == NULL)
+    goto error_return;
+
+  for (i = 0, section = abfd->sections; section; section = section->next)
+    {
+      if (!som_is_subspace (section))
+       continue;
+
+      subspace_sections[i] = section;
+      i++;
+    }
+  qsort (subspace_sections, total_subspaces,
+        sizeof (asection *), compare_subspaces);
+  
+  /* subspace_sections is now sorted in the order in which the subspaces
+     appear in the object file.  Assign an index to each one now.  */
+  for (i = 0; i < total_subspaces; i++)
+    subspace_sections[i]->target_index = i;
+
   if (space_strings != NULL)
     free (space_strings);
+
+  if (subspace_sections != NULL)
+    free (subspace_sections);
+
   return true;
 
  error_return:
   if (space_strings != NULL)
     free (space_strings);
+
+  if (subspace_sections != NULL)
+    free (subspace_sections);
   return false;
 }
 
@@ -1971,10 +2131,7 @@ som_mkobject (abfd)
   abfd->tdata.som_data = (struct som_data_struct *)
     bfd_zalloc (abfd, sizeof (struct som_data_struct));
   if (abfd->tdata.som_data == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   return true;
 }
 
@@ -1992,11 +2149,7 @@ som_prep_headers (abfd)
   /* Make and attach a file header to the BFD.  */
   file_hdr = (struct header *) bfd_zalloc (abfd, sizeof (struct header));
   if (file_hdr == NULL)
-
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   obj_som_file_hdr (abfd) = file_hdr;
 
   if (abfd->flags & (EXEC_P | DYNAMIC))
@@ -2006,10 +2159,7 @@ som_prep_headers (abfd)
       obj_som_exec_hdr (abfd) = (struct som_exec_auxhdr *)
        bfd_zalloc (abfd, sizeof (struct som_exec_auxhdr));
       if (obj_som_exec_hdr (abfd) == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
 
       if (abfd->flags & D_PAGED)
        file_hdr->a_magic = DEMAND_MAGIC;
@@ -2056,10 +2206,7 @@ som_prep_headers (abfd)
            = (struct space_dictionary_record *)
              bfd_zalloc (abfd, sizeof (struct space_dictionary_record));
          if (som_section_data (section)->space_dict == NULL)
-           {
-             bfd_set_error (bfd_error_no_memory);
-             return false;
-           }
+           return false;
          /* Set space attributes.  Note most attributes of SOM spaces
             are set based on the subspaces it contains.  */
          som_section_data (section)->space_dict->loader_fix_index = -1;
@@ -2082,10 +2229,7 @@ som_prep_headers (abfd)
            = (struct subspace_dictionary_record *)
              bfd_zalloc (abfd, sizeof (struct subspace_dictionary_record));
          if (som_section_data (section)->subspace_dict == NULL)
-           {
-             bfd_set_error (bfd_error_no_memory);
-             return false;
-           }
+           return false;
 
          /* Set subspace attributes.  Basic stuff is done here, additional
             attributes are filled in later as more information becomes
@@ -2136,7 +2280,9 @@ som_is_space (section)
 
   /* If the containing space isn't the same as the given section,
      then this isn't a space.  */
-  if (som_section_data (section)->copy_data->container != section)
+  if (som_section_data (section)->copy_data->container != section
+      && (som_section_data (section)->copy_data->container->output_section
+         != section))
     return false;
 
   /* OK.  Must be a space.  */
@@ -2156,7 +2302,9 @@ som_is_subspace (section)
 
   /* If the containing space is the same as the given section,
      then this isn't a subspace.  */
-  if (som_section_data (section)->copy_data->container == section)
+  if (som_section_data (section)->copy_data->container == section
+      || (som_section_data (section)->copy_data->container->output_section
+         == section))
     return false;
 
   /* OK.  Must be a subspace.  */
@@ -2171,7 +2319,9 @@ static boolean
 som_is_container (space, subspace)
      asection *space, *subspace;
 {
-  return som_section_data (subspace)->copy_data->container == space;
+  return (som_section_data (subspace)->copy_data->container == space
+         || (som_section_data (subspace)->copy_data->container->output_section
+             == space));
 }
 
 /* Count and return the number of spaces attached to the given BFD.  */
@@ -2240,6 +2390,27 @@ compare_syms (arg1, arg2)
   return 0;
 }
 
+/* Return -1, 0, 1 indicating the relative ordering of subspace1
+   and subspace.  */
+
+static int
+compare_subspaces (arg1, arg2)
+     const PTR arg1;
+     const PTR arg2;
+
+{
+  asection **subspace1 = (asection **) arg1;
+  asection **subspace2 = (asection **) arg2;
+  unsigned int count1, count2;
+  
+  if ((*subspace1)->target_index < (*subspace2)->target_index)
+    return -1;
+  else if ((*subspace2)->target_index < (*subspace1)->target_index)
+    return 1;
+  else
+    return 0;
+}
+
 /* Perform various work in preparation for emitting the fixup stream.  */
 
 static void
@@ -2472,6 +2643,12 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                case R_FSEL:
                case R_LSEL:
                case R_RSEL:
+               case R_COMP1:
+               case R_COMP2:
+               case R_BEGIN_BRTAB:
+               case R_END_BRTAB:
+               case R_N0SEL:
+               case R_N1SEL:
                  reloc_offset = bfd_reloc->address;
                  break;
 
@@ -2525,8 +2702,9 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                case R_DATA_PLABEL:
                case R_CODE_PLABEL:
                case R_DLT_REL:
-                 /* Account for any addend.  */
-                 if (bfd_reloc->addend)
+                 /* Account for any addend using R_DATA_OVERRIDE.  */
+                 if (bfd_reloc->howto->type != R_DATA_ONE_SYMBOL
+                     && bfd_reloc->addend)
                    p = som_reloc_addend (abfd, bfd_reloc->addend, p, 
                                          &subspace_reloc_size, reloc_queue);
 
@@ -2600,6 +2778,41 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                case R_FSEL:
                case R_LSEL:
                case R_RSEL:
+               case R_BEGIN_BRTAB:
+               case R_END_BRTAB:
+               case R_N0SEL:
+               case R_N1SEL:
+                 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+                 subspace_reloc_size += 1;
+                 p += 1;
+                 break;
+
+               case R_COMP1:
+                 /* The only time we generate R_COMP1, R_COMP2 and 
+                    R_CODE_EXPR relocs is for the difference of two
+                    symbols.  Hence we can cheat here.  */
+                 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+                 bfd_put_8 (abfd, 0x44, p + 1);
+                 p = try_prev_fixup (abfd, &subspace_reloc_size,
+                                     p, 2, reloc_queue);
+                 break;
+
+               case R_COMP2:
+                 /* The only time we generate R_COMP1, R_COMP2 and 
+                    R_CODE_EXPR relocs is for the difference of two
+                    symbols.  Hence we can cheat here.  */
+                 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+                 bfd_put_8 (abfd, 0x80, p + 1);
+                 bfd_put_8 (abfd, sym_num >> 16, p + 2);
+                 bfd_put_16 (abfd, sym_num, p + 3);
+                 p = try_prev_fixup (abfd, &subspace_reloc_size,
+                                     p, 5, reloc_queue);
+                 break;
+
+               case R_CODE_EXPR:
+                 /* The only time we generate R_COMP1, R_COMP2 and 
+                    R_CODE_EXPR relocs is for the difference of two
+                    symbols.  Hence we can cheat here.  */
                  bfd_put_8 (abfd, bfd_reloc->howto->type, p);
                  subspace_reloc_size += 1;
                  p += 1;
@@ -2805,9 +3018,8 @@ som_begin_writing (abfd)
   unsigned long current_offset = 0;
   int strings_size = 0;
   unsigned int total_reloc_size = 0;
-  unsigned long num_spaces, num_subspaces, num_syms, i;
+  unsigned long num_spaces, num_subspaces, i;
   asection *section;
-  asymbol **syms = bfd_get_outsymbols (abfd);
   unsigned int total_subspaces = 0;
   struct som_exec_auxhdr *exec_header = NULL;
 
@@ -2939,55 +3151,6 @@ som_begin_writing (abfd)
   obj_som_file_hdr (abfd)->space_strings_size = strings_size;
   current_offset += strings_size;
 
-  /* Next is the symbol table.  These are fixed length records.
-
-     Count the number of symbols to determine how much room is needed
-     in the object file for the symbol table.
-
-     The names of the symbols are stored in a separate string table,
-     and the index for each symbol name into the string table is computed
-     below.  Therefore, it is not possible to write the symobl table
-     at this time.  */
-  num_syms = bfd_get_symcount (abfd);
-  obj_som_file_hdr (abfd)->symbol_location = current_offset;
-  obj_som_file_hdr (abfd)->symbol_total = num_syms;
-  current_offset += num_syms * sizeof (struct symbol_dictionary_record);
-
-  /* Do prep work before handling fixups.  */
-  som_prep_for_fixups (abfd, syms, num_syms);
-
-  /* Next comes the fixup stream which starts on a word boundary.  */
-  if (current_offset % 4)
-    current_offset += (4 - (current_offset % 4)); 
-  obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
-
-  /* Write the fixups and update fields in subspace headers which
-     relate to the fixup stream.  */
-  if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
-    return false;
-
-  /* Record the total size of the fixup stream in the file header.  */
-  obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
-  current_offset += total_reloc_size;
-
-  /* Next are the symbol strings.
-     Align them to a word boundary.  */
-  if (current_offset % 4)
-    current_offset += (4 - (current_offset % 4));
-  obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
-
-  /* Scribble out the symbol strings.  */
-  if (som_write_symbol_strings (abfd, current_offset,
-                               obj_som_sorted_syms (abfd),
-                               num_syms, &strings_size)
-      == false)
-    return false;
-
-  /* Record total string table size in header and update the
-     current offset.  */
-  obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
-  current_offset += strings_size;
-
   /* Next is the compiler records.  We do not use these.  */
   obj_som_file_hdr (abfd)->compiler_location = current_offset;
   obj_som_file_hdr (abfd)->compiler_total = 0;
@@ -3185,7 +3348,7 @@ som_begin_writing (abfd)
   obj_som_file_hdr (abfd)->loader_fixup_location = 0;
   obj_som_file_hdr (abfd)->loader_fixup_total = 0;
 
-  /* Done.  Store the total size of the SOM.  */
+  /* Done.  Store the total size of the SOM so far.  */
   obj_som_file_hdr (abfd)->som_length = current_offset;
 
   return true;
@@ -3194,14 +3357,85 @@ som_begin_writing (abfd)
 /* Finally, scribble out the various headers to the disk.  */
 
 static boolean
-som_write_headers (abfd)
+som_finish_writing (abfd)
      bfd *abfd;
 {
   int num_spaces = som_count_spaces (abfd);
-  int i;
+  asymbol **syms = bfd_get_outsymbols (abfd);
+  int i, num_syms, strings_size;
   int subspace_index = 0;
   file_ptr location;
   asection *section;
+  unsigned long current_offset;
+  unsigned int total_reloc_size;
+
+  /* Next is the symbol table.  These are fixed length records.
+
+     Count the number of symbols to determine how much room is needed
+     in the object file for the symbol table.
+
+     The names of the symbols are stored in a separate string table,
+     and the index for each symbol name into the string table is computed
+     below.  Therefore, it is not possible to write the symbol table
+     at this time. 
+
+     These used to be output before the subspace contents, but they
+     were moved here to work around a stupid bug in the hpux linker
+     (fixed in hpux10).  */
+  current_offset = obj_som_file_hdr (abfd)->som_length;
+
+  /* Make sure we're on a word boundary.  */
+  if (current_offset % 4)
+    current_offset += (4 - (current_offset % 4)); 
+
+  num_syms = bfd_get_symcount (abfd);
+  obj_som_file_hdr (abfd)->symbol_location = current_offset;
+  obj_som_file_hdr (abfd)->symbol_total = num_syms;
+  current_offset += num_syms * sizeof (struct symbol_dictionary_record);
+
+  /* Next are the symbol strings.
+     Align them to a word boundary.  */
+  if (current_offset % 4)
+    current_offset += (4 - (current_offset % 4));
+  obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
+
+  /* Scribble out the symbol strings.  */
+  if (som_write_symbol_strings (abfd, current_offset, syms,
+                               num_syms, &strings_size)
+      == false)
+    return false;
+
+  /* Record total string table size in header and update the
+     current offset.  */
+  obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
+  current_offset += strings_size;
+
+  /* Do prep work before handling fixups.  */
+  som_prep_for_fixups (abfd,
+                      bfd_get_outsymbols (abfd),
+                      bfd_get_symcount (abfd));
+
+  /* At the end of the file is the fixup stream which starts on a
+     word boundary.  */
+  if (current_offset % 4)
+    current_offset += (4 - (current_offset % 4)); 
+  obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
+
+  /* Write the fixups and update fields in subspace headers which
+     relate to the fixup stream.  */
+  if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
+    return false;
+
+  /* Record the total size of the fixup stream in the file header.  */
+  obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
+
+  /* Done.  Store the total size of the SOM.  */
+  obj_som_file_hdr (abfd)->som_length = current_offset + total_reloc_size;
+  /* Now that the symbol table information is complete, build and
+     write the symbol table.  */
+  if (som_build_and_write_symbol_table (abfd) == false)
+    return false;
 
   /* Subspaces are written first so that we can set up information
      about them in their containing spaces as the subspace is written.  */
@@ -3348,13 +3582,12 @@ som_write_headers (abfd)
       section = section->next;
     }
 
-  /* FIXME.  This should really be conditional based on whether or not
-     PA1.1 instructions/registers have been used. 
-
-     Setting of the system_id has to happen very late now that copying of
+  /* Setting of the system_id has to happen very late now that copying of
      BFD private data happens *after* section contents are set.  */
   if (abfd->flags & (EXEC_P | DYNAMIC))
     obj_som_file_hdr(abfd)->system_id = obj_som_exec_data (abfd)->system_id;
+  else if (bfd_get_mach (abfd) == pa11)
+    obj_som_file_hdr(abfd)->system_id = CPU_PA_RISC1_1;
   else
     obj_som_file_hdr(abfd)->system_id = CPU_PA_RISC1_0;
 
@@ -3503,11 +3736,10 @@ som_bfd_derive_misc_symbol_info (abfd, sym, info)
   /* Now handle the symbol's scope.  Exported data which is not
      in the common section has scope SS_UNIVERSAL.  Note scope
      of common symbols was handled earlier!  */
-  if (sym->flags & BSF_EXPORT && ! bfd_is_com_section (sym->section))
-    info->symbol_scope = SS_UNIVERSAL;
-  /* Any undefined symbol at this point has a scope SS_UNSAT.  */
-  else if (bfd_is_und_section (sym->section))
+  if (bfd_is_und_section (sym->section))
     info->symbol_scope = SS_UNSAT;
+  else if (sym->flags & BSF_EXPORT && ! bfd_is_com_section (sym->section))
+    info->symbol_scope = SS_UNIVERSAL;
   /* Anything else which is not in the common section has scope
      SS_LOCAL.  */
   else if (! bfd_is_com_section (sym->section))
@@ -3546,12 +3778,9 @@ som_build_and_write_symbol_table (abfd)
   /* Compute total symbol table size and allocate a chunk of memory
      to hold the symbol table as we build it.  */
   symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
-  som_symtab = (struct symbol_dictionary_record *) malloc (symtab_size);
+  som_symtab = (struct symbol_dictionary_record *) bfd_malloc (symtab_size);
   if (som_symtab == NULL && symtab_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
   memset (som_symtab, 0, symtab_size);
 
   /* Walk over each symbol.  */
@@ -3609,12 +3838,7 @@ som_write_object_contents (abfd)
       som_begin_writing (abfd);
     }
 
-  /* Now that the symbol table information is complete, build and
-     write the symbol table.  */
-  if (som_build_and_write_symbol_table (abfd) == false)
-    return false;
-
-  return (som_write_headers (abfd));
+  return (som_finish_writing (abfd));
 }
 
 \f
@@ -3640,12 +3864,10 @@ som_slurp_string_table (abfd)
     }
 
   /* Allocate and read in the string table.  */
-  stringtab = malloc (obj_som_stringtab_size (abfd));
+  stringtab = bfd_malloc (obj_som_stringtab_size (abfd));
   if (stringtab == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
+  memset (stringtab, 0, obj_som_stringtab_size (abfd));
 
   if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
     return false;
@@ -3746,21 +3968,16 @@ som_slurp_symbol_table (abfd)
 
   stringtab = obj_som_stringtab (abfd);
 
-  symbase = (som_symbol_type *)
-    malloc (symbol_count * sizeof (som_symbol_type));
+  symbase = ((som_symbol_type *)
+            bfd_malloc (symbol_count * sizeof (som_symbol_type)));
   if (symbase == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
+  memset (symbase, 0, symbol_count * sizeof (som_symbol_type));
 
   /* Read in the external SOM representation.  */
-  buf = malloc (symbol_count * symsize);
+  buf = bfd_malloc (symbol_count * symsize);
   if (buf == NULL && symbol_count * symsize != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
     goto error_return;
   if (bfd_read (buf, symbol_count * symsize, 1, abfd) 
@@ -3872,7 +4089,7 @@ som_slurp_symbol_table (abfd)
         Note $START$ is a magic code symbol, NOT a section symbol.  */
       if (sym->symbol.name[0] == '$'
          && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
-         && strcmp (sym->symbol.name, "$START$"))
+         && !strcmp (sym->symbol.name, sym->symbol.section->name))
        sym->symbol.flags |= BSF_SECTION_SYM;
       else if (!strncmp (sym->symbol.name, "L$0\002", 4))
        {
@@ -3887,6 +4104,10 @@ som_slurp_symbol_table (abfd)
       sym++;
     }
 
+  /* We modify the symbol count to record the number of BFD symbols we
+     created.  */
+  bfd_get_symcount (abfd) = sym - symbase;
+
   /* Save our results and return success.  */
   obj_som_symtab (abfd) = symbase;
  successful_return:
@@ -3934,10 +4155,7 @@ som_make_empty_symbol (abfd)
   som_symbol_type *new =
   (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
   if (new == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return 0;
-    }
+    return 0;
   new->symbol.the_bfd = abfd;
 
   return &new->symbol;
@@ -4004,7 +4222,7 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
      asymbol **symbols;
      boolean just_count;
 {
-  unsigned int op, varname;
+  unsigned int op, varname, deallocate_contents = 0;
   unsigned char *end_fixups = &fixup[end];
   const struct fixup_format *fp;
   char *cp;
@@ -4095,8 +4313,11 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
                 the stack.  */
              else if (islower (c))
                {
+                 int bits = (c - 'a') * 8;
                  for (v = 0; c > 'a'; --c)
                    v = (v << 8) | *fixup++;
+                 if (varname == 'V')
+                   v = sign_extend (v, bits);
                  push (v);
                }
 
@@ -4158,6 +4379,73 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
              if (! just_count)
                rptr->sym_ptr_ptr = &symbols[c];
              break;
+           /* Argument relocation bits for a function call.  */
+           case 'R':
+             if (! just_count)
+               {
+                 unsigned int tmp = var ('R');
+                 rptr->addend = 0;
+
+                 if ((som_hppa_howto_table[op].type == R_PCREL_CALL
+                      && R_PCREL_CALL + 10 > op)
+                     || (som_hppa_howto_table[op].type == R_ABS_CALL
+                         && R_ABS_CALL + 10 > op))
+                   {
+                     /* Simple encoding.  */
+                     if (tmp > 4)
+                       {
+                         tmp -= 5;
+                         rptr->addend |= 1;
+                       }
+                     if (tmp == 4)
+                       rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2;
+                     else if (tmp == 3)
+                       rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4;
+                     else if (tmp == 2)
+                       rptr->addend |= 1 << 8 | 1 << 6;
+                     else if (tmp == 1)
+                       rptr->addend |= 1 << 8;
+                   }
+                 else
+                   {
+                     unsigned int tmp1, tmp2;
+
+                     /* First part is easy -- low order two bits are
+                        directly copied, then shifted away.  */
+                     rptr->addend = tmp & 0x3;
+                     tmp >>= 2;
+
+                     /* Diving the result by 10 gives us the second
+                        part.  If it is 9, then the first two words
+                        are a double precision paramater, else it is
+                        3 * the first arg bits + the 2nd arg bits.  */
+                     tmp1 = tmp / 10;
+                     tmp -= tmp1 * 10;
+                     if (tmp1 == 9)
+                       rptr->addend += (0xe << 6);
+                     else
+                       {
+                         /* Get the two pieces.  */
+                         tmp2 = tmp1 / 3;
+                         tmp1 -= tmp2 * 3;
+                         /* Put them in the addend.  */
+                         rptr->addend += (tmp2 << 8) + (tmp1 << 6);
+                       }
+
+                     /* What's left is the third part.  It's unpacked
+                        just like the second.  */
+                     if (tmp == 9)
+                       rptr->addend += (0xe << 2);
+                     else
+                       {
+                         tmp2 = tmp / 3;
+                         tmp -= tmp2 * 3;
+                         rptr->addend += (tmp2 << 4) + (tmp << 2);
+                       }
+                   }
+                 rptr->addend = HPPA_R_ADDEND (rptr->addend, 0);
+               }
+             break;
            /* Handle the linker expression stack.  */
            case 'O':
              switch (op)
@@ -4210,6 +4498,40 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
                rptr->addend = var ('T');
              else if (som_hppa_howto_table[op].type == R_EXIT)
                rptr->addend = var ('U');
+             else if (som_hppa_howto_table[op].type == R_PCREL_CALL
+                      || som_hppa_howto_table[op].type == R_ABS_CALL)
+               ;
+             else if (som_hppa_howto_table[op].type == R_DATA_ONE_SYMBOL)
+               {
+                 unsigned addend = var ('V');
+
+                 /* Try what was specified in R_DATA_OVERRIDE first
+                    (if anything).  Then the hard way using the
+                    section contents.  */
+                 rptr->addend = var ('V');
+
+                 if (rptr->addend == 0 && !section->contents)
+                   {
+                     /* Got to read the damn contents first.  We don't
+                        bother saving the contents (yet).  Add it one
+                        day if the need arises.  */
+                     section->contents = bfd_malloc (section->_raw_size);
+                     if (section->contents == NULL)
+                       return -1;
+
+                     deallocate_contents = 1;
+                     bfd_get_section_contents (section->owner,
+                                               section,
+                                               section->contents,
+                                               0,
+                                               section->_raw_size);
+                   }
+                 else if (rptr->addend == 0)
+                   rptr->addend = bfd_get_32 (section->owner,
+                                              (section->contents
+                                               + offset - var ('L')));
+                       
+               }
              else
                rptr->addend = var ('V');
              rptr++;
@@ -4221,6 +4543,9 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
          memset (stack, 0, sizeof (stack));
        }
     }
+  if (deallocate_contents)
+    free (section->contents);
+
   return count;
 
 #undef var
@@ -4256,12 +4581,9 @@ som_slurp_reloc_table (abfd, section, symbols, just_count)
      parsed.  We must do so now to know how many relocations exist.  */
   if (section->reloc_count == -1)
     {
-      external_relocs = (char *) malloc (fixup_stream_size);
+      external_relocs = (char *) bfd_malloc (fixup_stream_size);
       if (external_relocs == (char *) NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
       /* Read in the external forms. */
       if (bfd_seek (abfd,
                    obj_som_reloc_filepos (abfd) + section->rel_filepos,
@@ -4292,17 +4614,18 @@ som_slurp_reloc_table (abfd, section, symbols, just_count)
   if (section->relocation != (arelent *) NULL)
     return true;
 
-  internal_relocs = (arelent *) malloc (num_relocs * sizeof (arelent));
+  internal_relocs = (arelent *) 
+    bfd_zalloc (abfd, (num_relocs * sizeof (arelent)));
   if (internal_relocs == (arelent *) NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   /* Process and internalize the relocations.  */
   som_set_reloc_info (external_relocs, fixup_stream_size,
                      internal_relocs, section, symbols, false);
 
+  /* We're done with the external relocations.  Free them.  */
+  free (external_relocs);
+
   /* Save our results and return success.  */
   section->relocation = internal_relocs;
   return (true);
@@ -4321,8 +4644,8 @@ som_get_reloc_upper_bound (abfd, asect)
   if (asect->flags & SEC_RELOC)
     {
       if (! som_slurp_reloc_table (abfd, asect, NULL, true))
-       return false;
-      return (asect->reloc_count + 1) * sizeof (arelent);
+       return -1;
+      return (asect->reloc_count + 1) * sizeof (arelent *);
     }
   /* There are no relocations.  */
   return 0;
@@ -4366,16 +4689,38 @@ som_new_section_hook (abfd, newsect)
   newsect->used_by_bfd =
     (PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
   if (!newsect->used_by_bfd)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   newsect->alignment_power = 3;
 
   /* We allow more than three sections internally */
   return true;
 }
 
+/* Copy any private info we understand from the input symbol
+   to the output symbol.  */
+
+static boolean
+som_bfd_copy_private_symbol_data (ibfd, isymbol, obfd, osymbol)
+     bfd *ibfd;
+     asymbol *isymbol;
+     bfd *obfd;
+     asymbol *osymbol;
+{
+  struct som_symbol *input_symbol = (struct som_symbol *) isymbol;
+  struct som_symbol *output_symbol = (struct som_symbol *) osymbol;
+
+  /* One day we may try to grok other private data.  */
+  if (ibfd->xvec->flavour != bfd_target_som_flavour
+      || obfd->xvec->flavour != bfd_target_som_flavour)
+    return false;
+
+  /* The only private information we need to copy is the argument relocation
+     bits.  */
+  output_symbol->tc_data.hppa_arg_reloc = input_symbol->tc_data.hppa_arg_reloc;
+
+  return true;
+}
+
 /* Copy any private info we understand from the input section
    to the output section.  */
 static boolean
@@ -4389,16 +4734,13 @@ som_bfd_copy_private_section_data (ibfd, isection, obfd, osection)
   if (ibfd->xvec->flavour != bfd_target_som_flavour
       || obfd->xvec->flavour != bfd_target_som_flavour
       || (!som_is_space (isection) && !som_is_subspace (isection)))
-    return false;
+    return true;
 
   som_section_data (osection)->copy_data
     = (struct som_copyable_section_data_struct *)
       bfd_zalloc (obfd, sizeof (struct som_copyable_section_data_struct));
   if (som_section_data (osection)->copy_data == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   memcpy (som_section_data (osection)->copy_data,
          som_section_data (isection)->copy_data,
@@ -4422,16 +4764,13 @@ som_bfd_copy_private_bfd_data (ibfd, obfd)
   /* One day we may try to grok other private data.  */
   if (ibfd->xvec->flavour != bfd_target_som_flavour
       || obfd->xvec->flavour != bfd_target_som_flavour)
-    return false;
+    return true;
 
   /* Allocate some memory to hold the data we need.  */
   obj_som_exec_data (obfd) = (struct som_exec_data *)
     bfd_zalloc (obfd, sizeof (struct som_exec_data));
   if (obj_som_exec_data (obfd) == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   /* Now copy the data.  */
   memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
@@ -4459,10 +4798,7 @@ bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
          bfd_zalloc (section->owner,
                      sizeof (struct som_copyable_section_data_struct));
       if (som_section_data (section)->copy_data == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
     }
   som_section_data (section)->copy_data->sort_key = sort_key;
   som_section_data (section)->copy_data->is_defined = defined;
@@ -4492,10 +4828,7 @@ bfd_som_set_subsection_attributes (section, container, access,
          bfd_zalloc (section->owner,
                      sizeof (struct som_copyable_section_data_struct));
       if (som_section_data (section)->copy_data == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
     }
   som_section_data (section)->copy_data->sort_key = sort_key;
   som_section_data (section)->copy_data->access_control_bits = access;
@@ -4537,10 +4870,7 @@ bfd_som_attach_aux_hdr (abfd, type, string)
        bfd_zalloc (abfd, sizeof (struct aux_id)
                              + sizeof (unsigned int) + len + pad);
       if (!obj_som_version_hdr (abfd))
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
       obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
       obj_som_version_hdr (abfd)->header_id.length = len + pad;
       obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
@@ -4558,10 +4888,7 @@ bfd_som_attach_aux_hdr (abfd, type, string)
        bfd_zalloc (abfd, sizeof (struct aux_id)
                            + sizeof (unsigned int) + len + pad);
       if (!obj_som_copyright_hdr (abfd))
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
       obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
       obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
       obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
@@ -4645,9 +4972,6 @@ som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
      CONST char **functionname_ptr;
      unsigned int *line_ptr;
 {
-  fprintf (stderr, "som_find_nearest_line unimplemented\n");
-  fflush (stderr);
-  abort ();
   return (false);
 }
 
@@ -4656,7 +4980,7 @@ som_sizeof_headers (abfd, reloc)
      bfd *abfd;
      boolean reloc;
 {
-  fprintf (stderr, "som_sizeof_headers unimplemented\n");
+  (*_bfd_error_handler) ("som_sizeof_headers unimplemented");
   fflush (stderr);
   abort ();
   return (0);
@@ -4692,7 +5016,9 @@ som_decode_symclass (symbol)
   if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL)))
     return '?';
 
-  if (bfd_is_abs_section (symbol->section))
+  if (bfd_is_abs_section (symbol->section)
+      || (som_symbol_data (symbol) != NULL
+         && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
     c = 'a';
   else if (symbol->section)
     c = som_section_type (symbol->section->name);
@@ -4733,12 +5059,10 @@ som_bfd_count_ar_symbols (abfd, lst_header, count)
   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
 
   hash_table = 
-    (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
+    (unsigned int *) bfd_malloc (lst_header->hash_size
+                                * sizeof (unsigned int));
   if (hash_table == NULL && lst_header->hash_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   /* Don't forget to initialize the counter!  */
   *count = 0;
@@ -4813,21 +5137,16 @@ som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
 
   hash_table = 
-    (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
+    (unsigned int *) bfd_malloc (lst_header->hash_size
+                                * sizeof (unsigned int));
   if (hash_table == NULL && lst_header->hash_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   som_dict =
-    (struct som_entry *) malloc (lst_header->module_count
-                                * sizeof (struct som_entry));
+    (struct som_entry *) bfd_malloc (lst_header->module_count
+                                    * sizeof (struct som_entry));
   if (som_dict == NULL && lst_header->module_count != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   /* Read in the hash table.  The has table is an array of 32bit file offsets
      which point to the hash chains.  */
@@ -4879,10 +5198,7 @@ som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
       /* Allocate space for the name and null terminate it too.  */
       set->name = bfd_zalloc (abfd, len + 1);
       if (!set->name)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         goto error_return;
-       }
+       goto error_return;
       if (bfd_read (set->name, 1, len, abfd) != len)
        goto error_return;
 
@@ -4918,10 +5234,7 @@ som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
          /* Allocate space for the name and null terminate it too.  */
          set->name = bfd_zalloc (abfd, len + 1);
          if (!set->name)
-           {
-             bfd_set_error (bfd_error_no_memory);
-             goto error_return;
-           }
+           goto error_return;
 
          if (bfd_read (set->name, 1, len, abfd) != len)
            goto error_return;
@@ -5032,10 +5345,7 @@ som_slurp_armap (abfd)
                                          (ardata->symdef_count
                                           * sizeof (carsym)));
   if (!ardata->symdefs)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   /* Now fill in the canonical archive symbols.  */
   if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
@@ -5177,29 +5487,20 @@ som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
   unsigned int maxname = abfd->xvec->ar_max_namelen;
 
   hash_table =
-    (unsigned int *) malloc (lst.hash_size * sizeof (unsigned int));
+    (unsigned int *) bfd_malloc (lst.hash_size * sizeof (unsigned int));
   if (hash_table == NULL && lst.hash_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
   som_dict =
-    (struct som_entry *) malloc (lst.module_count
-                                * sizeof (struct som_entry));
+    (struct som_entry *) bfd_malloc (lst.module_count
+                                    * sizeof (struct som_entry));
   if (som_dict == NULL && lst.module_count != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   last_hash_entry =
     ((struct lst_symbol_record **)
-     malloc (lst.hash_size * sizeof (struct lst_symbol_record *)));
+     bfd_malloc (lst.hash_size * sizeof (struct lst_symbol_record *)));
   if (last_hash_entry == NULL && lst.hash_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   /* Lots of fields are file positions relative to the start
      of the lst record.  So save its location.  */
@@ -5231,10 +5532,7 @@ som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
       unsigned int thislen;
 
       if (!normal)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
       thislen = strlen (normal);
       if (thislen > maxname)
        extended_name_length += thislen + 1;
@@ -5249,18 +5547,12 @@ som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
   curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
 
   /* FIXME should be done with buffers just like everything else... */
-  lst_syms = malloc (nsyms * sizeof (struct lst_symbol_record));
+  lst_syms = bfd_malloc (nsyms * sizeof (struct lst_symbol_record));
   if (lst_syms == NULL && nsyms != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
-  strings = malloc (string_size);
+    goto error_return;
+  strings = bfd_malloc (string_size);
   if (strings == NULL && string_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   p = strings;
   curr_lst_sym = lst_syms;
@@ -5389,6 +5681,11 @@ som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
       /* Keep track of where each SOM will finally reside; then look
         at the next BFD.  */
       curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
+      /* A particular object in the archive may have an odd length; the
+        linker requires objects begin on an even boundary.  So round
+        up the current offset as necessary.  */
+      curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
       curr_bfd = curr_bfd->next;
       som_index++;
     }
@@ -5487,6 +5784,8 @@ som_write_armap (abfd, elength, map, orl_count, stridx)
   lst_size = sizeof (struct lst_header);
 
   /* Start building the LST header.  */
+  /* FIXME:  Do we need to examine each element to determine the
+     largest id number?  */
   lst.system_id = CPU_PA_RISC1_0;
   lst.a_magic = LIBMAGIC;
   lst.version_id = VERSION_ID;
@@ -5611,16 +5910,32 @@ som_bfd_free_cached_info (abfd)
 
 /* End of miscellaneous support functions. */
 
+/* Linker support functions.  */
+static boolean
+som_bfd_link_split_section (abfd, sec)
+     bfd *abfd;
+     asection *sec;
+{
+  return (som_is_subspace (sec) && sec->_raw_size > 240000);
+}
+
 #define        som_close_and_cleanup           som_bfd_free_cached_info
 
+#define som_read_ar_hdr                        _bfd_generic_read_ar_hdr
 #define som_openr_next_archived_file   bfd_generic_openr_next_archived_file
+#define som_get_elt_at_index           _bfd_generic_get_elt_at_index
 #define som_generic_stat_arch_elt      bfd_generic_stat_arch_elt
 #define som_truncate_arname            bfd_bsd_truncate_arname
 #define som_slurp_extended_name_table  _bfd_slurp_extended_name_table
 #define som_update_armap_timestamp     bfd_true
+#define som_bfd_print_private_bfd_data  _bfd_generic_bfd_print_private_bfd_data
 
 #define som_get_lineno                  _bfd_nosymbols_get_lineno
 #define som_bfd_make_debug_symbol      _bfd_nosymbols_bfd_make_debug_symbol
+#define som_read_minisymbols           _bfd_generic_read_minisymbols
+#define som_minisymbol_to_symbol       _bfd_generic_minisymbol_to_symbol
+#define som_get_section_contents_in_window \
+  _bfd_generic_get_section_contents_in_window
 
 #define som_bfd_get_relocated_section_contents \
  bfd_generic_get_relocated_section_contents
@@ -5629,12 +5944,13 @@ som_bfd_free_cached_info (abfd)
 #define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define som_bfd_final_link _bfd_generic_final_link
 
+
 const bfd_target som_vec =
 {
   "som",                       /* name */
   bfd_target_som_flavour,
-  true,                                /* target byte order */
-  true,                                /* target headers byte order */
+  BFD_ENDIAN_BIG,              /* target byte order */
+  BFD_ENDIAN_BIG,              /* target headers byte order */
   (HAS_RELOC | EXEC_P |                /* object flags */
    HAS_LINENO | HAS_DEBUG |
    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
@@ -5646,7 +5962,6 @@ const bfd_target som_vec =
   0,
   '/',                         /* ar_pad_char */
   14,                          /* ar_max_namelen */
-  3,                           /* minimum alignment */
   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
   bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* data */
This page took 0.060423 seconds and 4 git commands to generate.