* aoutx.h (translate_to_native_sym_flags): Use the output_section
authorIan Lance Taylor <ian@airs.com>
Wed, 24 Aug 1994 15:59:40 +0000 (15:59 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 24 Aug 1994 15:59:40 +0000 (15:59 +0000)
(and output_offset) if there is one.

* aoutx.h (aout_link_check_archive_element): Discard the symbols
if the archive element was not needed.

* aoutx.h (aout_get_external_symbols): Ensure that a zero string
index yields an empty string.
(aout_link_write_symbols): If info->keep_memory is false, use name
from original hash table entry, not from entry in *sym_hash.

* aoutx.h (struct aout_final_link_info): Add fields contents,
relocs, symbol_map and output_syms.
(NAME(aout,final_link)): Work out the largest section size, reloc
size, and number of symbols.  Use them to preallocate buffers that
are large enough for all cases.
(aout_link_input_bfd): Use preallocated symbol_map.
(aout_link_write_symbols): Remove symbol_map argument; use
preallocated symbol_map instead.  Change all callers.  Use
preallocated output_syms.
(aout_link_input_section): Remove symbol_map argument.  Change all
callers.  Use preallocated contents and relocs.
(aout_link_input_section_std): Remove symbol_map argument; use
preallocated symbol_map instead.  Change all callers.
(aout_link_input_section_ext): Likewise.

bfd/ChangeLog
bfd/aoutx.h

index 637ba74c66cd61eecfaa2bc8dcd0d4bbbe351cea..864fe838b676e040d4526a3e3ad1425dce20a01d 100644 (file)
@@ -1,3 +1,37 @@
+Wed Aug 24 11:49:19 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * aoutx.h (translate_to_native_sym_flags): Use the output_section
+       (and output_offset) if there is one.
+
+       * aoutx.h (aout_link_check_archive_element): Discard the symbols
+       if the archive element was not needed.
+
+       * aoutx.h (aout_get_external_symbols): Ensure that a zero string
+       index yields an empty string.
+       (aout_link_write_symbols): If info->keep_memory is false, use name
+       from original hash table entry, not from entry in *sym_hash.
+
+       * aoutx.h (struct aout_final_link_info): Add fields contents,
+       relocs, symbol_map and output_syms.
+       (NAME(aout,final_link)): Work out the largest section size, reloc
+       size, and number of symbols.  Use them to preallocate buffers that
+       are large enough for all cases.
+       (aout_link_input_bfd): Use preallocated symbol_map.
+       (aout_link_write_symbols): Remove symbol_map argument; use
+       preallocated symbol_map instead.  Change all callers.  Use
+       preallocated output_syms.
+       (aout_link_input_section): Remove symbol_map argument.  Change all
+       callers.  Use preallocated contents and relocs.
+       (aout_link_input_section_std): Remove symbol_map argument; use
+       preallocated symbol_map instead.  Change all callers.
+       (aout_link_input_section_ext): Likewise.
+
+Tue Aug 23 10:51:09 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * archive.c (_bfd_write_archive_contents): Don't update the
+       symbol map timestamp if there is no symbol map.  From
+       schwab@issan.informatik.uni-dortmund.de (Andreas Schwab).
+
 Mon Aug 22 12:26:42 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
 
        * targets.c (BFD_JUMP_TABLE_ARCHIVE): Add _update_armap_timestamp.
index 095d3997ee2e71cc16a17b38d3f875ad37bff6db..f62228d884c0d5c570febd7368efdd1a56f30af1 100644 (file)
@@ -1237,6 +1237,9 @@ aout_get_external_symbols (abfd)
          return false;
        }
 
+      /* Ensure that a zero index yields an empty string.  */
+      strings[0] = '\0';
+
       /* Sanity preservation.  */
       strings[stringsize] = '\0';
 
@@ -1553,7 +1556,11 @@ translate_to_native_sym_flags (abfd, cache_ptr, sym_pointer)
     }
 
   /* Turn the symbol from section relative to absolute again */
-  value += cache_ptr->section->vma;
+  if (cache_ptr->section->output_section != NULL)
+    value += (cache_ptr->section->output_section->vma
+             + cache_ptr->section->output_offset);
+  else
+    value += cache_ptr->section->vma;
 
   if ((cache_ptr->flags & BSF_WARNING) != 0)
     sym_pointer->e_type[0] = N_WARNING;
@@ -1739,168 +1746,38 @@ NAME(aout,slurp_symbol_table) (abfd)
    contributing object file tends to have many duplicate stabs
    strings.
 
-   Possible improvements:
-   + look for strings matching trailing substrings of other strings
-   + better data structures?  balanced trees?
-   + look at reducing memory use elsewhere -- maybe if we didn't have
-     to construct the entire symbol table at once, we could get by
-     with smaller amounts of VM?  (What effect does that have on the
-     string table reductions?)
-
    This hash table code breaks dbx on SunOS 4.1.3, so we don't do it
    if BFD_TRADITIONAL_FORMAT is set.  */
 
-/* An entry in the strtab hash table.  */
-
-struct strtab_hash_entry
-{
-  struct bfd_hash_entry root;
-  /* Index in string table.  */
-  bfd_size_type index;
-  /* Next string in strtab.  */
-  struct strtab_hash_entry *next;
-};
-
-/* The strtab hash table.  */
-
-struct strtab_hash
-{
-  struct bfd_hash_table table;
-  /* Size of strtab--also next available index.  */
-  bfd_size_type size;
-  /* First string in strtab.  */
-  struct strtab_hash_entry *first;
-  /* Last string in strtab.  */
-  struct strtab_hash_entry *last;
-};
-
-static struct bfd_hash_entry *strtab_hash_newfunc
-  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static boolean stringtab_init PARAMS ((struct strtab_hash *));
 static bfd_size_type add_to_stringtab
-  PARAMS ((bfd *, struct strtab_hash *, const char *, boolean));
-static boolean emit_stringtab PARAMS ((bfd *, struct strtab_hash *));
-
-/* Routine to create an entry in a strtab.  */
-
-static struct bfd_hash_entry *
-strtab_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
-{
-  struct strtab_hash_entry *ret = (struct strtab_hash_entry *) entry;
-
-  /* Allocate the structure if it has not already been allocated by a
-     subclass.  */
-  if (ret == (struct strtab_hash_entry *) NULL)
-    ret = ((struct strtab_hash_entry *)
-          bfd_hash_allocate (table, sizeof (struct strtab_hash_entry)));
-  if (ret == (struct strtab_hash_entry *) NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
-
-  /* Call the allocation method of the superclass.  */
-  ret = ((struct strtab_hash_entry *)
-        bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
-
-  if (ret)
-    {
-      /* Initialize the local fields.  */
-      ret->index = (bfd_size_type) -1;
-      ret->next = NULL;
-    }
-
-  return (struct bfd_hash_entry *) ret;
-}
-
-/* Look up an entry in an strtab.  */
-
-#define strtab_hash_lookup(t, string, create, copy) \
-  ((struct strtab_hash_entry *) \
-   bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
-
-/* Create a new strtab.  */
-
-static boolean
-stringtab_init (table)
-     struct strtab_hash *table;
-{
-  if (! bfd_hash_table_init (&table->table, strtab_hash_newfunc))
-    return false;
-
-  /* Leave space for the size of the string table.  */
-  table->size = BYTES_IN_WORD;
-
-  table->first = NULL;
-  table->last = NULL;
-
-  return true;
-}
-
-/* Free a strtab.  */
-
-#define stringtab_free(tab) bfd_hash_table_free (&(tab)->table)
+  PARAMS ((bfd *, struct bfd_strtab_hash *, const char *, boolean));
+static boolean emit_stringtab PARAMS ((bfd *, struct bfd_strtab_hash *));
 
 /* Get the index of a string in a strtab, adding it if it is not
-   already present.  If HASH is false, we don't really use the hash
-   table, and we don't eliminate duplicate strings.  */
+   already present.  */
 
 static INLINE bfd_size_type
 add_to_stringtab (abfd, tab, str, copy)
      bfd *abfd;
-     struct strtab_hash *tab;
+     struct bfd_strtab_hash *tab;
      const char *str;
      boolean copy;
 {
-  register struct strtab_hash_entry *entry;
+  boolean hash;
 
   /* An index of 0 always means the empty string.  */
   if (*str == '\0')
     return 0;
 
-  if ((abfd->flags & BFD_TRADITIONAL_FORMAT) == 0)
-    {
-      entry = strtab_hash_lookup (tab, str, true, copy);
-      if (entry == NULL)
-       return (bfd_size_type) -1;
-    }
-  else
-    {
-      entry = ((struct strtab_hash_entry *)
-              bfd_hash_allocate (&tab->table,
-                                 sizeof (struct strtab_hash_entry)));
-      if (entry == NULL)
-       return (bfd_size_type) -1;
-      if (! copy)
-       entry->root.string = str;
-      else
-       {
-         char *n;
-
-         n = (char *) bfd_hash_allocate (&tab->table, strlen (str) + 1);
-         if (n == NULL)
-           return (bfd_size_type) -1;
-         entry->root.string = n;
-       }
-      entry->index = (bfd_size_type) -1;
-      entry->next = NULL;
-    }
+  /* Don't hash if BFD_TRADITIONAL_FORMAT is set, because SunOS dbx
+     doesn't understand a hashed string table.  */
+  hash = true;
+  if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+    hash = false;
 
-  if (entry->index == (bfd_size_type) -1)
-    {
-      entry->index = tab->size;
-      tab->size += strlen (str) + 1;
-      if (tab->first == NULL)
-       tab->first = entry;
-      else
-       tab->last->next = entry;
-      tab->last = entry;
-    }
-
-  return entry->index;
+  /* Add BYTES_IN_WORD to the return value to account for the space
+     taken up by the count.  */
+  return BYTES_IN_WORD + _bfd_stringtab_add (tab, str, hash, copy);
 }
 
 /* Write out a strtab.  ABFD is already at the right location in the
@@ -1909,27 +1786,16 @@ add_to_stringtab (abfd, tab, str, copy)
 static boolean
 emit_stringtab (abfd, tab)
      register bfd *abfd;
-     struct strtab_hash *tab;
+     struct bfd_strtab_hash *tab;
 {
   bfd_byte buffer[BYTES_IN_WORD];
-  register struct strtab_hash_entry *entry;
 
-  PUT_WORD (abfd, tab->size, buffer);
+  /* The string table starts with the size.  */
+  PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer);
   if (bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd) != BYTES_IN_WORD)
     return false;
 
-  for (entry = tab->first; entry != NULL; entry = entry->next)
-    {
-      register const char *str;
-      register size_t len;
-
-      str = entry->root.string;
-      len = strlen (str) + 1;
-      if (bfd_write ((PTR) str, 1, len, abfd) != len)
-       return false;
-    }
-
-  return true;
+  return _bfd_stringtab_emit (abfd, tab);
 }
 \f
 boolean
@@ -1938,9 +1804,10 @@ NAME(aout,write_syms) (abfd)
 {
   unsigned int count ;
   asymbol **generic = bfd_get_outsymbols (abfd);
-  struct strtab_hash strtab;
+  struct bfd_strtab_hash *strtab;
 
-  if (! stringtab_init (&strtab))
+  strtab = _bfd_stringtab_init ();
+  if (strtab == NULL)
     return false;
 
   for (count = 0; count < bfd_get_symcount (abfd); count++)
@@ -1949,7 +1816,7 @@ NAME(aout,write_syms) (abfd)
       bfd_size_type indx;
       struct external_nlist nsp;
 
-      indx = add_to_stringtab (abfd, &strtab, g->name, false);
+      indx = add_to_stringtab (abfd, strtab, g->name, false);
       if (indx == (bfd_size_type) -1)
        goto error_return;
       PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx);
@@ -1979,15 +1846,15 @@ NAME(aout,write_syms) (abfd)
       g->KEEPIT = count;
     }
 
-  if (! emit_stringtab (abfd, &strtab))
+  if (! emit_stringtab (abfd, strtab))
     goto error_return;
 
-  stringtab_free (&strtab);
+  _bfd_stringtab_free (strtab);
 
   return true;
 
 error_return:
-  stringtab_free (&strtab);
+  _bfd_stringtab_free (strtab);
   return false;
 }
 
@@ -2905,11 +2772,7 @@ aout_link_check_archive_element (abfd, info, pneeded)
        return false;
     }
 
-  /* We keep around the symbols even if we aren't going to use this
-     object file, because we may want to reread it.  This doesn't
-     waste too much memory, because it isn't all that common to read
-     an archive element but not need it.  */
-  if (! info->keep_memory)
+  if (! info->keep_memory || ! *pneeded)
     {
       if (! aout_link_free_symbols (abfd))
        return false;
@@ -3343,27 +3206,35 @@ struct aout_final_link_info
   /* File position of symbols.  */
   file_ptr symoff;
   /* String table.  */
-  struct strtab_hash strtab;
+  struct bfd_strtab_hash *strtab;
+  /* A buffer large enough to hold the contents of any section.  */
+  bfd_byte *contents;
+  /* A buffer large enough to hold the relocs of any section.  */
+  PTR relocs;
+  /* A buffer large enough to hold the symbol map of any input BFD.  */
+  int *symbol_map;
+  /* A buffer large enough to hold output symbols of any input BFD.  */
+  struct external_nlist *output_syms;
 };
 
 static boolean aout_link_input_bfd
   PARAMS ((struct aout_final_link_info *, bfd *input_bfd));
 static boolean aout_link_write_symbols
-  PARAMS ((struct aout_final_link_info *, bfd *input_bfd, int *symbol_map));
+  PARAMS ((struct aout_final_link_info *, bfd *input_bfd));
 static boolean aout_link_write_other_symbol
   PARAMS ((struct aout_link_hash_entry *, PTR));
 static boolean aout_link_input_section
   PARAMS ((struct aout_final_link_info *, bfd *input_bfd,
           asection *input_section, file_ptr *reloff_ptr,
-          bfd_size_type rel_size, int *symbol_map));
+          bfd_size_type rel_size));
 static boolean aout_link_input_section_std
   PARAMS ((struct aout_final_link_info *, bfd *input_bfd,
           asection *input_section, struct reloc_std_external *,
-          bfd_size_type rel_size, bfd_byte *contents, int *symbol_map));
+          bfd_size_type rel_size, bfd_byte *contents));
 static boolean aout_link_input_section_ext
   PARAMS ((struct aout_final_link_info *, bfd *input_bfd,
           asection *input_section, struct reloc_ext_external *,
-          bfd_size_type rel_size, bfd_byte *contents, int *symbol_map));
+          bfd_size_type rel_size, bfd_byte *contents));
 static INLINE asection *aout_reloc_index_to_section
   PARAMS ((bfd *, int));
 static boolean aout_link_reloc_link_order
@@ -3385,6 +3256,10 @@ NAME(aout,final_link) (abfd, info, callback)
 {
   struct aout_final_link_info aout_info;
   register bfd *sub;
+  bfd_size_type trsize, drsize;
+  size_t max_contents_size;
+  size_t max_relocs_size;
+  size_t max_sym_count;
   bfd_size_type text_size;
   file_ptr text_end;
   register struct bfd_link_order *p;
@@ -3393,20 +3268,21 @@ NAME(aout,final_link) (abfd, info, callback)
 
   aout_info.info = info;
   aout_info.output_bfd = abfd;
-
-  if (! info->relocateable)
+  aout_info.contents = NULL;
+  aout_info.relocs = NULL;
+
+  /* Figure out the largest section size.  Also, if generating
+     relocateable output, count the relocs.  */
+  trsize = 0;
+  drsize = 0;
+  max_contents_size = 0;
+  max_relocs_size = 0;
+  max_sym_count = 0;
+  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
     {
-      exec_hdr (abfd)->a_trsize = 0;
-      exec_hdr (abfd)->a_drsize = 0;
-    }
-  else
-    {
-      bfd_size_type trsize, drsize;
+      size_t sz;
 
-      /* Count up the relocation sizes.  */
-      trsize = 0;
-      drsize = 0;
-      for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
+      if (info->relocateable)
        {
          if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
            {
@@ -3422,25 +3298,48 @@ NAME(aout,final_link) (abfd, info, callback)
              abort ();
            }
        }
+
+      sz = bfd_section_size (sub, obj_textsec (sub));
+      if (sz > max_contents_size)
+       max_contents_size = sz;
+      sz = bfd_section_size (sub, obj_datasec (sub));
+      if (sz > max_contents_size)
+       max_contents_size = sz;
+
+      sz = exec_hdr (sub)->a_trsize;
+      if (sz > max_relocs_size)
+       max_relocs_size = sz;
+      sz = exec_hdr (sub)->a_drsize;
+      if (sz > max_relocs_size)
+       max_relocs_size = sz;
+
+      sz = obj_aout_external_sym_count (sub);
+      if (sz > max_sym_count)
+       max_sym_count = sz;
+    }
+
+  if (info->relocateable)
+    {
       if (obj_textsec (abfd) != (asection *) NULL)
        trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
                                                 ->link_order_head)
                   * obj_reloc_entry_size (abfd));
-      exec_hdr (abfd)->a_trsize = trsize;
       if (obj_datasec (abfd) != (asection *) NULL)
        drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd)
                                                 ->link_order_head)
                   * obj_reloc_entry_size (abfd));
-      exec_hdr (abfd)->a_drsize = drsize;
     }
 
+  exec_hdr (abfd)->a_trsize = trsize;
+  exec_hdr (abfd)->a_drsize = drsize;
+
   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
 
   /* Adjust the section sizes and vmas according to the magic number.
      This sets a_text, a_data and a_bss in the exec_hdr and sets the
      filepos for each section.  */
   if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
-    return false;
+    goto error_return;
 
   /* The relocation and symbol file positions differ among a.out
      targets.  We are passed a callback routine from the backend
@@ -3460,8 +3359,25 @@ NAME(aout,final_link) (abfd, info, callback)
   obj_aout_external_sym_count (abfd) = 0;
 
   /* We accumulate the string table as we write out the symbols.  */
-  if (! stringtab_init (&aout_info.strtab))
-    return false;
+  aout_info.strtab = _bfd_stringtab_init ();
+  if (aout_info.strtab == NULL)
+    goto error_return;
+
+  /* Allocate buffers to hold section contents and relocs.  */
+  aout_info.contents = (bfd_byte *) malloc (max_contents_size);
+  aout_info.relocs = (PTR) malloc (max_relocs_size);
+  aout_info.symbol_map = (int *) malloc (max_sym_count * sizeof (int *));
+  aout_info.output_syms = ((struct external_nlist *)
+                          malloc ((max_sym_count + 1)
+                                  * sizeof (struct external_nlist)));
+  if ((aout_info.contents == NULL && max_contents_size != 0)
+      || (aout_info.relocs == NULL && max_relocs_size != 0)
+      || (aout_info.symbol_map == NULL && max_sym_count != 0)
+      || aout_info.output_syms == NULL)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
 
   /* The most time efficient way to do the link would be to read all
      the input object files into memory and then sort out the
@@ -3504,7 +3420,7 @@ NAME(aout,final_link) (abfd, info, callback)
              if (! input_bfd->output_has_begun)
                {
                  if (! aout_link_input_bfd (&aout_info, input_bfd))
-                   return false;
+                   goto error_return;
                  input_bfd->output_has_begun = true;
                }
            }
@@ -3517,7 +3433,7 @@ NAME(aout,final_link) (abfd, info, callback)
          else
            {
              if (! _bfd_default_link_order (abfd, info, o, p))
-               return false;
+               goto error_return;
            }
        }
     }
@@ -3543,17 +3459,38 @@ NAME(aout,final_link) (abfd, info, callback)
                  || p->type == bfd_symbol_reloc_link_order)
                {
                  if (! aout_link_reloc_link_order (&aout_info, o, p))
-                   return false;
+                   goto error_return;
                }
            }
        }
     }
 
+  if (aout_info.contents != NULL)
+    {
+      free (aout_info.contents);
+      aout_info.contents = NULL;
+    }
+  if (aout_info.relocs != NULL)
+    {
+      free (aout_info.relocs);
+      aout_info.relocs = NULL;
+    }
+  if (aout_info.symbol_map != NULL)
+    {
+      free (aout_info.symbol_map);
+      aout_info.symbol_map = NULL;
+    }
+  if (aout_info.output_syms != NULL)
+    {
+      free (aout_info.output_syms);
+      aout_info.output_syms = NULL;
+    }
+
   /* Finish up any dynamic linking we may be doing.  */
   if (aout_backend_info (abfd)->finish_dynamic_link != NULL)
     {
       if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info))
-       return false;
+       goto error_return;
     }
 
   /* Update the header information.  */
@@ -3567,8 +3504,19 @@ NAME(aout,final_link) (abfd, info, callback)
 
   /* Write out the string table.  */
   if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0)
-    return false;
-  return emit_stringtab (abfd, &aout_info.strtab);
+    goto error_return;
+  return emit_stringtab (abfd, aout_info.strtab);
+
+ error_return:
+  if (aout_info.contents != NULL)
+    free (aout_info.contents);
+  if (aout_info.relocs != NULL)
+    free (aout_info.relocs);
+  if (aout_info.symbol_map != NULL)
+    free (aout_info.symbol_map);
+  if (aout_info.output_syms != NULL)
+    free (aout_info.output_syms);
+  return false;
 }
 
 /* Link an a.out input BFD into the output file.  */
@@ -3579,7 +3527,6 @@ aout_link_input_bfd (finfo, input_bfd)
      bfd *input_bfd;
 {
   bfd_size_type sym_count;
-  int *symbol_map = NULL;
 
   BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
 
@@ -3597,29 +3544,23 @@ aout_link_input_bfd (finfo, input_bfd)
     return false;
 
   sym_count = obj_aout_external_sym_count (input_bfd);
-  symbol_map = (int *) malloc ((size_t) sym_count * sizeof (int));
-  if (symbol_map == NULL && sym_count != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
 
-  /* Write out the symbols and get a map of the new indices.  */
-  if (! aout_link_write_symbols (finfo, input_bfd, symbol_map))
-    goto error_return;
+  /* Write out the symbols and get a map of the new indices.  The map
+     is placed into finfo->symbol_map.  */
+  if (! aout_link_write_symbols (finfo, input_bfd))
+    return false;
 
-  /* Relocate and write out the sections.  */
+  /* Relocate and write out the sections.  These functions use the
+     symbol map created by aout_link_write_symbols.  */
   if (! aout_link_input_section (finfo, input_bfd,
                                 obj_textsec (input_bfd),
                                 &finfo->treloff,
-                                exec_hdr (input_bfd)->a_trsize,
-                                symbol_map)
+                                exec_hdr (input_bfd)->a_trsize)
       || ! aout_link_input_section (finfo, input_bfd,
                                    obj_datasec (input_bfd),
                                    &finfo->dreloff,
-                                   exec_hdr (input_bfd)->a_drsize,
-                                   symbol_map))
-    goto error_return;
+                                   exec_hdr (input_bfd)->a_drsize))
+    return false;
 
   /* If we are not keeping memory, we don't need the symbols any
      longer.  We still need them if we are keeping memory, because the
@@ -3627,38 +3568,31 @@ aout_link_input_bfd (finfo, input_bfd)
   if (! finfo->info->keep_memory)
     {
       if (! aout_link_free_symbols (input_bfd))
-       goto error_return;
+       return false;
     }
 
-  if (symbol_map != NULL)
-    free (symbol_map);
   return true;
- error_return:
-  if (symbol_map != NULL)
-    free (symbol_map);
-  return false;
 }
 
 /* Adjust and write out the symbols for an a.out file.  Set the new
    symbol indices into a symbol_map.  */
 
 static boolean
-aout_link_write_symbols (finfo, input_bfd, symbol_map)
+aout_link_write_symbols (finfo, input_bfd)
      struct aout_final_link_info *finfo;
      bfd *input_bfd;
-     int *symbol_map;
 {
   bfd *output_bfd;
   bfd_size_type sym_count;
   char *strings;
   enum bfd_link_strip strip;
   enum bfd_link_discard discard;
-  struct external_nlist *output_syms = NULL;
   struct external_nlist *outsym;
   bfd_size_type strtab_index;
   register struct external_nlist *sym;
   struct external_nlist *sym_end;
   struct aout_link_hash_entry **sym_hash;
+  int *symbol_map;
   boolean pass;
   boolean skip_indirect;
 
@@ -3667,14 +3601,7 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
   strings = obj_aout_external_strings (input_bfd);
   strip = finfo->info->strip;
   discard = finfo->info->discard;
-  output_syms = ((struct external_nlist *)
-                malloc ((size_t) (sym_count + 1) * EXTERNAL_NLIST_SIZE));
-  if (output_syms == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
-  outsym = output_syms;
+  outsym = finfo->output_syms;
 
   /* First write out a symbol for this object file, unless we are
      discarding such symbols.  */
@@ -3687,10 +3614,10 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
       bfd_h_put_8 (output_bfd, N_TEXT, outsym->e_type);
       bfd_h_put_8 (output_bfd, 0, outsym->e_other);
       bfd_h_put_16 (output_bfd, (bfd_vma) 0, outsym->e_desc);
-      strtab_index = add_to_stringtab (output_bfd, &finfo->strtab,
+      strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
                                       input_bfd->filename, false);
       if (strtab_index == (bfd_size_type) -1)
-       goto error_return;
+       return false;
       PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
       PUT_WORD (output_bfd,
                (bfd_get_section_vma (output_bfd,
@@ -3706,6 +3633,7 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
   sym = obj_aout_external_syms (input_bfd);
   sym_end = sym + sym_count;
   sym_hash = obj_aout_sym_hashes (input_bfd);
+  symbol_map = finfo->symbol_map;
   for (; sym < sym_end; sym++, sym_hash++, symbol_map++)
     {
       const char *name;
@@ -3970,14 +3898,14 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
             free.  If there is a hash table entry, use that string.
             Otherwise, copy name into memory.  */
          if (h != (struct aout_link_hash_entry *) NULL)
-           name = (*sym_hash)->root.root.string;
+           name = h->root.root.string;
          else
            copy = true;
        }
-      strtab_index = add_to_stringtab (output_bfd, &finfo->strtab,
+      strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
                                       name, copy);
       if (strtab_index == (bfd_size_type) -1)
-       goto error_return;
+       return false;
       PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
       PUT_WORD (output_bfd, val, outsym->e_value);
       *symbol_map = obj_aout_external_sym_count (output_bfd);
@@ -3986,27 +3914,22 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
     }
 
   /* Write out the output symbols we have just constructed.  */
-  if (outsym > output_syms)
+  if (outsym > finfo->output_syms)
     {
       bfd_size_type outsym_count;
 
       if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0)
-       goto error_return;
-      outsym_count = outsym - output_syms;
-      if (bfd_write ((PTR) output_syms, (bfd_size_type) EXTERNAL_NLIST_SIZE,
+       return false;
+      outsym_count = outsym - finfo->output_syms;
+      if (bfd_write ((PTR) finfo->output_syms,
+                    (bfd_size_type) EXTERNAL_NLIST_SIZE,
                     (bfd_size_type) outsym_count, output_bfd)
          != outsym_count * EXTERNAL_NLIST_SIZE)
-       goto error_return;
+       return false;
       finfo->symoff += outsym_count * EXTERNAL_NLIST_SIZE;
     }
 
-  if (output_syms != NULL)
-    free (output_syms);
   return true;
- error_return:
-  if (output_syms != NULL)
-    free (output_syms);
-  return false;
 }
 
 /* Write out a symbol that was not associated with an a.out input
@@ -4098,7 +4021,7 @@ aout_link_write_other_symbol (h, data)
   bfd_h_put_8 (output_bfd, type, outsym.e_type);
   bfd_h_put_8 (output_bfd, 0, outsym.e_other);
   bfd_h_put_16 (output_bfd, 0, outsym.e_desc);
-  indx = add_to_stringtab (output_bfd, &finfo->strtab, h->root.root.string,
+  indx = add_to_stringtab (output_bfd, finfo->strtab, h->root.root.string,
                           false);
   if (indx == (bfd_size_type) -1)
     {
@@ -4127,30 +4050,22 @@ aout_link_write_other_symbol (h, data)
 
 static boolean
 aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
-                        rel_size, symbol_map)
+                        rel_size)
      struct aout_final_link_info *finfo;
      bfd *input_bfd;
      asection *input_section;
      file_ptr *reloff_ptr;
      bfd_size_type rel_size;
-     int *symbol_map;
 {
   bfd_size_type input_size;
-  bfd_byte *contents = NULL;
   PTR relocs;
-  PTR free_relocs = NULL;
 
   /* Get the section contents.  */
   input_size = bfd_section_size (input_bfd, input_section);
-  contents = (bfd_byte *) malloc (input_size);
-  if (contents == NULL && input_size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
-  if (! bfd_get_section_contents (input_bfd, input_section, (PTR) contents,
+  if (! bfd_get_section_contents (input_bfd, input_section,
+                                 (PTR) finfo->contents,
                                  (file_ptr) 0, input_size))
-    goto error_return;
+    return false;
 
   /* Read in the relocs if we haven't already done it.  */
   if (aout_section_data (input_section) != NULL
@@ -4158,15 +4073,10 @@ aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
     relocs = aout_section_data (input_section)->relocs;
   else
     {
-      relocs = free_relocs = (PTR) malloc (rel_size);
-      if (relocs == NULL && rel_size != 0)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         goto error_return;
-       }
+      relocs = finfo->relocs;
       if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
          || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size)
-       goto error_return;
+       return false;
     }
 
   /* Relocate the section contents.  */
@@ -4174,34 +4084,34 @@ aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
     {
       if (! aout_link_input_section_std (finfo, input_bfd, input_section,
                                         (struct reloc_std_external *) relocs,
-                                        rel_size, contents, symbol_map))
-       goto error_return;
+                                        rel_size, finfo->contents))
+       return false;
     }
   else
     {
       if (! aout_link_input_section_ext (finfo, input_bfd, input_section,
                                         (struct reloc_ext_external *) relocs,
-                                        rel_size, contents, symbol_map))
-       goto error_return;
+                                        rel_size, finfo->contents))
+       return false;
     }
 
   /* Write out the section contents.  */
   if (! bfd_set_section_contents (finfo->output_bfd,
                                  input_section->output_section,
-                                 (PTR) contents,
+                                 (PTR) finfo->contents,
                                  input_section->output_offset,
                                  input_size))
-    goto error_return;
+    return false;
 
   /* If we are producing relocateable output, the relocs were
      modified, and we now write them out.  */
   if (finfo->info->relocateable)
     {
       if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0)
-       goto error_return;
+       return false;
       if (bfd_write (relocs, (bfd_size_type) 1, rel_size, finfo->output_bfd)
          != rel_size)
-       goto error_return;
+       return false;
       *reloff_ptr += rel_size;
 
       /* Assert that the relocs have not run into the symbols, and
@@ -4213,17 +4123,7 @@ aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
                          <= obj_datasec (finfo->output_bfd)->rel_filepos)));
     }
 
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (contents != NULL)
-    free (contents);
   return true;
- error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (contents != NULL)
-    free (contents);
-  return false;
 }
 
 /* Get the section corresponding to a reloc index.  */
@@ -4253,14 +4153,13 @@ aout_reloc_index_to_section (abfd, indx)
 
 static boolean
 aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
-                            rel_size, contents, symbol_map)
+                            rel_size, contents)
      struct aout_final_link_info *finfo;
      bfd *input_bfd;
      asection *input_section;
      struct reloc_std_external *relocs;
      bfd_size_type rel_size;
      bfd_byte *contents;
-     int *symbol_map;
 {
   boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *,
                                          bfd *, asection *,
@@ -4271,6 +4170,7 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
   struct external_nlist *syms;
   char *strings;
   struct aout_link_hash_entry **sym_hashes;
+  int *symbol_map;
   bfd_size_type reloc_count;
   register struct reloc_std_external *rel;
   struct reloc_std_external *rel_end;
@@ -4286,6 +4186,7 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
   syms = obj_aout_external_syms (input_bfd);
   strings = obj_aout_external_strings (input_bfd);
   sym_hashes = obj_aout_sym_hashes (input_bfd);
+  symbol_map = finfo->symbol_map;
 
   reloc_count = rel_size / RELOC_STD_SIZE;
   rel = relocs;
@@ -4551,14 +4452,13 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
 
 static boolean
 aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
-                            rel_size, contents, symbol_map)
+                            rel_size, contents)
      struct aout_final_link_info *finfo;
      bfd *input_bfd;
      asection *input_section;
      struct reloc_ext_external *relocs;
      bfd_size_type rel_size;
      bfd_byte *contents;
-     int *symbol_map;
 {
   boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *,
                                          bfd *, asection *,
@@ -4569,6 +4469,7 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
   struct external_nlist *syms;
   char *strings;
   struct aout_link_hash_entry **sym_hashes;
+  int *symbol_map;
   bfd_size_type reloc_count;
   register struct reloc_ext_external *rel;
   struct reloc_ext_external *rel_end;
@@ -4584,6 +4485,7 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
   syms = obj_aout_external_syms (input_bfd);
   strings = obj_aout_external_strings (input_bfd);
   sym_hashes = obj_aout_sym_hashes (input_bfd);
+  symbol_map = finfo->symbol_map;
 
   reloc_count = rel_size / RELOC_EXT_SIZE;
   rel = relocs;