* Finish basic read-write support for SOM archive libraries. Bugs
authorJeff Law <law@redhat.com>
Tue, 15 Feb 1994 07:05:04 +0000 (07:05 +0000)
committerJeff Law <law@redhat.com>
Tue, 15 Feb 1994 07:05:04 +0000 (07:05 +0000)
surely remain as this hasn't been tested all that much.
* som.c (SOM_LST_HASH_SIZE, SOM_LST_MODULE_LIMIT): Define.
(struct som_misc_symbol_info): New structure to hold info necessary
to build both normal and library symbol tables.
(som_derive_misc_symbol_info): New function to derive info necessary
to build both normal and library symbol tables.
(som_build_and_write_symbol_table): Use new function to derive misc
symbol information.
(som_slurp_symbol_table): Update backend private data for symbols
appropriately.
(som_bfd_prep_for_ar_write): New function.
(som_bfd_ar_symbol_hash): New function.
(som_bfd_ar_write_symbol_stuff): New function.
(som_write_armap): Flesh out.
(som_vec): Fix ar padding character.

* som.c: Consistently use memset rather than bzero.

bfd/ChangeLog
bfd/som.c

index 28dc9f30151e584369dd2a4caf286e73994b077c..7f5bfff2d3ae95d2c112182efdb7248035bed43d 100644 (file)
@@ -1,3 +1,24 @@
+Mon Feb 14 22:55:20 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * Finish basic read-write support for SOM archive libraries.  Bugs
+       surely remain as this hasn't been tested all that much.
+       * som.c (SOM_LST_HASH_SIZE, SOM_LST_MODULE_LIMIT): Define.
+       (struct som_misc_symbol_info): New structure to hold info necessary
+       to build both normal and library symbol tables.
+       (som_derive_misc_symbol_info): New function to derive info necessary
+       to build both normal and library symbol tables.
+       (som_build_and_write_symbol_table): Use new function to derive misc
+       symbol information.
+       (som_slurp_symbol_table): Update backend private data for symbols
+       appropriately.
+       (som_bfd_prep_for_ar_write): New function.
+       (som_bfd_ar_symbol_hash): New function.
+       (som_bfd_ar_write_symbol_stuff): New function.
+       (som_write_armap): Flesh out.
+       (som_vec): Fix ar padding character.
+
+       * som.c: Consistently use memset rather than bzero.
+
 Mon Feb 14 17:02:28 1994  Stu Grossman  (grossman at cygnus.com)
 
        * coff-rs6000.c:  Add Lynx core file support, use HOST_AIX, where
@@ -14,6 +35,7 @@ Sun Feb 13 14:30:00 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
        * som.h (som_symbol_data): Safely access backend private data
        for BFD symbols.  All callers changed.
 
+       * Read-only SOM archive support.
        * som.c (som_bfd_count_ar_symbols): New helper function.
        (som_bfd_fill_in_ar_symbols): New helper function.
        (som_slurp_armap): New function to read a SOM LST.
index 24d2a747304b98e7b96db31aa66f0f4839bade48..758f3065bd0eb3353fc8008eeb56c3bd4546836f 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
    
 #define SOM_TMP_BUFSIZE 8192
 
+/* Size of the hash table in archives.  */
+#define SOM_LST_HASH_SIZE 31
+
+/* Max number of SOMs to be found in an archive.  */
+#define SOM_LST_MODULE_LIMIT 1024
 
 /* SOM allows any one of the four previous relocations to be reused
    with a "R_PREV_FIXUP" relocation entry.  Since R_PREV_FIXUP
@@ -108,6 +113,17 @@ struct section_to_type
   char type;
 };
 
+/* Assorted symbol information that needs to be derived from the BFD symbol
+   and/or the BFD backend private symbol data.  */
+struct som_misc_symbol_info
+{
+  unsigned int symbol_type;
+  unsigned int symbol_scope;
+  unsigned int arg_reloc;
+  unsigned int symbol_info;
+  unsigned int symbol_value;
+};
+
 /* Forward declarations */
 
 static boolean som_mkobject PARAMS ((bfd *));
@@ -199,7 +215,15 @@ static boolean som_bfd_fill_in_ar_symbols PARAMS ((bfd *, struct lst_header *,
 static boolean som_slurp_armap PARAMS ((bfd *));
 static boolean som_write_armap PARAMS ((bfd *));
 static boolean som_slurp_extended_name_table PARAMS ((bfd *));
-
+static void som_bfd_derive_misc_symbol_info PARAMS ((bfd *, asymbol *,
+                                            struct som_misc_symbol_info *));
+static boolean som_bfd_prep_for_ar_write PARAMS ((bfd *, unsigned int *,
+                                                 unsigned int *));
+static unsigned int som_bfd_ar_symbol_hash PARAMS ((asymbol *));
+static boolean som_bfd_ar_write_symbol_stuff PARAMS ((bfd *, unsigned int,
+                                                     unsigned int,
+                                                     struct lst_header));
+       
 /* Map SOM section names to POSIX/BSD single-character symbol types.
 
    This table includes all the standard subspaces as defined in the 
@@ -1659,7 +1683,7 @@ setup_sections (abfd, file_hdr)
 
       /* 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));
+      memset (&save_subspace, 0, 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;
@@ -1829,7 +1853,7 @@ som_object_p (abfd)
   /* 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));
+  memset (&aux_hdr, 0, 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)
@@ -2143,7 +2167,7 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
   /* Get a chunk of memory that we can use as buffer space, then throw
      away.  */
   tmp_space = alloca (SOM_TMP_BUFSIZE);
-  bzero (tmp_space, SOM_TMP_BUFSIZE);
+  memset (tmp_space, 0, SOM_TMP_BUFSIZE);
   p = tmp_space;
 
   /* All the fixups for a particular subspace are emitted in a single
@@ -2432,7 +2456,7 @@ som_write_space_strings (abfd, current_offset, string_sizep)
   /* Get a chunk of memory that we can use as buffer space, then throw
      away.  */
   tmp_space = alloca (SOM_TMP_BUFSIZE);
-  bzero (tmp_space, SOM_TMP_BUFSIZE);
+  memset (tmp_space, 0, SOM_TMP_BUFSIZE);
   p = tmp_space;
 
   /* Seek to the start of the space strings in preparation for writing
@@ -2527,7 +2551,7 @@ som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep)
   /* Get a chunk of memory that we can use as buffer space, then throw
      away.  */
   tmp_space = alloca (SOM_TMP_BUFSIZE);
-  bzero (tmp_space, SOM_TMP_BUFSIZE);
+  memset (tmp_space, 0, SOM_TMP_BUFSIZE);
   p = tmp_space;
 
   /* Seek to the start of the space strings in preparation for writing
@@ -3080,6 +3104,108 @@ som_compute_checksum (abfd)
   return checksum;
 }
 
+static void
+som_bfd_derive_misc_symbol_info (abfd, sym, info)
+     bfd *abfd;
+     asymbol *sym;
+     struct som_misc_symbol_info *info;
+{
+  /* Initialize.  */
+  memset (info, 0, sizeof (struct som_misc_symbol_info));
+
+  /* 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 (sym->flags & BSF_SECTION_SYM)
+    info->symbol_type = ST_DATA;
+  else
+    {
+      /* Common symbols must have scope SS_UNSAT and type
+        ST_STORAGE or the linker will choke.  */
+      if (sym->section == &bfd_com_section)
+       {
+         info->symbol_scope = SS_UNSAT;
+         info->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 (sym)->som_type == SYMBOL_TYPE_UNKNOWN
+              && sym->section == &bfd_und_section
+              && sym->flags & BSF_FUNCTION)
+       info->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 (sym)->som_type == SYMBOL_TYPE_ENTRY
+              || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
+                  && (sym->flags & BSF_FUNCTION))
+              || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
+                  && (sym->flags & BSF_FUNCTION)))
+       {
+         info->symbol_type = ST_ENTRY;
+         info->arg_reloc = som_symbol_data (sym)->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 (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
+       info->symbol_type = ST_DATA;
+
+      /* From now on it's a very simple mapping.  */
+      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
+       info->symbol_type = ST_ABSOLUTE;
+      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
+       info->symbol_type = ST_CODE;
+      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
+       info->symbol_type = ST_DATA;
+      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
+       info->symbol_type = ST_MILLICODE;
+      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
+       info->symbol_type = ST_PLABEL;
+      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
+       info->symbol_type = ST_PRI_PROG;
+      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
+       info->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 (sym->flags & BSF_EXPORT && sym->section != &bfd_com_section)
+    info->symbol_scope = SS_UNIVERSAL;
+  /* Any undefined symbol at this point has a scope SS_UNSAT.  */
+  else if (sym->section == &bfd_und_section)
+    info->symbol_scope = SS_UNSAT;
+  /* Anything else which is not in the common section has scope
+     SS_LOCAL.  */
+  else if (sym->section != &bfd_com_section)
+    info->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 (sym->section == &bfd_com_section || sym->section == &bfd_und_section)
+    info->symbol_info = 0;
+  /* For all other symbols, the symbol_info field contains the 
+     subspace index of the space this symbol is contained in.  */
+  else
+    info->symbol_info = som_section_data (sym->section)->subspace_index;
+
+  /* Set the symbol's value.  */
+  info->symbol_value = sym->value + sym->section->vma;
+}
+
 /* Build and write, in one big chunk, the entire symbol table for
    this BFD.  */
 
@@ -3097,127 +3223,30 @@ som_build_and_write_symbol_table (abfd)
      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);
+  memset (som_symtab, 0, symtab_size);
 
   /* Walk over each symbol.  */
   for (i = 0; i < num_syms; i++)
     {
+      struct som_misc_symbol_info info;
+
       /* 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;
+      /* Derive SOM information from the BFD symbol.  */
+      som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
 
-      /* Set the symbol's value.  */
-      som_symtab[i].symbol_value
-       = bfd_syms[i]->value + bfd_syms[i]->section->vma;
+      /* Now use it.  */
+      som_symtab[i].symbol_type = info.symbol_type;
+      som_symtab[i].symbol_scope = info.symbol_scope;
+      som_symtab[i].arg_reloc = info.arg_reloc;
+      som_symtab[i].symbol_info = info.symbol_info;
+      som_symtab[i].symbol_value = info.symbol_value;
     }
 
-  /* Egad.  Everything is ready, seek to the right location and
+  /* Everything is ready, seek to the right location and
      scribble out the symbol table.  */
   if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
     {
@@ -3396,6 +3425,29 @@ som_slurp_symbol_table (abfd)
          || bufp->symbol_type == ST_ARG_EXT)
        continue;
 
+      /* Set some private data we care about.  */
+      if (bufp->symbol_type == ST_NULL)
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
+      else if (bufp->symbol_type == ST_ABSOLUTE)
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
+      else if (bufp->symbol_type == ST_DATA)
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
+      else if (bufp->symbol_type == ST_CODE)
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
+      else if (bufp->symbol_type == ST_PRI_PROG)
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
+      else if (bufp->symbol_type == ST_SEC_PROG)
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
+      else if (bufp->symbol_type == ST_ENTRY)
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
+      else if (bufp->symbol_type == ST_MILLICODE)
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
+      else if (bufp->symbol_type == ST_PLABEL)
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
+      else
+       som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
+      som_symbol_data (sym)->tc_data.hppa_arg_reloc = bufp->arg_reloc;
+
       /* Some reasonable defaults.  */
       sym->symbol.the_bfd = abfd;
       sym->symbol.name = bufp->name.n_strx + stringtab;
@@ -3584,8 +3636,8 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
 #define        emptystack()    (sp == stack)
 
   som_initialize_reloc_queue (reloc_queue);
-  bzero (variables, sizeof (variables));
-  bzero (stack, sizeof (stack));
+  memset (variables, 0, sizeof (variables));
+  memset (stack, 0, sizeof (stack));
   count = 0;
   prev_fixup = 0;
   sp = stack;
@@ -3767,8 +3819,8 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
          count++;
          /* Now that we've handled a "full" relocation, reset
             some state.  */
-         bzero (variables, sizeof (variables));
-         bzero (stack, sizeof (stack));
+         memset (variables, 0, sizeof (variables));
+         memset (stack, 0, sizeof (stack));
        }
     }
   return count;
@@ -4545,12 +4597,411 @@ som_slurp_armap (abfd)
   return true;
 }
 
-/* Write out the LST for the archive.  Not supported yet.  */
+/* Begin preparing to write a SOM library symbol table.
+
+   As part of the prep work we need to determine the number of symbols
+   and the size of the associated string section.  */
+
+static boolean
+som_bfd_prep_for_ar_write (abfd, num_syms, stringsize)
+     bfd *abfd;
+     unsigned int *num_syms, *stringsize;
+{
+  bfd *curr_bfd = abfd->archive_head;
+
+  /* Some initialization.  */
+  *num_syms = 0;
+  *stringsize = 0;
+
+  /* Iterate over each BFD within this archive.  */
+  while (curr_bfd != NULL)
+    {
+      unsigned int curr_count, i;
+      asymbol *sym;
+
+      /* Make sure the symbol table has been read, then snag a pointer
+        to it.  It's a little slimey to grab the symbols via obj_som_symtab,
+        but doing so avoids allocating lots of extra memory.  */
+      if (som_slurp_symbol_table (curr_bfd) == false)
+       return false;
+
+      sym = (asymbol *)obj_som_symtab (curr_bfd);
+      curr_count = bfd_get_symcount (curr_bfd);
+
+      /* Examine each symbol to determine if it belongs in the
+        library symbol table.  */
+      for (i = 0; i < curr_count; i++, sym++)
+       {
+         struct som_misc_symbol_info info;
+
+         /* Derive SOM information from the BFD symbol.  */
+         som_bfd_derive_misc_symbol_info (curr_bfd, sym, &info);
+
+         /* Should we include this symbol?  */
+         if (info.symbol_type == ST_NULL
+             || info.symbol_type == ST_SYM_EXT
+             || info.symbol_type == ST_ARG_EXT)
+           continue;
+
+         /* Only global symbols and unsatisfied commons.  */
+         if (info.symbol_scope != SS_UNIVERSAL
+             && info.symbol_type != ST_STORAGE)
+           continue;
+
+         /* Do no include undefined symbols.  */
+         if (sym->section == &bfd_und_section)
+           continue;
+
+         /* Bump the various counters, being careful to honor
+            alignment considerations in the string table.  */
+         (*num_syms)++;
+         *stringsize = *stringsize + strlen (sym->name) + 5;
+         while (*stringsize % 4)
+           (*stringsize)++;
+       }
+
+      curr_bfd = curr_bfd->next;
+    }
+  return true;
+}
+
+/* Hash a symbol name based on the hashing algorithm presented in the
+   SOM ABI.  */
+static unsigned int
+som_bfd_ar_symbol_hash (symbol)
+     asymbol *symbol;
+{
+  unsigned int len = strlen (symbol->name);
+
+  /* Names with length 1 are special.  */
+  if (len == 1)
+    return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
+
+  return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
+         | (symbol->name[len-2] << 8) | symbol->name[len-1];
+}
+
+/* Do the bulk of the work required to write the SOM library
+   symbol table.  */
+   
+static boolean
+som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
+     bfd *abfd;
+     unsigned int nsyms, string_size;
+     struct lst_header lst;
+{
+  file_ptr lst_filepos;
+  char *strings, *p;
+  struct lst_symbol_record *lst_syms, *curr_lst_sym;
+  bfd *curr_bfd = abfd->archive_head;
+  unsigned int hash_table[lst.hash_size];
+  struct som_entry som_dict[lst.module_count];
+  struct lst_symbol_record *last_hash_entry[lst.hash_size];
+  unsigned int curr_som_offset, som_index;
+
+  /* Lots of fields are file positions relative to the start
+     of the lst record.  So save its location.  */
+  lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
+
+  /* Some initialization.  */
+  memset (hash_table, 0, 4 * lst.hash_size);
+  memset (som_dict, 0, lst.module_count * sizeof (struct som_entry));
+  memset (last_hash_entry, 0,  
+         lst.hash_size * sizeof (struct lst_symbol_record *));
+
+  /* Symbols have som_index fields, so we have to keep track of the
+     index of each SOM in the archive.
+
+     The SOM dictionary has (among other things) the absolute file
+     position for the SOM which a particular dictionary entry
+     describes.  We have to compute that information as we iterate
+     through the SOMs/symbols.  */
+  som_index = 0;
+  curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
+
+  /* FIXME should be done with buffers just like everything else... */
+  lst_syms = alloca (nsyms * sizeof (struct lst_symbol_record));
+  strings = alloca (string_size);
+  p = strings;
+  curr_lst_sym = lst_syms;
+
+
+  while (curr_bfd != NULL)
+    {
+      unsigned int curr_count, i;
+      asymbol *sym;
+
+      /* Make sure the symbol table has been read, then snag a pointer
+        to it.  It's a little slimey to grab the symbols via obj_som_symtab,
+        but doing so avoids allocating lots of extra memory.  */
+      if (som_slurp_symbol_table (curr_bfd) == false)
+       return false;
+
+      sym = (asymbol *)obj_som_symtab (curr_bfd);
+      curr_count = bfd_get_symcount (curr_bfd);
+
+      for (i = 0; i < curr_count; i++, sym++)
+       {
+         struct som_misc_symbol_info info;
+
+         /* Derive SOM information from the BFD symbol.  */
+         som_bfd_derive_misc_symbol_info (curr_bfd, sym, &info);
+
+         /* Should we include this symbol?  */
+         if (info.symbol_type == ST_NULL
+             || info.symbol_type == ST_SYM_EXT
+             || info.symbol_type == ST_ARG_EXT)
+           continue;
+
+         /* Only global symbols and unsatisfied commons.  */
+         if (info.symbol_scope != SS_UNIVERSAL
+             && info.symbol_type != ST_STORAGE)
+           continue;
+
+         /* Do no include undefined symbols.  */
+         if (sym->section == &bfd_und_section)
+           continue;
+
+         /* If this is the first symbol from this SOM, then update
+            the SOM dictionary too.  */
+         if (som_dict[som_index].location == 0)
+           {
+             som_dict[som_index].location = curr_som_offset;
+             som_dict[som_index].length = arelt_size (curr_bfd);
+           }
+
+         /* Fill in the lst symbol record.  */
+         curr_lst_sym->hidden = 0;
+         curr_lst_sym->secondary_def = 0;
+         curr_lst_sym->symbol_type = info.symbol_type;
+         curr_lst_sym->symbol_scope = info.symbol_scope;
+         curr_lst_sym->check_level = 0;
+         curr_lst_sym->must_qualify = 0;
+         curr_lst_sym->initially_frozen = 0;
+         curr_lst_sym->memory_resident = 0;
+         curr_lst_sym->is_common = (sym->section == &bfd_com_section);
+         curr_lst_sym->dup_common = 0;
+         curr_lst_sym->xleast = 0;
+         curr_lst_sym->arg_reloc = info.arg_reloc;
+         curr_lst_sym->name.n_strx = p - strings + 4;
+         curr_lst_sym->qualifier_name.n_strx = 0;
+         curr_lst_sym->symbol_info = info.symbol_info;
+         curr_lst_sym->symbol_value = info.symbol_value;
+         curr_lst_sym->symbol_descriptor = 0;
+         curr_lst_sym->reserved = 0;
+         curr_lst_sym->som_index = som_index;
+         curr_lst_sym->symbol_key = som_bfd_ar_symbol_hash (sym);
+         curr_lst_sym->next_entry = 0;
+
+         /* Insert into the hash table.  */
+         if (hash_table[curr_lst_sym->symbol_key % lst.hash_size])
+           {
+             struct lst_symbol_record *tmp;
+
+             /* There is already something at the head of this hash chain,
+                so tack this symbol onto the end of the chain.  */
+             tmp = last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size];
+             tmp->next_entry
+               = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
+                 + lst.hash_size * 4 
+                 + lst.module_count * sizeof (struct som_entry)
+                 + sizeof (struct lst_header);
+           }
+         else
+           {
+             /* First entry in this hash chain.  */
+             hash_table[curr_lst_sym->symbol_key % lst.hash_size]
+               = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
+                 + lst.hash_size * 4 
+                 + lst.module_count * sizeof (struct som_entry)
+                 + sizeof (struct lst_header);
+           }
+
+         /* Keep track of the last symbol we added to this chain so we can
+            easily update its next_entry pointer.  */
+         last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size]
+           = curr_lst_sym;
+
+
+         /* Update the string table.  */
+         bfd_put_32 (abfd, strlen (sym->name), p);
+         p += 4;
+         strcpy (p, sym->name);
+         p += strlen (sym->name) + 1;
+         while ((int)p % 4)
+           {
+             bfd_put_8 (abfd, 0, p);
+             p++;
+           }
+
+         /* Head to the next symbol.  */
+         curr_lst_sym++;
+       }
+
+      /* 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);
+      curr_bfd = curr_bfd->next;
+      som_index++;
+    }
+
+  /* Now scribble out the hash table.  */
+  if (bfd_write ((PTR) hash_table, lst.hash_size, 4, abfd)
+      != lst.hash_size * 4)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* Then the SOM dictionary.  */
+  if (bfd_write ((PTR) som_dict, lst.module_count,
+                sizeof (struct som_entry), abfd)
+      != lst.module_count * sizeof (struct som_entry))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* The library symbols.  */
+  if (bfd_write ((PTR) lst_syms, nsyms, sizeof (struct lst_symbol_record), abfd)
+      != nsyms * sizeof (struct lst_symbol_record))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* And finally the strings.  */
+  if (bfd_write ((PTR) strings, string_size, 1, abfd) != string_size)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  return true;
+}
+
+/* Write out the LST for the archive.
+
+   You'll never believe this is really how armaps are handled in SOM...  */
+
 static boolean
 som_write_armap (abfd)
      bfd *abfd;
 {
-  return false;
+  bfd *curr_bfd;
+  struct stat statbuf;
+  unsigned int i, lst_size, nsyms, stringsize;
+  struct ar_hdr hdr;
+  struct lst_header lst;
+  int *p;
+  /* We'll use this for the archive's date and mode later.  */
+  if (stat (abfd->filename, &statbuf) != 0)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+  /* Fudge factor.  */
+  bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
+
+  /* Account for the lst header first.  */
+  lst_size = sizeof (struct lst_header);
+
+  /* Start building the LST header.  */
+  lst.system_id = HP9000S800_ID;
+  lst.a_magic = LIBMAGIC;
+  lst.version_id = VERSION_ID;
+  lst.file_time.secs = 0;
+  lst.file_time.nanosecs = 0;
+
+  lst.hash_loc = lst_size;
+  lst.hash_size = SOM_LST_HASH_SIZE;
+
+  /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
+  lst_size += 4 * SOM_LST_HASH_SIZE;
+
+  /* We need to count the number of SOMs in this archive.  */
+  curr_bfd = abfd->archive_head;
+  lst.module_count = 0;
+  while (curr_bfd != NULL)
+    {
+      lst.module_count++;
+      curr_bfd = curr_bfd->next;
+    }
+  lst.module_limit = lst.module_count;
+  lst.dir_loc = lst_size;
+  lst_size += sizeof (struct som_entry) * lst.module_count;
+
+  /* We don't support import/export tables, auxiliary headers,
+     or free lists yet.  Make the linker work a little harder
+     to make our life easier.  */
+
+  lst.export_loc = 0;
+  lst.export_count = 0;
+  lst.import_loc = 0;
+  lst.aux_loc = 0;
+  lst.aux_size = 0;
+
+  /* Count how many symbols we will have on the hash chains and the
+     size of the associated string table.  */
+  if (som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize) == false)
+    return false;
+
+  lst_size += sizeof (struct lst_symbol_record) * nsyms;
+
+  /* For the string table.  One day we might actually use this info
+     to avoid small seeks/reads when reading archives.  */
+  lst.string_loc = lst_size;
+  lst.string_size = stringsize;
+  lst_size += stringsize;
+
+  /* SOM ABI says this must be zero.  */
+  lst.free_list = 0;
+
+  lst.file_end = lst_size;
+
+  /* Compute the checksum.  Must happen after the entire lst header
+     has filled in.  */
+  p = (int *)&lst;
+  for (i = 0; i < sizeof (struct lst_header)/sizeof (int) - 1; i++)
+    lst.checksum ^= *p++;
+
+  sprintf (hdr.ar_name, "/               ");
+  sprintf (hdr.ar_date, "%ld", bfd_ardata (abfd)->armap_timestamp);
+  sprintf (hdr.ar_uid, "%d", getuid ());
+  sprintf (hdr.ar_gid, "%d", getgid ());
+  sprintf (hdr.ar_mode, "%-8o", (unsigned int) statbuf.st_mode);
+  sprintf (hdr.ar_size, "%-10d", (int) lst_size);
+  hdr.ar_fmag[0] = '`';
+  hdr.ar_fmag[1] = '\012';
+
+  /* Turn any nulls into spaces.  */
+  for (i = 0; i < sizeof (struct ar_hdr); i++)
+    if (((char *) (&hdr))[i] == '\0')
+      (((char *) (&hdr))[i]) = ' ';
+
+  /* Scribble out the ar header.  */
+  if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
+      != sizeof (struct ar_hdr))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* Now scribble out the lst header.  */
+  if (bfd_write ((PTR) &lst, 1, sizeof (struct lst_header), abfd)
+      != sizeof (struct lst_header))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* Build and write the armap.  */
+  if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst) == false)
+    return false;
+  
+  /* Done.  */
+  return true;
 }
 
 /* Apparently the extened names are never used, even though they appear
@@ -4606,7 +5057,7 @@ bfd_target som_vec =
 /* leading_symbol_char: is the first char of a user symbol
    predictable, and if so what is it */
   0,
-  ' ',                         /* ar_pad_char */
+  '/',                         /* ar_pad_char */
   16,                          /* ar_max_namelen */
   3,                           /* minimum alignment */
   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
This page took 0.040911 seconds and 4 git commands to generate.