* som.c (hppa_object_setup): Set SEC_CODE for .text section so
authorStu Grossman <grossman@cygnus>
Tue, 26 Oct 1993 09:42:15 +0000 (09:42 +0000)
committerStu Grossman <grossman@cygnus>
Tue, 26 Oct 1993 09:42:15 +0000 (09:42 +0000)
that GDB can figure out text_start and text_end.

bfd/ChangeLog
bfd/som.c

index 92ea13baff5c8c524627dae25d6ea9bd9023371d..1f60d3e5ce27a7d54e427b29a0d85b3701dc1634 100644 (file)
@@ -1,3 +1,8 @@
+Tue Oct 26 02:40:46 1993  Stu Grossman  (grossman at cygnus.com)
+
+       * som.c (hppa_object_setup):  Set SEC_CODE for .text section so
+       that GDB can figure out text_start and text_end.
+
 Mon Oct 25 16:05:23 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
 
        Fix up warnings from gcc -Wall:
index 8fd13240adf71a8275a04ea3e0bbba5f8054e701..8d6d14d13eef1a714104c99901aa0f09e19a103b 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -4,29 +4,25 @@
    Contributed by the Center for Software Science at the
    University of Utah (pa-gdb-bugs@cs.utah.edu).
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
 
-/* @@FIXME This is not a reasonable set of conditions to permit
-   cross-compilation, obviously.  It also isn't enough to support hppa-elf
-   targets either.  Can we eliminate the HPUX or BSD dependencies, or
-   at least get the conditionals more localized?  */
 #if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD)
 
 #include "libbfd.h"
@@ -70,59 +66,81 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
      ((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID))
 #endif /* _PA_RISC_ID */
 
-struct container
-  {
-    struct header f;
-    struct som_exec_auxhdr e;
-  };
+/* Forward declarations */
+
+static boolean som_mkobject PARAMS ((bfd *));
+static bfd_target * som_object_setup PARAMS ((bfd *,
+                                             struct header *,
+                                             struct som_exec_auxhdr *));
+static asection * make_unique_section PARAMS ((bfd *, CONST char *, int));
+static boolean setup_sections PARAMS ((bfd *, struct header *));
+static bfd_target * som_object_p PARAMS ((bfd *));
+static boolean som_write_object_contents PARAMS ((bfd *));
+static boolean som_slurp_string_table PARAMS ((bfd *));
+static unsigned int som_slurp_symbol_table PARAMS ((bfd *));
+static unsigned int som_get_symtab_upper_bound PARAMS ((bfd *));
+static unsigned int som_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
+                                                   arelent **, asymbol **));
+static unsigned int som_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
+static unsigned int som_get_symtab PARAMS ((bfd *, asymbol **));
+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_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
+                                                file_ptr, bfd_size_type));
+static boolean som_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
+                                         unsigned long));
+static boolean som_find_nearest_line PARAMS ((bfd *, asection *,
+                                             asymbol **, bfd_vma,
+                                             CONST char **,
+                                             CONST char **,
+                                             unsigned int *));
+static void som_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
+static asection * som_section_from_subspace_index PARAMS ((bfd *, 
+                                                          unsigned int));
+static int log2 PARAMS ((unsigned int));
+
+
+/* Return the logarithm of X, base 2, considering X unsigned. 
+   Abort if X is not a power of two -- this should never happen.  */
+
+static int
+log2 (x)
+     unsigned int x;
+{
+  int log = 0;
+
+  /* Test for 0 or a power of 2.  */
+  if (x == 0 || x != (x & -x))
+    abort();
+
+  while ((x >>= 1) != 0)
+    log++;
+  return log;
+}
+
+/* Perform some initialization for an object.  Save results of this
+   initialization in the BFD.  */
 
 static bfd_target *
-hppa_object_setup (abfd, file_hdrp, aux_hdrp)
+som_object_setup (abfd, file_hdrp, aux_hdrp)
      bfd *abfd;
      struct header *file_hdrp;
      struct som_exec_auxhdr *aux_hdrp;
 {
-  struct container *rawptr;
-  struct header *f;
-  struct hppa_data_struct *rawptr1;
   asection *text, *data, *bss;
 
-  rawptr = (struct container *) bfd_zalloc (abfd, sizeof (struct container));
-  if (rawptr == NULL)
-    {
-      bfd_error = no_memory;
-      return 0;
-    }
-
-  rawptr1 = (struct hppa_data_struct *) bfd_zalloc (abfd, sizeof (struct hppa_data_struct));
-  if (rawptr1 == NULL)
-    {
-      bfd_error = no_memory;
-      return 0;
-    }
-
-  abfd->tdata.hppa_data = rawptr1;
-  obj_file_hdr (abfd) = &rawptr->f;
-  obj_aux_hdr (abfd) = &rawptr->e;
-  *obj_file_hdr (abfd) = *file_hdrp;
-  *obj_aux_hdr (abfd) = *aux_hdrp;
-
-  /* Set the file flags */
-  abfd->flags = NO_FLAGS;
-  if (file_hdrp->entry_offset)
-    abfd->flags |= HAS_RELOC;
-  if (file_hdrp->symbol_total)
-    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
-
-  bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
-
-  obj_pa_symbols (abfd) = (hppa_symbol_type *) NULL;
-  bfd_get_symcount (abfd) = file_hdrp->symbol_total;
+  /* som_mkobject will set bfd_error if som_mkobject fails.  */
+  if (som_mkobject (abfd) != true)
+    return 0;
 
-  bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
+  /* Make the standard .text, .data, and .bss sections so that tools
+     which assume those names work (size for example).  They will have
+     no contents, but the sizes and such will reflect those of the
+     $CODE$, $DATA$, and $BSS$ subspaces respectively.
 
-  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
-     them */
+     FIXME:  Should check return status from bfd_make_section calls below.  */
 
   text = bfd_make_section (abfd, ".text");
   data = bfd_make_section (abfd, ".data");
@@ -132,7 +150,7 @@ hppa_object_setup (abfd, file_hdrp, aux_hdrp)
   data->_raw_size = aux_hdrp->exec_dsize;
   bss->_raw_size = aux_hdrp->exec_bsize;
 
-  text->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS);
+  text->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_CODE);
   data->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS);
   bss->flags = (SEC_ALLOC | SEC_IS_COMMON);
 
@@ -149,20 +167,35 @@ hppa_object_setup (abfd, file_hdrp, aux_hdrp)
   text->rel_filepos = 0;
   data->rel_filepos = 0;
 
-  /* The file offsets of the string table and symbol table.  */
-  obj_sym_filepos (abfd) = file_hdrp->symbol_location;
+  /* Set BFD flags based on what information is available in the SOM.  */
+  abfd->flags = NO_FLAGS;
+  if (! file_hdrp->entry_offset)
+    abfd->flags |= HAS_RELOC;
+  else
+    abfd->flags |= EXEC_P;
+  if (file_hdrp->symbol_total)
+    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
+
+  bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
+  bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
   bfd_get_symcount (abfd) = file_hdrp->symbol_total;
-  obj_str_filepos (abfd) = file_hdrp->symbol_strings_location;
-  obj_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
+
+  /* Initialize the saved symbol table and string table to NULL.  
+     Save important offsets and sizes from the SOM header into
+     the BFD.  */
+  obj_som_stringtab (abfd) = (char  *) NULL;
+  obj_som_symtab (abfd) = (som_symbol_type *) NULL;
+  obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
+  obj_som_sym_filepos (abfd) = file_hdrp->symbol_location;
+  obj_som_str_filepos (abfd) = file_hdrp->symbol_strings_location;
+  obj_som_reloc_filepos (abfd) = file_hdrp->fixup_request_location;
 
   return abfd->xvec;
 }
 
 /* Create a new BFD section for NAME.  If NAME already exists, then create a
    new unique name, with NAME as the prefix.  This exists because SOM .o files
-   created by the native compiler can have a $CODE$ section for each
-   subroutine.
- */
+   may have more than one $CODE$ subspace.  */
 
 static asection *
 make_unique_section (abfd, name, num)
@@ -194,41 +227,41 @@ make_unique_section (abfd, name, num)
    BFD sections which correspond to spaces will overlap the sections for the
    associated subspaces.  */
 
-static int
+static boolean
 setup_sections (abfd, file_hdr)
      bfd *abfd;
      struct header *file_hdr;
 {
   char *space_strings;
   int space_index;
+  unsigned int total_subspaces = 0;
 
   /* First, read in space names */
 
   space_strings = alloca (file_hdr->space_strings_size);
   if (!space_strings)
-    return 0;
+    return false;
 
   if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
-    return 0;
+    return false;
   if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
       != file_hdr->space_strings_size)
-    return 0;
+    return false;
 
   /* Loop over all of the space dictionaries, building up sections */
-
   for (space_index = 0; space_index < file_hdr->space_total; space_index++)
     {
       struct space_dictionary_record space;
-      struct subspace_dictionary_record subspace;
-      int subspace_index, tmp;
+      struct subspace_dictionary_record subspace, save_subspace;
+      int subspace_index;
       asection *space_asect;
 
       /* Read the space dictionary element */
       if (bfd_seek (abfd, file_hdr->space_location
                    + space_index * sizeof space, SEEK_SET) < 0)
-       return 0;
+       return false;
       if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
-       return 0;
+       return false;
 
       /* Setup the space name string */
       space.name.n_name = space.name.n_strx + space_strings;
@@ -236,33 +269,29 @@ setup_sections (abfd, file_hdr)
       /* Make a section out of it */
       space_asect = make_unique_section (abfd, space.name.n_name, space_index);
       if (!space_asect)
-       return 0;
+       return false;
 
       /* Now, read in the first subspace for this space */
       if (bfd_seek (abfd, file_hdr->subspace_location
                    + space.subspace_index * sizeof subspace,
                    SEEK_SET) < 0)
-       return 0;
+       return false;
       if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
-       return 0;
+       return false;
       /* Seek back to the start of the subspaces for loop below */
       if (bfd_seek (abfd, file_hdr->subspace_location
                    + space.subspace_index * sizeof subspace,
                    SEEK_SET) < 0)
-       return 0;
-
-      /* Setup the section flags as appropriate (this is somewhat bogus, as
-        there isn't a clear mapping between what's in the space record, and
-        what BFD can describe here). */
-      if (space.is_loadable)
-       space_asect->flags |= SEC_ALLOC;
-      if (space.is_defined)
-       space_asect->flags |= SEC_LOAD;
+       return false;
 
       /* Setup the start address and file loc from the first subspace record */
       space_asect->vma = subspace.subspace_start;
       space_asect->filepos = subspace.file_loc_init_value;
-      space_asect->alignment_power = subspace.alignment;
+      space_asect->alignment_power = log2 (subspace.alignment);
+
+      /* Initialize save_subspace so we can reliably determine if this
+        loop placed any useful values into it.  */
+      bzero (&save_subspace, sizeof (struct subspace_dictionary_record));
 
       /* Loop over the rest of the subspaces, building up more sections */
       for (subspace_index = 0; subspace_index < space.subspace_quantity;
@@ -273,7 +302,7 @@ setup_sections (abfd, file_hdr)
          /* Read in the next subspace */
          if (bfd_read (&subspace, 1, sizeof subspace, abfd)
              != sizeof subspace)
-           return 0;
+           return false;
 
          /* Setup the subspace name string */
          subspace.name.n_name = subspace.name.n_strx + space_strings;
@@ -283,39 +312,108 @@ setup_sections (abfd, file_hdr)
                                     space.subspace_index + subspace_index);
 
          if (!subspace_asect)
-           return 0;
-
+           return false;
+
+         /* Keep an easy mapping between subspaces and sections.  */
+         som_section_data (subspace_asect)->subspace_index 
+           = total_subspaces++;
+
+         /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
+            by the access_control_bits in the subspace header.  */
+         switch (subspace.access_control_bits >> 4)
+           {
+           /* Readonly data.  */  
+           case 0x0:
+             subspace_asect->flags |= SEC_DATA | SEC_READONLY;
+             break;
+
+           /* Normal data.  */  
+           case 0x1:
+             subspace_asect->flags |= SEC_DATA;
+             break;
+
+           /* Readonly code and the gateways.
+              Gateways have other attributes which do not map
+              into anything BFD knows about.  */
+           case 0x2:
+           case 0x4:
+           case 0x5:
+           case 0x6:
+           case 0x7:
+             subspace_asect->flags |= SEC_CODE | SEC_READONLY;
+             break;
+
+           /* dynamic (writable) code.  */
+           case 0x3:
+             subspace_asect->flags |= SEC_CODE;
+             break;
+           }
+         
+         if (subspace.dup_common || subspace.is_common) 
+           subspace_asect->flags |= SEC_IS_COMMON;
+         else
+           subspace_asect->flags |= SEC_HAS_CONTENTS;
          if (subspace.is_loadable)
            subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
          if (subspace.code_only)
            subspace_asect->flags |= SEC_CODE;
 
+         /* This subspace has relocations.
+            The fixup_request_quantity is a byte count for the number of
+            entries in the relocation stream; it is not the actual number
+            of relocations in the subspace.  */
+         if (subspace.fixup_request_quantity != 0)
+           {
+             subspace_asect->flags |= SEC_RELOC;
+             subspace_asect->rel_filepos = subspace.fixup_request_index;
+             som_section_data (subspace_asect)->reloc_size
+               = subspace.fixup_request_quantity;
+             /* We can not determine this yet.  When we read in the 
+                relocation table the correct value will be filled in.  */
+             subspace_asect->reloc_count = -1;
+           }
+
+         /* Update save_subspace if appropriate.  */
+         if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
+           save_subspace = subspace;
+
          subspace_asect->vma = subspace.subspace_start;
          subspace_asect->_cooked_size = subspace.subspace_length;
          subspace_asect->_raw_size = subspace.initialization_length;
-         subspace_asect->alignment_power = subspace.alignment;
+         subspace_asect->alignment_power = log2 (subspace.alignment);
          subspace_asect->filepos = subspace.file_loc_init_value;
-
        }
+
+      /* Yow! there is no subspace within the space which actually 
+         has initialized information in it; this should never happen
+         as far as I know.  */
+      if (!save_subspace.file_loc_init_value)
+       abort ();
+
       /* Setup the sizes for the space section based upon the info in the
-        last subspace of the space. */
-      space_asect->_cooked_size = (subspace.subspace_start - space_asect->vma)
-       + subspace.subspace_length;
-      space_asect->_raw_size = (subspace.file_loc_init_value
-                               - space_asect->filepos)
-       + subspace.initialization_length;
+         last subspace of the space.  */
+      space_asect->_cooked_size = save_subspace.subspace_start
+       - space_asect->vma + save_subspace.subspace_length;
+      space_asect->_raw_size = save_subspace.file_loc_init_value
+       - space_asect->filepos + save_subspace.initialization_length;
     }
+  return true;
 }
 
+/* Read in a SOM object and make it into a BFD.  */
+
 static bfd_target *
-hppa_object_p (abfd)
+som_object_p (abfd)
      bfd *abfd;
 {
   struct header file_hdr;
   struct som_exec_auxhdr aux_hdr;
 
   if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
-    return 0;
+    {
+      bfd_error = system_call_error;
+      return 0;
+    }
 
   if (!_PA_RISC_ID (file_hdr.system_id))
     {
@@ -325,7 +423,7 @@ hppa_object_p (abfd)
 
   switch (file_hdr.a_magic)
     {
-    case RELOC_MAGIC:          /* I'm not really sure about all of these types... */
+    case RELOC_MAGIC:
     case EXEC_MAGIC:
     case SHARE_MAGIC:
     case DEMAND_MAGIC:
@@ -334,6 +432,9 @@ hppa_object_p (abfd)
 #endif
 #ifdef SHL_MAGIC
     case SHL_MAGIC:
+#endif
+#ifdef EXECLIBMAGIC
+    case EXECLIBMAGIC:
 #endif
       break;
     default:
@@ -348,143 +449,414 @@ hppa_object_p (abfd)
       return 0;
     }
 
-  if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
-    bfd_error = wrong_format;
+  /* If the aux_header_size field in the file header is zero, then this
+     object is an incomplete executable (a .o file).  Do not try to read
+     a non-existant auxiliary header.  */
+  bzero (&aux_hdr, sizeof (struct som_exec_auxhdr));
+  if (file_hdr.aux_header_size != 0)
+    {
+      if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
+       {
+         bfd_error = wrong_format;
+         return 0;
+       }
+    }
 
   if (!setup_sections (abfd, &file_hdr))
-    return 0;
+    {
+      /* setup_sections does not bubble up a bfd error code.  */
+      bfd_error = bad_value;
+      return 0;
+    }
 
-  return hppa_object_setup (abfd, &file_hdr, &aux_hdr);
+  /* This appears to be a valid SOM object.  Do some initialization.  */
+  return som_object_setup (abfd, &file_hdr, &aux_hdr);
 }
 
+/* Create a SOM object.  */
+
 static boolean
-hppa_mkobject (abfd)
+som_mkobject (abfd)
      bfd *abfd;
 {
-  fprintf (stderr, "hppa_mkobject unimplemented\n");
-  fflush (stderr);
-  abort ();
-  return (false);
+  /* Allocate memory to hold backend information.  */
+  abfd->tdata.som_data = (struct som_data_struct *)
+    bfd_zalloc (abfd, sizeof (struct som_data_struct));
+  if (abfd->tdata.som_data == NULL)
+    {
+      bfd_error = no_memory;
+      return false;
+    }
+  obj_som_file_hdr (abfd) = bfd_zalloc (abfd, sizeof (struct header));
+  if (obj_som_file_hdr (abfd) == NULL)
+
+    {
+      bfd_error = no_memory;
+      return false;
+    }
+  return true;
 }
 
 boolean
-hppa_write_object_contents(abfd)
+som_write_object_contents (abfd)
      bfd *abfd;
 {
-  fprintf (stderr, "hppa_write_object_contents unimplemented\n");
+  fprintf (stderr, "som_write_object_contents unimplemented\n");
   fflush (stderr);
   abort ();
   return (false);
 }
+/* Read and save the string table associated with the given BFD.  */
 
-static unsigned int
-hppa_get_symtab_upper_bound (abfd)
+static boolean
+som_slurp_string_table (abfd)
      bfd *abfd;
 {
-  fprintf (stderr, "hppa_get_symtab_upper_bound unimplemented\n");
-  fflush (stderr);
-  abort ();
-  return (0);
+  char *stringtab;
+
+  /* Use the saved version if its available.  */
+  if (obj_som_stringtab (abfd) != NULL)
+    return true;
+
+  /* Allocate and read in the string table.  */
+  stringtab = bfd_zalloc (abfd, obj_som_stringtab_size (abfd));
+  if (stringtab == NULL)
+    {
+      bfd_error = no_memory;
+      return false;
+    }
+
+  if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+  
+  if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
+      != obj_som_stringtab_size (abfd))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* Save our results and return success. */
+  obj_som_stringtab (abfd) = stringtab;
+  return true;
 }
 
+/* Return the amount of data (in bytes) required to hold the symbol
+   table for this object.  */
+
 static unsigned int
-hppa_get_reloc_upper_bound (abfd, asect)
+som_get_symtab_upper_bound (abfd)
      bfd *abfd;
-     sec_ptr asect;
 {
-  fprintf (stderr, "hppa_get_reloc_upper_bound unimplemented\n");
-  fflush (stderr);
-  abort ();
-  return (0);
+  if (!som_slurp_symbol_table (abfd))
+    return 0;
+
+  return (bfd_get_symcount (abfd) + 1) * (sizeof (som_symbol_type *));
 }
 
+/* Convert from a SOM subspace index to a BFD section.  */
+
+static asection *
+som_section_from_subspace_index (abfd, index)
+     bfd *abfd;
+     unsigned int index;
+{
+  asection *section;
+
+  for (section = abfd->sections; section != NULL; section = section->next)
+    if (som_section_data (section)->subspace_index == index)
+      return section;
+
+  /* Should never happen.  */
+  abort();
+}
+
+/* Read and save the symbol table associated with the given BFD.  */
+
 static unsigned int
-hppa_canonicalize_reloc (abfd, section, relptr, symbols)
+som_slurp_symbol_table (abfd)
      bfd *abfd;
-     sec_ptr section;
-     arelent **relptr;
-     asymbol **symbols;
 {
-  fprintf (stderr, "hppa_canonicalize_reloc unimplemented\n");
-  fflush (stderr);
-  abort ();
+  int symbol_count = bfd_get_symcount (abfd);
+  int symsize = sizeof (struct symbol_dictionary_record);
+  char *stringtab;
+  struct symbol_dictionary_record *buf, *bufp, *endbufp;
+  som_symbol_type *sym, *symbase;
+
+  /* Return saved value if it exists.  */
+  if (obj_som_symtab (abfd) != NULL)
+    return true;
+
+  /* Sanity checking.  Make sure there are some symbols and that 
+     we can read the string table too.  */
+  if (symbol_count == 0)
+    {
+      bfd_error = no_symbols;
+      return false;
+    }
+
+  if (!som_slurp_string_table (abfd))
+    return false;
+
+  stringtab = obj_som_stringtab (abfd);
+
+  symbase = (som_symbol_type *)
+    bfd_zalloc (abfd, symbol_count * sizeof (som_symbol_type));
+  if (symbase == NULL)
+    {
+      bfd_error = no_memory;
+      return false;
+    }
+
+  /* Read in the external SOM representation.  */
+  buf = alloca (symbol_count * symsize);
+  if (buf == NULL)
+    {
+      bfd_error = no_memory;
+      return false;
+    }
+  if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+  if (bfd_read (buf, symbol_count * symsize, 1, abfd) 
+      != symbol_count * symsize)
+    {
+      bfd_error = no_symbols;
+      return (false);
+    }
+
+  /* Iterate over all the symbols and internalize them.  */
+  endbufp = buf + symbol_count;
+  for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
+    {
+
+      /* I don't think we care about these.  */
+      if (bufp->symbol_type == ST_SYM_EXT
+         || bufp->symbol_type == ST_ARG_EXT)
+       continue;
+
+      /* Some reasonable defaults.  */
+      sym->symbol.the_bfd = abfd;
+      sym->symbol.name = bufp->name.n_strx + stringtab;
+      sym->symbol.value = bufp->symbol_value;
+      sym->symbol.section = 0;
+      sym->symbol.flags = 0;
+
+      switch (bufp->symbol_type)
+       {
+       case ST_ENTRY:
+         sym->symbol.flags |= BSF_FUNCTION;
+         sym->symbol.value &= ~0x3;
+         break;
+
+       case ST_PRI_PROG:
+       case ST_SEC_PROG:
+       case ST_STUB:
+       case ST_MILLICODE:
+       case ST_CODE:
+         sym->symbol.value &= ~0x3;
+
+       default:
+         break;
+       }
+
+      /* Handle scoping and section information.  */
+      switch (bufp->symbol_scope)
+       {
+       /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
+          so the section associated with this symbol can't be known.  */
+       case SS_EXTERNAL:
+       case SS_UNSAT:
+         sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
+         break;
+
+       case SS_UNIVERSAL:
+         sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
+         sym->symbol.section
+           = som_section_from_subspace_index (abfd, bufp->symbol_info);
+         sym->symbol.value -= sym->symbol.section->vma;
+         break;
+
+#if 0
+       /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
+          Sound dumb?  It is.  */
+       case SS_GLOBAL:
+#endif
+       case SS_LOCAL:
+         sym->symbol.flags |= BSF_LOCAL;
+         sym->symbol.section
+           = som_section_from_subspace_index (abfd, bufp->symbol_info);
+         sym->symbol.value -= sym->symbol.section->vma;
+         break;
+       }
+
+      /* Mark symbols left around by the debugger.  */
+      if (strlen (sym->symbol.name) >= 3
+         && sym->symbol.name[0] == 'L'
+         && (sym->symbol.name[2] == '$' || sym->symbol.name[3] == '$'))
+       sym->symbol.flags |= BSF_DEBUGGING;
+
+      /* Note increment at bottom of loop, since we skip some symbols
+         we can not include it as part of the for statement.  */
+      sym++;
+    }
+
+  /* Save our results and return success.  */
+  obj_som_symtab (abfd) = symbase;
+  return (true);
 }
 
-extern bfd_target hppa_vec;
+/* Canonicalize a SOM symbol table.  Return the number of entries
+   in the symbol table.  */
 
 static unsigned int
-hppa_get_symtab (abfd, location)
+som_get_symtab (abfd, location)
      bfd *abfd;
      asymbol **location;
 {
-  fprintf (stderr, "hppa_get_symtab unimplemented\n");
-  fflush (stderr);
-  abort ();
-  return (0);
+  int i;
+  som_symbol_type *symbase;
+
+  if (!som_slurp_symbol_table (abfd))
+    return 0;
+
+  i = bfd_get_symcount (abfd);
+  symbase = obj_som_symtab (abfd);
+
+  for (; i > 0; i--, location++, symbase++)
+    *location = &symbase->symbol;
+
+  /* Final null pointer.  */
+  *location = 0;
+  return (bfd_get_symcount (abfd));
 }
 
+/* Make a SOM symbol.  There is nothing special to do here.  */
+
 static asymbol *
-hppa_make_empty_symbol (abfd)
+som_make_empty_symbol (abfd)
      bfd *abfd;
 {
-  hppa_symbol_type *new =
-  (hppa_symbol_type *) bfd_zalloc (abfd, sizeof (hppa_symbol_type));
+  som_symbol_type *new =
+  (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
+  if (new == NULL)
+    {
+      bfd_error = no_memory;
+      return 0;
+    }
   new->symbol.the_bfd = abfd;
 
   return &new->symbol;
 }
 
+/* Print symbol information.  */
+
 static void
-hppa_print_symbol (ignore_abfd, afile, symbol, how)
+som_print_symbol (ignore_abfd, afile, symbol, how)
      bfd *ignore_abfd;
      PTR afile;
      asymbol *symbol;
      bfd_print_symbol_type how;
 {
-  fprintf (stderr, "hppa_print_symbol unimplemented\n");
+  FILE *file = (FILE *) afile;
+  switch (how)
+    {
+    case bfd_print_symbol_name:
+      fprintf (file, "%s", symbol->name);
+      break;
+    case bfd_print_symbol_more:
+      fprintf (file, "som ");
+      fprintf_vma (file, symbol->value);
+      fprintf (file, " %lx", (long) symbol->flags);
+      break;
+    case bfd_print_symbol_all:
+      {
+       CONST char *section_name;
+       section_name = symbol->section ? symbol->section->name : "(*none*)";
+       bfd_print_symbol_vandf ((PTR) file, symbol);
+       fprintf (file, " %s\t%s", section_name, symbol->name);
+       break;
+      }
+    }
+}
+
+static unsigned int
+som_get_reloc_upper_bound (abfd, asect)
+     bfd *abfd;
+     sec_ptr asect;
+{
+  fprintf (stderr, "som_get_reloc_upper_bound unimplemented\n");
   fflush (stderr);
   abort ();
+  return (0);
 }
 
+static unsigned int
+som_canonicalize_reloc (abfd, section, relptr, symbols)
+     bfd *abfd;
+     sec_ptr section;
+     arelent **relptr;
+     asymbol **symbols;
+{
+  fprintf (stderr, "som_canonicalize_reloc unimplemented\n");
+  fflush (stderr);
+  abort ();
+}
+
+extern bfd_target som_vec;
+
+/* A hook to set up object file dependent section information.  */
+
 static boolean
-hppa_new_section_hook (abfd, newsect)
+som_new_section_hook (abfd, newsect)
      bfd *abfd;
      asection *newsect;
 {
+  newsect->used_by_bfd = (struct som_section_data_struct *)
+    bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
   newsect->alignment_power = 3;
 
+  /* Initialize the subspace_index field to -1 so that it does
+     not match a subspace with an index of 0.  */
+  som_section_data (newsect)->subspace_index = -1;
+
   /* We allow more than three sections internally */
   return true;
 }
 
 static boolean
-hppa_set_section_contents (abfd, section, location, offset, count)
+som_set_section_contents (abfd, section, location, offset, count)
      bfd *abfd;
      sec_ptr section;
      PTR location;
      file_ptr offset;
      bfd_size_type count;
 {
-  fprintf (stderr, "hppa_set_section_contents unimplimented\n");
+  fprintf (stderr, "som_set_section_contents unimplimented\n");
   fflush (stderr);
   abort ();
   return false;
 }
 
 static boolean
-hppa_set_arch_mach (abfd, arch, machine)
+som_set_arch_mach (abfd, arch, machine)
      bfd *abfd;
      enum bfd_architecture arch;
      unsigned long machine;
 {
-  fprintf (stderr, "hppa_set_arch_mach unimplemented\n");
+  fprintf (stderr, "som_set_arch_mach unimplemented\n");
   fflush (stderr);
-  /* Allow any architecture to be supported by the hppa backend */
+  /* Allow any architecture to be supported by the som backend */
   return bfd_default_set_arch_mach (abfd, arch, machine);
 }
 
 static boolean
-hppa_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
+som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
                        functionname_ptr, line_ptr)
      bfd *abfd;
      asection *section;
@@ -494,18 +866,18 @@ hppa_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
      CONST char **functionname_ptr;
      unsigned int *line_ptr;
 {
-  fprintf (stderr, "hppa_find_nearest_line unimplemented\n");
+  fprintf (stderr, "som_find_nearest_line unimplemented\n");
   fflush (stderr);
   abort ();
   return (false);
 }
 
 static int
-hppa_sizeof_headers (abfd, reloc)
+som_sizeof_headers (abfd, reloc)
      bfd *abfd;
      boolean reloc;
 {
-  fprintf (stderr, "hppa_sizeof_headers unimplemented\n");
+  fprintf (stderr, "som_sizeof_headers unimplemented\n");
   fflush (stderr);
   abort ();
   return (0);
@@ -514,7 +886,7 @@ hppa_sizeof_headers (abfd, reloc)
 /* Return information about SOM symbol SYMBOL in RET.  */
 
 static void
-hppa_get_symbol_info (ignore_abfd, symbol, ret)
+som_get_symbol_info (ignore_abfd, symbol, ret)
      bfd *ignore_abfd;         /* Ignored.  */
      asymbol *symbol;
      symbol_info *ret;
@@ -524,78 +896,78 @@ hppa_get_symbol_info (ignore_abfd, symbol, ret)
 
 /* End of miscellaneous support functions. */
 
-#define hppa_bfd_debug_info_start        bfd_void
-#define hppa_bfd_debug_info_end          bfd_void
-#define hppa_bfd_debug_info_accumulate   (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
+#define som_bfd_debug_info_start        bfd_void
+#define som_bfd_debug_info_end          bfd_void
+#define som_bfd_debug_info_accumulate   (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
 
-#define hppa_openr_next_archived_file    bfd_generic_openr_next_archived_file
-#define hppa_generic_stat_arch_elt       bfd_generic_stat_arch_elt
-#define hppa_slurp_armap                  bfd_false
-#define hppa_slurp_extended_name_table    _bfd_slurp_extended_name_table
-#define hppa_truncate_arname              (void (*)())bfd_nullvoidptr
-#define hppa_write_armap                  0
+#define som_openr_next_archived_file    bfd_generic_openr_next_archived_file
+#define som_generic_stat_arch_elt       bfd_generic_stat_arch_elt
+#define som_slurp_armap                  bfd_false
+#define som_slurp_extended_name_table    _bfd_slurp_extended_name_table
+#define som_truncate_arname              (void (*)())bfd_nullvoidptr
+#define som_write_armap                  0
 
-#define hppa_get_lineno                   (struct lineno_cache_entry *(*)())bfd_nullvoidptr
-#define        hppa_close_and_cleanup             bfd_generic_close_and_cleanup
-#define hppa_get_section_contents          bfd_generic_get_section_contents
+#define som_get_lineno                   (struct lineno_cache_entry *(*)())bfd_nullvoidptr
+#define        som_close_and_cleanup              bfd_generic_close_and_cleanup
+#define som_get_section_contents          bfd_generic_get_section_contents
 
-#define hppa_bfd_get_relocated_section_contents \
+#define som_bfd_get_relocated_section_contents \
  bfd_generic_get_relocated_section_contents
-#define hppa_bfd_relax_section bfd_generic_relax_section
-#define hppa_bfd_seclet_link bfd_generic_seclet_link
-#define hppa_bfd_reloc_type_lookup \
+#define som_bfd_relax_section bfd_generic_relax_section
+#define som_bfd_seclet_link bfd_generic_seclet_link
+#define som_bfd_reloc_type_lookup \
   ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
-#define hppa_bfd_make_debug_symbol \
+#define som_bfd_make_debug_symbol \
   ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
 
 /* Core file support is in the hpux-core backend.  */
-#define hppa_core_file_failing_command _bfd_dummy_core_file_failing_command
-#define hppa_core_file_failing_signal  _bfd_dummy_core_file_failing_signal
-#define hppa_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
+#define som_core_file_failing_command  _bfd_dummy_core_file_failing_command
+#define som_core_file_failing_signal   _bfd_dummy_core_file_failing_signal
+#define som_core_file_matches_executable_p     _bfd_dummy_core_file_matches_executable_p
 
-bfd_target hppa_vec =
+bfd_target som_vec =
 {
-  "hppa",                      /* name */
-  bfd_target_hppa_flavour,
+  "som",                       /* name */
+  bfd_target_som_flavour,
   true,                                /* target byte order */
   true,                                /* target headers byte order */
   (HAS_RELOC | EXEC_P |                /* object flags */
    HAS_LINENO | HAS_DEBUG |
    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
-   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),        /* section flags */
+   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),                /* section flags */
 
 /* leading_symbol_char: is the first char of a user symbol
-      predictable, and if so what is it */
+   predictable, and if so what is it */
   0,
   ' ',                         /* ar_pad_char */
   16,                          /* ar_max_namelen */
   3,                           /* minimum alignment */
-  _do_getb64, _do_getb_signed_64, _do_putb64,
-  _do_getb32, _do_getb_signed_32, _do_putb32,
-  _do_getb16, _do_getb_signed_16, _do_putb16,  /* data */
-  _do_getb64, _do_getb_signed_64, _do_putb64,
-  _do_getb32, _do_getb_signed_32, _do_putb32,
-  _do_getb16, _do_getb_signed_16, _do_putb16,  /* hdrs */
+  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 */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* hdrs */
   {_bfd_dummy_target,
-   hppa_object_p,              /* bfd_check_format */
+   som_object_p,               /* bfd_check_format */
    bfd_generic_archive_p,
    _bfd_dummy_target
   },
   {
     bfd_false,
-    hppa_mkobject,
+    som_mkobject,
     _bfd_generic_mkarchive,
     bfd_false
   },
   {
     bfd_false,
-    hppa_write_object_contents,
+    som_write_object_contents,
     _bfd_write_archive_contents,
     bfd_false,
   },
-#undef hppa
-  JUMP_TABLE (hppa),
+#undef som
+  JUMP_TABLE (som),
   (PTR) 0
 };