* som.h (som_symbol_data): Safely access backend private data
[deliverable/binutils-gdb.git] / bfd / som.c
index eef9c73bc2320a48f56b695622ce2c9288a714d6..24d2a747304b98e7b96db31aa66f0f4839bade48 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -191,7 +191,14 @@ static const reloc_howto_type * som_bfd_reloc_type_lookup
        PARAMS ((bfd_arch_info_type *, bfd_reloc_code_real_type));
 static char som_section_type PARAMS ((const char *));
 static int som_decode_symclass PARAMS ((asymbol *));
+static boolean som_bfd_count_ar_symbols PARAMS ((bfd *, struct lst_header *,
+                                                symindex *));
 
+static boolean som_bfd_fill_in_ar_symbols PARAMS ((bfd *, struct lst_header *,
+                                                  carsym **syms));
+static boolean som_slurp_armap PARAMS ((bfd *));
+static boolean som_write_armap PARAMS ((bfd *));
+static boolean som_slurp_extended_name_table PARAMS ((bfd *));
 
 /* Map SOM section names to POSIX/BSD single-character symbol types.
 
@@ -1021,16 +1028,16 @@ som_reloc_queue_find (p, size, queue)
      unsigned int size;
      struct reloc_queue *queue;
 {
-  if (!bcmp (p, queue[0].reloc, size)
+  if (queue[0].reloc && !bcmp (p, queue[0].reloc, size)
       && size == queue[0].size)
     return 0;
-  if (!bcmp (p, queue[1].reloc, size)
+  if (queue[1].reloc && !bcmp (p, queue[1].reloc, size)
       && size == queue[1].size)
     return 1;
-  if (!bcmp (p, queue[2].reloc, size)
+  if (queue[2].reloc && !bcmp (p, queue[2].reloc, size)
       && size == queue[2].size)
     return 2;
-  if (!bcmp (p, queue[3].reloc, size)
+  if (queue[3].reloc && !bcmp (p, queue[3].reloc, size)
       && size == queue[3].size)
     return 3;
   return -1;
@@ -1347,6 +1354,11 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
 
   final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 3);
   final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+  if (!final_types || !final_type)
+    {
+      bfd_error = no_memory;
+      return NULL;
+    }
 
   /* The field selector may require additional relocations to be 
      generated.  It's impossible to know at this moment if additional
@@ -1369,6 +1381,11 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_ltsel:
       case e_rtsel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       if (!final_types[0])
+         {
+           bfd_error = no_memory;
+           return NULL;
+         }
        if (field == e_tsel)
          *final_types[0] = R_FSEL;
        else if (field == e_ltsel)
@@ -1383,6 +1400,11 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_lssel:
       case e_rssel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       if (!final_types[0])
+         {
+           bfd_error = no_memory;
+           return NULL;
+         }
        *final_types[0] = R_S_MODE;
        final_types[1] = final_type;
        final_types[2] = NULL;
@@ -1392,6 +1414,11 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_lsel:
       case e_rsel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       if (!final_types[0])
+         {
+           bfd_error = no_memory;
+           return NULL;
+         }
        *final_types[0] = R_N_MODE;
        final_types[1] = final_type;
        final_types[2] = NULL;
@@ -1401,6 +1428,11 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_ldsel:
       case e_rdsel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       if (!final_types[0])
+         {
+           bfd_error = no_memory;
+           return NULL;
+         }
        *final_types[0] = R_D_MODE;
        final_types[1] = final_type;
        final_types[2] = NULL;
@@ -1410,6 +1442,11 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
       case e_lrsel:
       case e_rrsel:
        final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+       if (!final_types[0])
+         {
+           bfd_error = no_memory;
+           return NULL;
+         }
        *final_types[0] = R_R_MODE;
        final_types[1] = final_type;
        final_types[2] = NULL;
@@ -1541,6 +1578,11 @@ make_unique_section (abfd, name, num)
     }
 
   newname = bfd_alloc (abfd, strlen (sect->name) + 1);
+  if (!newname)
+    {
+      bfd_error = no_memory;
+      return NULL;
+    }
   strcpy (newname, sect->name);
 
   sect->name = newname;
@@ -1822,7 +1864,8 @@ som_mkobject (abfd)
       bfd_error = no_memory;
       return false;
     }
-  obj_som_file_hdr (abfd) = bfd_zalloc (abfd, sizeof (struct header));
+  obj_som_file_hdr (abfd)
+    = (struct header *) bfd_zalloc (abfd, sizeof (struct header));
   if (obj_som_file_hdr (abfd) == NULL)
 
     {
@@ -1973,12 +2016,12 @@ compare_syms (sym1, sym2)
   if ((*sym1)->flags & BSF_SECTION_SYM)
     count1 = (int)(*sym1)->udata;
   else
-    count1 = (*som_symbol_data ((*sym1)))->reloc_count;
+    count1 = som_symbol_data (*sym1)->reloc_count;
 
   if ((*sym2)->flags & BSF_SECTION_SYM)
     count2 = (int)(*sym2)->udata;
   else
-    count2 = (*som_symbol_data ((*sym2)))->reloc_count;
+    count2 = som_symbol_data (*sym2)->reloc_count;
 
   /* Return the appropriate value.  */
   if (count1 < count2)
@@ -2020,7 +2063,7 @@ som_prep_for_fixups (abfd, syms, num_syms)
          syms[i]->udata = (PTR) 0;
        }
       else
-       (*som_symbol_data (syms[i]))->reloc_count = 0;
+       som_symbol_data (syms[i])->reloc_count = 0;
     }
 
   /* Now that the counters are initialized, make a weighted count
@@ -2064,7 +2107,7 @@ som_prep_for_fixups (abfd, syms, num_syms)
            }
 
          /* A normal symbol.  Increment the count.  */
-         (*som_symbol_data ((*reloc->sym_ptr_ptr)))->reloc_count += scale;
+         som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale;
        }
     }
 
@@ -2080,7 +2123,7 @@ som_prep_for_fixups (abfd, syms, num_syms)
       if (syms[i]->flags & BSF_SECTION_SYM)
        syms[i]->udata = (PTR) i;
       else
-        (*som_symbol_data (syms[i]))->index = i;
+        som_symbol_data (syms[i])->index = i;
     }
 }
 
@@ -2175,7 +2218,7 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
              if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
                sym_num = (int) (*bfd_reloc->sym_ptr_ptr)->udata;
              else
-               sym_num = (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->index;
+               sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index;
              
              /* If there is not enough room for the next couple relocations,
                 then dump the current buffer contents now.  Also reinitialize
@@ -2300,7 +2343,7 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
                case R_ENTRY:
                  {
                    int *descp
-                      = (int *) (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->unwind;
+                      = (int *) som_symbol_data (*bfd_reloc->sym_ptr_ptr)->unwind;
                    bfd_put_8 (abfd, R_ENTRY, p);
                    bfd_put_32 (abfd, descp[0], p + 1);
                    bfd_put_32 (abfd, descp[1], p + 5);
@@ -3089,7 +3132,7 @@ som_build_and_write_symbol_table (abfd)
             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
+         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))
@@ -3098,46 +3141,46 @@ som_build_and_write_symbol_table (abfd)
          /* 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
+         else if ((som_symbol_data (bfd_syms[i])->som_type
                    == SYMBOL_TYPE_ENTRY)
-                  || (((*som_symbol_data (bfd_syms[i]))->som_type
+                  || ((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
+                  || ((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;
+               = 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
+         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
+         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
+         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
+         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
+         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
+         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
+         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
+         else if (som_symbol_data (bfd_syms[i])->som_type
                   == SYMBOL_TYPE_SEC_PROG)
            som_symtab[i].symbol_type = ST_SEC_PROG;
        }
@@ -3878,8 +3921,13 @@ 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->used_by_bfd =
+    (PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
+  if (!newsect->used_by_bfd)
+    {
+      bfd_error = no_memory;
+      return false;
+    }
   newsect->alignment_power = 3;
 
   /* Initialize the subspace_index field to -1 so that it does
@@ -3943,7 +3991,7 @@ bfd_som_set_symbol_type (symbol, type)
      asymbol *symbol;
      unsigned int type;
 {
-  (*som_symbol_data (symbol))->som_type = type;
+  som_symbol_data (symbol)->som_type = type;
 }
 
 /* Attach 64bits of unwind information to a symbol (which hopefully
@@ -3955,7 +4003,7 @@ bfd_som_attach_unwind_info (symbol, unwind_desc)
      asymbol *symbol;
      char *unwind_desc;
 {
-  (*som_symbol_data (symbol))->unwind = unwind_desc;
+  som_symbol_data (symbol)->unwind = unwind_desc;
 }
 
 /* Attach an auxiliary header to the BFD backend so that it may be
@@ -3973,9 +4021,14 @@ bfd_som_attach_aux_hdr (abfd, type, string)
 
       if (len % 4)
        pad = (4 - (len % 4));
-      obj_som_version_hdr (abfd)
-       bfd_zalloc (abfd, sizeof (struct aux_id)
+      obj_som_version_hdr (abfd) = (struct user_string_aux_hdr *)
+       bfd_zalloc (abfd, sizeof (struct aux_id)
                              + sizeof (unsigned int) + len + pad);
+      if (!obj_som_version_hdr (abfd))
+       {
+         bfd_error = no_memory;
+         abort();              /* FIXME */
+       }
       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);
@@ -3989,9 +4042,14 @@ bfd_som_attach_aux_hdr (abfd, type, string)
 
       if (len % 4)
        pad = (4 - (len % 4));
-      obj_som_copyright_hdr (abfd)
-       = bfd_zalloc (abfd, sizeof (struct aux_id)
-                             + sizeof (unsigned int) + len + pad);
+      obj_som_copyright_hdr (abfd) = (struct copyright_aux_hdr *)
+       bfd_zalloc (abfd, sizeof (struct aux_id)
+                           + sizeof (unsigned int) + len + pad);
+      if (!obj_som_copyright_hdr (abfd))
+       {
+         bfd_error = no_error;
+         abort();              /* FIXME */
+       }
       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);
@@ -4139,18 +4197,381 @@ som_get_symbol_info (ignore_abfd, symbol, ret)
   ret->name = symbol->name;
 }
 
+/* Count the number of symbols in the archive symbol table.  Necessary
+   so that we can allocate space for all the carsyms at once.  */
+
+static boolean
+som_bfd_count_ar_symbols (abfd, lst_header, count)
+     bfd *abfd;
+     struct lst_header *lst_header;
+     symindex *count;
+{
+  unsigned int i;
+  unsigned int hash_table[lst_header->hash_size];
+  file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
+
+  /* Don't forget to initialize the counter!  */
+  *count = 0;
+
+  /* Read in the hash table.  The has table is an array of 32bit file offsets
+     which point to the hash chains.  */
+  if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
+      != lst_header->hash_size * 4)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* Walk each chain counting the number of symbols found on that particular
+     chain.  */
+  for (i = 0; i < lst_header->hash_size; i++)
+    {
+      struct lst_symbol_record lst_symbol;
+
+      /* An empty chain has zero as it's file offset.  */
+      if (hash_table[i] == 0)
+       continue;
+
+      /* Seek to the first symbol in this hash chain.  */
+      if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
+       {
+         bfd_error = system_call_error;
+         return false;
+       }
+
+      /* Read in this symbol and update the counter.  */
+      if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+         != sizeof (lst_symbol))
+       {
+         bfd_error = system_call_error;
+         return false;
+       }
+      (*count)++;
+
+      /* Now iterate through the rest of the symbols on this chain.  */
+      while (lst_symbol.next_entry)
+       {
+
+         /* Seek to the next symbol.  */
+         if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
+             < 0)
+           {
+             bfd_error = system_call_error;
+             return false;
+           }
+
+         /* Read the symbol in and update the counter.  */
+         if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+             != sizeof (lst_symbol))
+           {
+             bfd_error = system_call_error;
+             return false;
+           }
+         (*count)++;
+       }
+    }
+  return true;
+}
+
+/* Fill in the canonical archive symbols (SYMS) from the archive described
+   by ABFD and LST_HEADER.  */
+
+static boolean
+som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
+     bfd *abfd;
+     struct lst_header *lst_header;
+     carsym **syms;
+{
+  unsigned int i, len;
+  carsym *set = syms[0];
+  unsigned int hash_table[lst_header->hash_size];
+  struct som_entry som_dict[lst_header->module_count];
+  file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
+
+  /* Read in the hash table.  The has table is an array of 32bit file offsets
+     which point to the hash chains.  */
+  if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
+      != lst_header->hash_size * 4)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* Seek to and read in the SOM dictionary.  We will need this to fill
+     in the carsym's filepos field.  */
+  if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) < 0)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  if (bfd_read ((PTR) som_dict, lst_header->module_count, 
+               sizeof (struct som_entry), abfd)
+      != lst_header->module_count * sizeof (struct som_entry))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* Walk each chain filling in the carsyms as we go along.  */
+  for (i = 0; i < lst_header->hash_size; i++)
+    {
+      struct lst_symbol_record lst_symbol;
+
+      /* An empty chain has zero as it's file offset.  */
+      if (hash_table[i] == 0)
+       continue;
+
+      /* Seek to and read the first symbol on the chain.  */
+      if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
+       {
+         bfd_error = system_call_error;
+         return false;
+       }
+
+      if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+         != sizeof (lst_symbol))
+       {
+         bfd_error = system_call_error;
+         return false;
+       }
+
+      /* Get the name of the symbol, first get the length which is stored
+        as a 32bit integer just before the symbol.
+
+        One might ask why we don't just read in the entire string table
+        and index into it.  Well, according to the SOM ABI the string
+        index can point *anywhere* in the archive to save space, so just
+        using the string table would not be safe.  */
+      if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
+                           + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
+       {
+         bfd_error = system_call_error;
+         return false;
+       }
+
+      if (bfd_read (&len, 1, 4, abfd) != 4)
+       {
+         bfd_error = system_call_error;
+         return false;
+       }
+
+      /* Allocate space for the name and null terminate it too.  */
+      set->name = bfd_zalloc (abfd, len + 1);
+      if (!set->name)
+       {
+         bfd_error = no_memory;
+         return false;
+       }
+      if (bfd_read (set->name, 1, len, abfd) != len)
+       {
+         bfd_error = system_call_error;
+         return false;
+       }
+      set->name[len] = 0;
+
+      /* Fill in the file offset.  Note that the "location" field points
+        to the SOM itself, not the ar_hdr in front of it.  */
+      set->file_offset = som_dict[lst_symbol.som_index].location
+                         - sizeof (struct ar_hdr);
+
+      /* Go to the next symbol.  */
+      set++;
+
+      /* Iterate through the rest of the chain.  */
+      while (lst_symbol.next_entry)
+       {
+         /* Seek to the next symbol and read it in.  */
+         if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
+             < 0)
+           {
+             bfd_error = system_call_error;
+             return false;
+           }
+
+         if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+             != sizeof (lst_symbol))
+           {
+             bfd_error = system_call_error;
+             return false;
+           }
+
+         /* Seek to the name length & string and read them in.  */
+         if (bfd_seek (abfd, lst_filepos + lst_header->string_loc 
+                               + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
+           {
+             bfd_error = system_call_error;
+             return false;
+           }
+
+         if (bfd_read (&len, 1, 4, abfd) != 4)
+           {
+             bfd_error = system_call_error;
+             return false;
+           }
+
+         /* Allocate space for the name and null terminate it too.  */
+         set->name = bfd_zalloc (abfd, len + 1);
+         if (!set->name)
+           {
+             bfd_error = no_memory;
+             return false;
+           }
+         if (bfd_read (set->name, 1, len, abfd) != len)
+           {
+             bfd_error = system_call_error;
+             return false;
+           }
+         set->name[len] = 0;
+
+         /* Fill in the file offset.  Note that the "location" field points
+            to the SOM itself, not the ar_hdr in front of it.  */
+         set->file_offset = som_dict[lst_symbol.som_index].location
+                              - sizeof (struct ar_hdr);
+
+         /* Go on to the next symbol.  */
+         set++;
+       }
+    }
+  /* If we haven't died by now, then we successfully read the entire 
+     archive symbol table.  */
+  return true;
+}
+
+/* Read in the LST from the archive.  */
+static boolean
+som_slurp_armap (abfd)
+     bfd *abfd;
+{
+  struct lst_header lst_header;
+  struct ar_hdr ar_header;
+  unsigned int parsed_size;
+  struct artdata *ardata = bfd_ardata (abfd);
+  char nextname[17];
+  int i = bfd_read ((PTR) nextname, 1, 16, abfd);
+
+  /* Special cases.  */
+  if (i == 0)
+    return true;
+  if (i != 16)
+    return false;
+
+  if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) < 0)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* For archives without .o files there is no symbol table.  */
+  if (strncmp (nextname, "/               ", 16))
+    {
+      bfd_has_map (abfd) = false;
+      return true;
+    }
+
+  /* Read in and sanity check the archive header.  */
+  if (bfd_read ((PTR) &ar_header, 1, sizeof (struct ar_hdr), abfd)
+      != sizeof (struct ar_hdr))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
+    {
+      bfd_error = malformed_archive;
+      return NULL;
+    }
+
+  /* How big is the archive symbol table entry?  */
+  errno = 0;
+  parsed_size = strtol (ar_header.ar_size, NULL, 10);
+  if (errno != 0)
+    {
+      bfd_error = malformed_archive;
+      return NULL;
+    }
+
+  /* Save off the file offset of the first real user data.  */
+  ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
+
+  /* Read in the library symbol table.  We'll make heavy use of this
+     in just a minute.  */
+  if (bfd_read ((PTR) & lst_header, 1, sizeof (struct lst_header), abfd)
+      != sizeof (struct lst_header))
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* Sanity check.  */
+  if (lst_header.a_magic != LIBMAGIC)
+    {
+      bfd_error = malformed_archive;
+      return NULL;
+    }
+
+  /* Count the number of symbols in the library symbol table.  */
+  if (som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count)
+      == false)
+    return false;
+
+  /* Get back to the start of the library symbol table.  */
+  if (bfd_seek (abfd, ardata->first_file_filepos - parsed_size 
+                       + sizeof (struct lst_header), SEEK_SET) < 0)
+    {
+      bfd_error = system_call_error;
+      return false;
+    }
+
+  /* Initializae the cache and allocate space for the library symbols.  */
+  ardata->cache = 0;
+  ardata->symdefs = (carsym *) bfd_alloc (abfd,
+                                         (ardata->symdef_count
+                                          * sizeof (carsym)));
+  if (!ardata->symdefs)
+    {
+      bfd_error = no_memory;
+      return false;
+    }
+
+  /* Now fill in the canonical archive symbols.  */
+  if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
+      == false)
+    return false;
+
+  /* Notify the generic archive code that we have a symbol map.  */
+  bfd_has_map (abfd) = true;
+  return true;
+}
+
+/* Write out the LST for the archive.  Not supported yet.  */
+static boolean
+som_write_armap (abfd)
+     bfd *abfd;
+{
+  return false;
+}
+
+/* Apparently the extened names are never used, even though they appear
+   in the SOM ABI.  Hmmm.  */
+static boolean
+som_slurp_extended_name_table (abfd)
+     bfd *abfd;
+{
+  bfd_ardata (abfd)->extended_names = NULL;
+  return true;
+}
+
 /* End of miscellaneous support functions. */
 
 #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 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 som_openr_next_archived_file   bfd_generic_openr_next_archived_file
+#define som_generic_stat_arch_elt      bfd_generic_stat_arch_elt
+#define som_truncate_arname            bfd_bsd_truncate_arname
 
 #define som_get_lineno                   (struct lineno_cache_entry *(*)())bfd_nullvoidptr
 #define        som_close_and_cleanup              bfd_generic_close_and_cleanup
This page took 0.031313 seconds and 4 git commands to generate.