* som.c (som_build_and_write_symbol_table): New function.
authorJeff Law <law@redhat.com>
Sat, 13 Nov 1993 08:37:14 +0000 (08:37 +0000)
committerJeff Law <law@redhat.com>
Sat, 13 Nov 1993 08:37:14 +0000 (08:37 +0000)
bfd/ChangeLog
bfd/som.c

index 7fec4e9219b647fc17c543296b4782e18b977e6f..56ce98aa277b45154ff95e13a5d342ef63685d35 100644 (file)
@@ -2,6 +2,7 @@ Fri Nov 12 15:29:36 1993  Jeffrey A. Law  (law@snake.cs.utah.edu)
 
        * som.c (som_write_headers): New function.
        (som_prep_headers): New function.
+       (som_build_and_write_symbol_table): New function.
 
        * som.c (som_sizeof_headers): Add missing prototype.
        (som_set_arch_mach): Do not abort.
index 03b7ae43b0b4e5c573e510fe4eb7bcb93434ca17..bfe8af2beaaf0e8e23a0a070635acca9fe8698c9 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -160,6 +160,8 @@ 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_build_and_write_symbol_table PARAMS ((bfd *));
+
 
 static reloc_howto_type som_hppa_howto_table[] =
 {
@@ -1632,6 +1634,159 @@ som_compute_checksum (abfd)
   return checksum;
 }
 
+/* Build and write, in one big chunk, the entire symbol table for
+   this BFD.  */
+
+static boolean
+som_build_and_write_symbol_table (abfd)
+     bfd *abfd;
+{
+  unsigned int num_syms = bfd_get_symcount (abfd);
+  file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
+  asymbol **bfd_syms = bfd_get_outsymbols (abfd);
+  struct symbol_dictionary_record *som_symtab;
+  int i, symtab_size;
+
+  /* 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 *) alloca (symtab_size);
+  bzero (som_symtab, symtab_size);
+
+  /* Walk over each symbol.  */
+  for (i = 0; i < num_syms; i++)
+    {
+      /* This is really an index into the symbol strings table.  
+        By the time we get here, the index has already been 
+        computed and stored into the name field in the BFD symbol.  */
+      som_symtab[i].name.n_strx = (int) bfd_syms[i]->name;
+
+      /* The HP SOM linker requires detailed type information about
+        all symbols (including undefined symbols!).  Unfortunately,
+        the type specified in an import/export statement does not
+        always match what the linker wants.  Severe braindamage.  */
+        
+      /* Section symbols will not have a SOM symbol type assigned to
+        them yet.  Assign all section symbols type ST_DATA.  */
+      if (bfd_syms[i]->flags & BSF_SECTION_SYM)
+       som_symtab[i].symbol_type = ST_DATA;
+      else
+       {
+         /* Common symbols must have scope SS_UNSAT and type
+            ST_STORAGE or the linker will choke.  */
+         if (bfd_syms[i]->section == &bfd_com_section)
+           {
+             som_symtab[i].symbol_scope = SS_UNSAT;
+             som_symtab[i].symbol_type = ST_STORAGE;
+           }
+
+         /* It is possible to have a symbol without an associated
+            type.  This happens if the user imported the symbol
+            without a type and the symbol was never defined
+            locally.  If BSF_FUNCTION is set for this symbol, then
+            assign it type ST_CODE (the HP linker requires undefined
+            external functions to have type ST_CODE rather than ST_ENTRY.  */
+         else if (((*som_symbol_data (bfd_syms[i]))->som_type
+                   == SYMBOL_TYPE_UNKNOWN)
+                  && (bfd_syms[i]->section == &bfd_und_section)
+                  && (bfd_syms[i]->flags & BSF_FUNCTION))
+           som_symtab[i].symbol_type = ST_CODE;
+
+         /* Handle function symbols which were defined in this file.
+            They should have type ST_ENTRY.  Also retrieve the argument
+            relocation bits from the SOM backend information.  */
+         else if (((*som_symbol_data (bfd_syms[i]))->som_type
+                   == SYMBOL_TYPE_ENTRY)
+                  || (((*som_symbol_data (bfd_syms[i]))->som_type
+                       == SYMBOL_TYPE_CODE)
+                      && (bfd_syms[i]->flags & BSF_FUNCTION))
+                  || (((*som_symbol_data (bfd_syms[i]))->som_type
+                       == SYMBOL_TYPE_UNKNOWN)
+                      && (bfd_syms[i]->flags & BSF_FUNCTION)))
+           {
+             som_symtab[i].symbol_type = ST_ENTRY;
+             som_symtab[i].arg_reloc
+               = (*som_symbol_data (bfd_syms[i]))->tc_data.hppa_arg_reloc;
+           }
+
+         /* If the type is unknown at this point, it should be
+            ST_DATA (functions were handled as special cases above).  */
+         else if ((*som_symbol_data (bfd_syms[i]))->som_type
+                  == SYMBOL_TYPE_UNKNOWN)
+           som_symtab[i].symbol_type = ST_DATA;
+
+         /* From now on it's a very simple mapping.  */
+         else if ((*som_symbol_data (bfd_syms[i]))->som_type
+                  == SYMBOL_TYPE_ABSOLUTE)
+           som_symtab[i].symbol_type = ST_ABSOLUTE;
+         else if ((*som_symbol_data (bfd_syms[i]))->som_type
+                  == SYMBOL_TYPE_CODE)
+           som_symtab[i].symbol_type = ST_CODE;
+         else if ((*som_symbol_data (bfd_syms[i]))->som_type
+                  == SYMBOL_TYPE_DATA)
+           som_symtab[i].symbol_type = ST_DATA;
+         else if ((*som_symbol_data (bfd_syms[i]))->som_type
+                  == SYMBOL_TYPE_MILLICODE)
+           som_symtab[i].symbol_type = ST_MILLICODE;
+         else if ((*som_symbol_data (bfd_syms[i]))->som_type
+                  == SYMBOL_TYPE_PLABEL)
+           som_symtab[i].symbol_type = ST_PLABEL;
+         else if ((*som_symbol_data (bfd_syms[i]))->som_type
+                  == SYMBOL_TYPE_PRI_PROG)
+           som_symtab[i].symbol_type = ST_PRI_PROG;
+         else if ((*som_symbol_data (bfd_syms[i]))->som_type
+                  == SYMBOL_TYPE_SEC_PROG)
+           som_symtab[i].symbol_type = ST_SEC_PROG;
+       }
+       
+      /* 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 (bfd_syms[i]->flags & BSF_EXPORT
+         && bfd_syms[i]->section != &bfd_com_section)
+       som_symtab[i].symbol_scope = SS_UNIVERSAL;
+      /* Any undefined symbol at this point has a scope SS_UNSAT.  */
+      else if (bfd_syms[i]->section == &bfd_und_section)
+       som_symtab[i].symbol_scope = SS_UNSAT;
+      /* Anything else which is not in the common section has scope
+        SS_LOCAL.  */
+      else if (bfd_syms[i]->section != &bfd_com_section)
+       som_symtab[i].symbol_scope = SS_LOCAL;
+
+      /* Now set the symbol_info field.  It has no real meaning
+        for undefined or common symbols, but the HP linker will
+        choke if it's not set to some "reasonable" value.  We
+        use zero as a reasonable value.  */
+      if (bfd_syms[i]->section == &bfd_com_section
+         || bfd_syms[i]->section == &bfd_und_section)
+       som_symtab[i].symbol_info = 0;
+      /* For all other symbols, the symbol_info field contains the 
+        subspace index of the space this symbol is contained in.  */
+      else
+       som_symtab[i].symbol_info
+         = som_section_data (bfd_syms[i]->section)->subspace_index;
+
+      /* Set the symbol's value.  */
+      som_symtab[i].symbol_value
+       = bfd_syms[i]->value + bfd_syms[i]->section->vma;
+    }
+
+  /* Egad.  Everything is ready, seek to the right location and
+     scribble out the symbol table.  */
+  if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  if (bfd_write ((PTR) som_symtab, symtab_size, 1, abfd) != symtab_size)
+    {
+      bfd_error  = system_call_error;
+      return false;
+    }
+  return true; 
+}
+
 boolean
 som_write_object_contents (abfd)
      bfd *abfd;