* aoutx.h (NAME(aout,new_section_hook)): Don't set N_EXT in target
[deliverable/binutils-gdb.git] / bfd / aoutx.h
index 1d0fa1bf5f23ec85f9fc208831ca16dca76211d3..ca56a50c763a801d848cdd97a9c215c36915aebb 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD semi-generic back-end for a.out binaries.
-   Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+   Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -125,7 +125,6 @@ DESCRIPTION
 #include <string.h>            /* For strchr and friends */
 #include "bfd.h"
 #include <sysdep.h>
-#include <ansidecl.h>
 #include "bfdlink.h"
 
 #include "libaout.h"
@@ -134,6 +133,8 @@ DESCRIPTION
 #include "aout/stab_gnu.h"
 #include "aout/ar.h"
 
+static boolean aout_get_external_symbols PARAMS ((bfd *));
+
 /*
 SUBSECTION
        Relocations
@@ -202,9 +203,9 @@ HOWTO(10,          0,  2,   32, false, 0, complain_overflow_bitfield,0,"BASE32",    f
 #define TABLE_SIZE(TABLE)      (sizeof(TABLE)/sizeof(TABLE[0]))
 
 CONST struct reloc_howto_struct *
-DEFUN(NAME(aout,reloc_type_lookup),(abfd,code),
-      bfd *abfd AND
-      bfd_reloc_code_real_type code)
+NAME(aout,reloc_type_lookup) (abfd,code)
+     bfd *abfd;
+     bfd_reloc_code_real_type code;
 {
 #define EXT(i,j)       case i: return &howto_table_ext[j]
 #define STD(i,j)       case i: return &howto_table_std[j]
@@ -215,6 +216,9 @@ DEFUN(NAME(aout,reloc_type_lookup),(abfd,code),
       case 32:
        code = BFD_RELOC_32;
        break;
+      case 64:
+       code = BFD_RELOC_64;
+       break;
       }
   if (ext)
     switch (code)
@@ -224,6 +228,8 @@ DEFUN(NAME(aout,reloc_type_lookup),(abfd,code),
        EXT (BFD_RELOC_LO10, 11);
        EXT (BFD_RELOC_32_PCREL_S2, 6);
        EXT (BFD_RELOC_SPARC_WDISP22, 7);
+       EXT (BFD_RELOC_SPARC13, 10);
+       EXT (BFD_RELOC_SPARC_BASE13, 15);
       default: return (CONST struct reloc_howto_struct *) 0;
       }
   else
@@ -270,10 +276,10 @@ DESCRIPTION
 
 #ifndef NAME_swap_exec_header_in
 void
-DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp),
-      bfd *abfd AND
-      struct external_exec *raw_bytes AND
-      struct internal_exec *execp)
+NAME(aout,swap_exec_header_in) (abfd, raw_bytes, execp)
+     bfd *abfd;
+     struct external_exec *raw_bytes;
+     struct internal_exec *execp;
 {
   struct external_exec *bytes = (struct external_exec *)raw_bytes;
 
@@ -281,7 +287,7 @@ DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp),
      configuration (IE for i960), so ensure that all such uninitialized
      fields are zero'd out.  There are places where two of these structs
      are memcmp'd, and thus the contents do matter. */
-  memset (execp, 0, sizeof (struct internal_exec));
+  memset ((PTR) execp, 0, sizeof (struct internal_exec));
   /* Now fill in fields in the execp, from the bytes in the raw data.  */
   execp->a_info   = bfd_h_get_32 (abfd, bytes->e_info);
   execp->a_text   = GET_WORD (abfd, bytes->e_text);
@@ -310,10 +316,10 @@ DESCRIPTION
        @var{execp} into the buffer @var{raw_bytes} ready for writing to disk.
 */
 void
-DEFUN(NAME(aout,swap_exec_header_out),(abfd, execp, raw_bytes),
-     bfd *abfd AND
-     struct internal_exec *execp AND
-     struct external_exec *raw_bytes)
+NAME(aout,swap_exec_header_out) (abfd, execp, raw_bytes)
+     bfd *abfd;
+     struct internal_exec *execp;
+     struct external_exec *raw_bytes;
 {
   struct external_exec *bytes = (struct external_exec *)raw_bytes;
 
@@ -348,17 +354,17 @@ DESCRIPTION
 */
 
 bfd_target *
-DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p),
-      bfd *abfd AND
-      struct internal_exec *execp AND
-      bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *)))
+NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p)
+     bfd *abfd;
+     struct internal_exec *execp;
+     bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *));
 {
   struct aout_data_struct *rawptr, *oldrawptr;
   bfd_target *result;
 
   rawptr = (struct aout_data_struct  *) bfd_zalloc (abfd, sizeof (struct aout_data_struct ));
   if (rawptr == NULL) {
-    bfd_error = no_memory;
+    bfd_set_error (bfd_error_no_memory);
     return 0;
   }
 
@@ -430,18 +436,23 @@ DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p),
   obj_datasec (abfd)->_raw_size = execp->a_data;
   obj_bsssec (abfd)->_raw_size = execp->a_bss;
 
-  obj_textsec (abfd)->flags = (execp->a_trsize != 0 ?
-       (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) :
-       (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
-  obj_datasec (abfd)->flags = (execp->a_drsize != 0 ?
-       (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) :
-       (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
+  /* If this object is dynamically linked, we assume that both
+     sections have relocs.  This does no real harm, even though it may
+     not be true.  */
+  obj_textsec (abfd)->flags =
+    (execp->a_trsize != 0 || (abfd->flags & DYNAMIC) != 0
+     ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
+     : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
+  obj_datasec (abfd)->flags =
+    (execp->a_drsize != 0 || (abfd->flags & DYNAMIC) != 0
+     ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
+     : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
   obj_bsssec (abfd)->flags = SEC_ALLOC;
 
 #ifdef THIS_IS_ONLY_DOCUMENTATION
   /* The common code can't fill in these things because they depend
      on either the start address of the text segment, the rounding
-     up of virtual addersses between segments, or the starting file
+     up of virtual addresses between segments, or the starting file
      position of the text segment -- all of which varies among different
      versions of a.out.  */
 
@@ -536,18 +547,18 @@ DESCRIPTION
 */
 
 boolean
-DEFUN(NAME(aout,mkobject),(abfd),
-     bfd *abfd)
+NAME(aout,mkobject) (abfd)
+     bfd *abfd;
 {
   struct aout_data_struct  *rawptr;
 
-  bfd_error = system_call_error;
+  bfd_set_error (bfd_error_system_call);
 
   /* Use an intermediate variable for clarity */
   rawptr = (struct aout_data_struct *)bfd_zalloc (abfd, sizeof (struct aout_data_struct ));
 
   if (rawptr == NULL) {
-    bfd_error = no_memory;
+    bfd_set_error (bfd_error_no_memory);
     return false;
   }
 
@@ -590,9 +601,9 @@ DESCRIPTION
 */
 
 enum machine_type
-DEFUN(NAME(aout,machine_type),(arch, machine),
-      enum bfd_architecture arch AND
-      unsigned long machine)
+NAME(aout,machine_type) (arch, machine)
+     enum bfd_architecture arch;
+     unsigned long machine;
 {
   enum machine_type arch_flags;
 
@@ -657,10 +668,10 @@ DESCRIPTION
 */
 
 boolean
-DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine),
-      bfd *abfd AND
-      enum bfd_architecture arch AND
-      unsigned long machine)
+NAME(aout,set_arch_mach) (abfd, arch, machine)
+     bfd *abfd;
+     enum bfd_architecture arch;
+     unsigned long machine;
 {
   if (! bfd_default_set_arch_mach (abfd, arch, machine))
     return false;
@@ -788,10 +799,8 @@ adjust_z_magic (abfd, execp)
   if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted)))
     execp->a_text += adata(abfd).exec_bytes_size;
   N_SET_MAGIC (*execp, ZMAGIC);
+
   /* Spec says data section should be rounded up to page boundary.  */
-  /* If extra space in page is left after data section, fudge data
-     in the header so that the bss section looks smaller by that
-     amount.  We'll start the bss section there, and lie to the OS.  */
   obj_datasec(abfd)->_raw_size
     = align_power (obj_datasec(abfd)->_raw_size,
                   obj_bsssec(abfd)->alignment_power);
@@ -803,8 +812,19 @@ adjust_z_magic (abfd, execp)
   if (!obj_bsssec(abfd)->user_set_vma)
     obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma
                             + obj_datasec(abfd)->_raw_size);
-  execp->a_bss = (data_pad > obj_bsssec(abfd)->_raw_size) ? 0 :
-    obj_bsssec(abfd)->_raw_size - data_pad;
+  /* If the BSS immediately follows the data section and extra space
+     in the page is left after the data section, fudge data
+     in the header so that the bss section looks smaller by that
+     amount.  We'll start the bss section there, and lie to the OS.
+     (Note that a linker script, as well as the above assignment,
+     could have explicitly set the BSS vma to immediately follow
+     the data section.)  */
+  if (align_power (obj_bsssec(abfd)->vma, obj_bsssec(abfd)->alignment_power)
+      == obj_datasec(abfd)->vma + obj_datasec(abfd)->_raw_size)
+    execp->a_bss = (data_pad > obj_bsssec(abfd)->_raw_size) ? 0 :
+      obj_bsssec(abfd)->_raw_size - data_pad;
+  else
+    execp->a_bss = obj_bsssec(abfd)->_raw_size;
 }
 
 static void
@@ -851,14 +871,16 @@ adjust_n_magic (abfd, execp)
 }
 
 boolean
-DEFUN (NAME(aout,adjust_sizes_and_vmas), (abfd, text_size, text_end),
-       bfd *abfd AND bfd_size_type *text_size AND file_ptr *text_end)
+NAME(aout,adjust_sizes_and_vmas) (abfd, text_size, text_end)
+     bfd *abfd;
+     bfd_size_type *text_size;
+     file_ptr *text_end;
 {
   struct internal_exec *execp = exec_hdr (abfd);
 
   if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL))
     {
-      bfd_error = invalid_operation;
+      bfd_set_error (bfd_error_invalid_operation);
       return false;
     }
   if (adata(abfd).magic != undecided_magic) return true;
@@ -955,9 +977,9 @@ DESCRIPTION
        request.
 */
 boolean
-DEFUN(NAME(aout,new_section_hook),(abfd, newsect),
-       bfd *abfd AND
-       asection *newsect)
+NAME(aout,new_section_hook) (abfd, newsect)
+     bfd *abfd;
+     asection *newsect;
 {
   /* align to double at least */
   newsect->alignment_power = bfd_get_arch_info(abfd)->section_align_power;
@@ -967,19 +989,19 @@ DEFUN(NAME(aout,new_section_hook),(abfd, newsect),
   {
     if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
        obj_textsec(abfd)= newsect;
-       newsect->target_index = N_TEXT | N_EXT;
+       newsect->target_index = N_TEXT;
        return true;
       }
 
     if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
        obj_datasec(abfd) = newsect;
-       newsect->target_index = N_DATA | N_EXT;
+       newsect->target_index = N_DATA;
        return true;
       }
 
     if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
        obj_bsssec(abfd) = newsect;
-       newsect->target_index = N_BSS | N_EXT;
+       newsect->target_index = N_BSS;
        return true;
       }
 
@@ -990,12 +1012,12 @@ DEFUN(NAME(aout,new_section_hook),(abfd, newsect),
 }
 
 boolean
-DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count),
-      bfd *abfd AND
-      sec_ptr section AND
-      PTR location AND
-      file_ptr offset AND
-      bfd_size_type count)
+NAME(aout,set_section_contents) (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     PTR location;
+     file_ptr offset;
+     bfd_size_type count;
 {
   file_ptr text_end;
   bfd_size_type text_size;
@@ -1011,7 +1033,8 @@ DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count),
   /* regardless, once we know what we're doing, we might as well get going */
   if (section != obj_bsssec(abfd))
       {
-       bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+       if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
+         return false;
 
        if (count) {
          return (bfd_write ((PTR)location, 1, count, abfd) == count) ?
@@ -1060,28 +1083,110 @@ DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count),
 #define sym_is_indirect(sym) \
   (((sym)->type & N_ABS)== N_ABS)
 
+/* Read the external symbols from an a.out file.  */
+
+static boolean
+aout_get_external_symbols (abfd)
+     bfd *abfd;
+{
+  if (obj_aout_external_syms (abfd) == (struct external_nlist *) NULL)
+    {
+      bfd_size_type count;
+      struct external_nlist *syms;
+
+      count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE;
+
+      /* We allocate using malloc to make the values easy to free
+        later on.  If we put them on the obstack it might not be
+        possible to free them.  */
+      syms = ((struct external_nlist *)
+             malloc ((size_t) count * EXTERNAL_NLIST_SIZE));
+      if (syms == (struct external_nlist *) NULL && count != 0)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
+
+      if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
+         || (bfd_read (syms, 1, exec_hdr (abfd)->a_syms, abfd)
+             != exec_hdr (abfd)->a_syms))
+       {
+         free (syms);
+         return false;
+       }
+
+      obj_aout_external_syms (abfd) = syms;
+      obj_aout_external_sym_count (abfd) = count;
+    }
+      
+  if (obj_aout_external_strings (abfd) == NULL)
+    {
+      unsigned char string_chars[BYTES_IN_WORD];
+      bfd_size_type stringsize;
+      char *strings;
+
+      /* Get the size of the strings.  */
+      if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
+         || (bfd_read ((PTR) string_chars, BYTES_IN_WORD, 1, abfd)
+             != BYTES_IN_WORD))
+       return false;
+      stringsize = GET_WORD (abfd, string_chars);
+
+      strings = (char *) malloc ((size_t) stringsize + 1);
+      if (strings == NULL)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
+
+      /* Skip space for the string count in the buffer for convenience
+        when using indexes.  */
+      if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD,
+                   abfd)
+         != stringsize - BYTES_IN_WORD)
+       {
+         free (strings);
+         return false;
+       }
+
+      /* Sanity preservation.  */
+      strings[stringsize] = '\0';
+
+      obj_aout_external_strings (abfd) = strings;
+      obj_aout_external_string_size (abfd) = stringsize;
+    }
+
+  return true;
+}
+
 /* Only in their own functions for ease of debugging; when sym flags have
   stabilised these should be inlined into their (single) caller */
 
-static void
-DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd),
-       struct external_nlist *sym_pointer AND
-       aout_symbol_type * cache_ptr AND
-       bfd * abfd)
+static boolean
+translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd)
+     struct external_nlist *sym_pointer;
+     aout_symbol_type * cache_ptr;
+     bfd * abfd;
 {
   cache_ptr->symbol.section = 0;
   switch (cache_ptr->type & N_TYPE)
     {
-    case N_SETA:
-    case N_SETT:
-    case N_SETD:
-    case N_SETB:
+    case N_SETA: case N_SETA | N_EXT:
+    case N_SETT: case N_SETT | N_EXT:
+    case N_SETD: case N_SETD | N_EXT:
+    case N_SETB: case N_SETB | N_EXT:
       {
        char *copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1);
        asection *section;
        asection *into_section;
-
        arelent_chain *reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
+
+       if (!copy || !reloc)
+         {
+           bfd_set_error (bfd_error_no_memory);
+           return false;
+         }
+
        strcpy (copy, cache_ptr->symbol.name);
 
        /* Make sure that this bfd has a section with the right contructor
@@ -1093,24 +1198,25 @@ DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd),
        /* Build a relocation entry for the constructor */
        switch ((cache_ptr->type & N_TYPE))
          {
-         case N_SETA:
+         case N_SETA: case N_SETA | N_EXT:
            into_section = &bfd_abs_section;
            cache_ptr->type = N_ABS;
            break;
-         case N_SETT:
+         case N_SETT: case N_SETT | N_EXT:
            into_section = (asection *) obj_textsec (abfd);
            cache_ptr->type = N_TEXT;
            break;
-         case N_SETD:
+         case N_SETD: case N_SETD | N_EXT:
            into_section = (asection *) obj_datasec (abfd);
            cache_ptr->type = N_DATA;
            break;
-         case N_SETB:
+         case N_SETB: case N_SETB | N_EXT:
            into_section = (asection *) obj_bsssec (abfd);
            cache_ptr->type = N_BSS;
            break;
          default:
-           abort ();
+           bfd_set_error (bfd_error_bad_value);
+           return false;
          }
 
        /* Build a relocation pointing into the constuctor section
@@ -1127,7 +1233,7 @@ DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd),
           pointer to the symbol. Build a reloc entry to relocate to this
           symbol attached to this section.  */
 
-       section->flags = SEC_CONSTRUCTOR;
+       section->flags = SEC_CONSTRUCTOR | SEC_RELOC;
 
 
        section->reloc_count++;
@@ -1159,6 +1265,11 @@ DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd),
            abort ();
          cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1));
 
+          /* We don't use a warning symbol's section, but we need
+            it to be nonzero for the sanity check below, so
+            pick one arbitrarily.  */
+         cache_ptr->symbol.section = &bfd_abs_section;
+
          /* We furgle with the next symbol in place.
             We don't want it to be undefined, we'll trample the type */
          (sym_pointer + 1)->e_type[0] = 0xff;
@@ -1259,7 +1370,7 @@ DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd),
            {
              cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
            }
-         else
+         else if (! sym_is_undefined (cache_ptr))
            {
              cache_ptr->symbol.flags = BSF_LOCAL;
            }
@@ -1267,15 +1378,15 @@ DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd),
     }
   if (cache_ptr->symbol.section == 0)
     abort ();
+  return true;
 }
 
 
-
 static boolean
-DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
-     struct external_nlist *sym_pointer AND
-     asymbol *cache_ptr AND
-     bfd *abfd)
+translate_to_native_sym_flags (sym_pointer, cache_ptr, abfd)
+     struct external_nlist *sym_pointer;
+     asymbol *cache_ptr;
+     bfd *abfd;
 {
   bfd_vma value = cache_ptr->value;
 
@@ -1283,7 +1394,6 @@ DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
      to another */
   sym_pointer->e_type[0] &= ~N_TYPE;
 
-
   /* We attempt to order these tests by decreasing frequency of success,
      according to tcov when linking the linker.  */
   if (bfd_get_output_section(cache_ptr) == &bfd_abs_section) {
@@ -1298,27 +1408,33 @@ DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
   else if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
     sym_pointer->e_type[0] |= N_BSS;
   }
-  else if (bfd_get_output_section(cache_ptr) == &bfd_und_section)
-    {
-      sym_pointer->e_type[0] = (N_UNDF | N_EXT);
-    }
-  else if (bfd_get_output_section(cache_ptr) == &bfd_ind_section)
-    {
-      sym_pointer->e_type[0] = N_INDR;
-    }
+  else if (bfd_get_output_section(cache_ptr) == &bfd_und_section) {
+    sym_pointer->e_type[0] = (N_UNDF | N_EXT);
+  }
+  else if (bfd_get_output_section(cache_ptr) == &bfd_ind_section) {
+    sym_pointer->e_type[0] = N_INDR;
+  }
+  else if (bfd_get_output_section(cache_ptr) == NULL) {
+    /* Protect the bfd_is_com_section call.
+       This case occurs, e.g., for the *DEBUG* section of a COFF file.  */
+    bfd_set_error (bfd_error_nonrepresentable_section);
+    return false;
+  }
   else if (bfd_is_com_section (bfd_get_output_section (cache_ptr))) {
     sym_pointer->e_type[0] = (N_UNDF | N_EXT);
   }
   else {
-    bfd_error = bfd_error_nonrepresentable_section;
+    bfd_set_error (bfd_error_nonrepresentable_section);
     return false;
   }
+
   /* Turn the symbol from section relative to absolute again */
 
   value +=  cache_ptr->section->output_section->vma  + cache_ptr->section->output_offset ;
 
 
   if (cache_ptr->flags & (BSF_WARNING)) {
+    sym_pointer->e_type[0] = N_WARNING;
     (sym_pointer+1)->e_type[0] = 1;
   }
 
@@ -1347,107 +1463,141 @@ DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
 \f
 /* Native-level interface to symbols. */
 
-/* We read the symbols into a buffer, which is discarded when this
-function exits.  We read the strings into a buffer large enough to
-hold them all plus all the cached symbol entries. */
 
 asymbol *
-DEFUN(NAME(aout,make_empty_symbol),(abfd),
-      bfd *abfd)
+NAME(aout,make_empty_symbol) (abfd)
+     bfd *abfd;
 {
   aout_symbol_type  *new =
     (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
+  if (!new)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
   new->symbol.the_bfd = abfd;
 
   return &new->symbol;
 }
 
+/* Translate a set of internal symbols into external symbols.  */
+
 boolean
-DEFUN(NAME(aout,slurp_symbol_table),(abfd),
-      bfd *abfd)
+NAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic)
+     bfd *abfd;
+     aout_symbol_type *in;
+     struct external_nlist *ext;
+     bfd_size_type count;
+     char *str;
+     bfd_size_type strsize;
+     boolean dynamic;
 {
-  bfd_size_type symbol_size;
-  bfd_size_type string_size;
-  unsigned char string_chars[BYTES_IN_WORD];
-  struct external_nlist *syms;
-  char *strings;
+  struct external_nlist *ext_end;
+
+  ext_end = ext + count;
+  for (; ext < ext_end; ext++, in++)
+    {
+      bfd_vma x;
+
+      x = GET_WORD (abfd, ext->e_strx);
+      in->symbol.the_bfd = abfd;
+
+      /* For the normal symbols, the zero index points at the number
+        of bytes in the string table but is to be interpreted as the
+        null string.  For the dynamic symbols, the number of bytes in
+        the string table is stored in the __DYNAMIC structure and the
+        zero index points at an actual string.  */
+      if (x == 0 && ! dynamic)
+       in->symbol.name = "";
+      else if (x < strsize)
+       in->symbol.name = str + x;
+      else
+       return false;
+
+      in->symbol.value = GET_SWORD (abfd,  ext->e_value);
+      in->desc = bfd_h_get_16 (abfd, ext->e_desc);
+      in->other = bfd_h_get_8 (abfd, ext->e_other);
+      in->type = bfd_h_get_8 (abfd,  ext->e_type);
+      in->symbol.udata = 0;
+
+      if (!translate_from_native_sym_flags (ext, in, abfd))
+       return false;
+
+      if (dynamic)
+       in->symbol.flags |= BSF_DYNAMIC;
+    }
+
+  return true;
+}
+
+/* We read the symbols into a buffer, which is discarded when this
+   function exits.  We read the strings into a buffer large enough to
+   hold them all plus all the cached symbol entries. */
+
+boolean
+NAME(aout,slurp_symbol_table) (abfd)
+     bfd *abfd;
+{
+  struct external_nlist *old_external_syms;
   aout_symbol_type *cached;
+  size_t cached_size;
 
   /* If there's no work to be done, don't do any */
-  if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
-  symbol_size = exec_hdr(abfd)->a_syms;
-  if (symbol_size == 0)
+  if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
+    return true;
+
+  old_external_syms = obj_aout_external_syms (abfd);
+
+  if (! aout_get_external_symbols (abfd))
+    return false;
+
+  if (obj_aout_external_sym_count (abfd) == 0)
     {
-      bfd_error = no_symbols;
+      bfd_set_error (bfd_error_no_symbols);
       return false;
     }
 
-  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
-  if (bfd_read ((PTR)string_chars, BYTES_IN_WORD, 1, abfd) != BYTES_IN_WORD)
-    return false;
-  string_size = GET_WORD (abfd, string_chars);
-
-  strings =(char *) bfd_alloc(abfd, string_size + 1);
-  cached = (aout_symbol_type *)
-    bfd_zalloc(abfd, (bfd_size_type)(bfd_get_symcount (abfd) * sizeof(aout_symbol_type)));
+  cached_size = (obj_aout_external_sym_count (abfd)
+                * sizeof (aout_symbol_type));
+  cached = (aout_symbol_type *) malloc (cached_size);
+  memset (cached, 0, cached_size);
 
-  /* malloc this, so we can free it if simply. The symbol caching
-     might want to allocate onto the bfd's obstack  */
-  syms = (struct external_nlist *) bfd_xmalloc(symbol_size);
-  bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
-  if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size)
+  if (cached == NULL)
     {
-    bailout:
-      if (syms)
-       free (syms);
-      if (cached)
-       bfd_release (abfd, cached);
-      if (strings)
-       bfd_release (abfd, strings);
+      bfd_set_error (bfd_error_no_memory);
       return false;
     }
 
-  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
-  if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size)
+  /* Convert from external symbol information to internal.  */
+  if (! (NAME(aout,translate_symbol_table)
+        (abfd, cached,
+         obj_aout_external_syms (abfd),
+         obj_aout_external_sym_count (abfd),
+         obj_aout_external_strings (abfd),
+         obj_aout_external_string_size (abfd),
+         false)))
     {
-      goto bailout;
+      free (cached);
+      return false;
     }
-  strings[string_size] = 0; /* Just in case. */
 
-  /* OK, now walk the new symtable, cacheing symbol properties */
-  {
-    register struct external_nlist *sym_pointer;
-    register struct external_nlist *sym_end = syms + bfd_get_symcount (abfd);
-    register aout_symbol_type *cache_ptr = cached;
+  bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd);
 
-    /* Run through table and copy values */
-    for (sym_pointer = syms, cache_ptr = cached;
-        sym_pointer < sym_end; sym_pointer ++, cache_ptr++)
-      {
-       long x = GET_WORD(abfd, sym_pointer->e_strx);
-       cache_ptr->symbol.the_bfd = abfd;
-       if (x == 0)
-         cache_ptr->symbol.name = "";
-       else if (x >= 0 && x < string_size)
-         cache_ptr->symbol.name = x + strings;
-       else
-         goto bailout;
-
-       cache_ptr->symbol.value = GET_SWORD(abfd,  sym_pointer->e_value);
-       cache_ptr->desc = bfd_h_get_16(abfd, sym_pointer->e_desc);
-       cache_ptr->other = bfd_h_get_8(abfd, sym_pointer->e_other);
-       cache_ptr->type = bfd_h_get_8(abfd,  sym_pointer->e_type);
-       cache_ptr->symbol.udata = 0;
-       translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
-      }
-  }
+  obj_aout_symbols (abfd) = cached;
 
-  obj_aout_symbols (abfd) =  cached;
-  free((PTR)syms);
+  /* It is very likely that anybody who calls this function will not
+     want the external symbol information, so if it was allocated
+     because of our call to aout_get_external_symbols, we free it up
+     right away to save space.  */
+  if (old_external_syms == (struct external_nlist *) NULL
+      && obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
+    {
+      free (obj_aout_external_syms (abfd));
+      obj_aout_external_syms (abfd) = NULL;
+    }
 
   return true;
 }
-
 \f
 /* Possible improvements:
    + look for strings matching trailing substrings of other strings
@@ -1741,6 +1891,11 @@ add_to_stringtab (abfd, str, tab)
  add_it:
   entry = (struct stringtab_entry *)
     bfd_alloc_by_size_t (abfd, sizeof (struct stringtab_entry));
+  if (!entry)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      abort();                 /* FIXME */
+    }
 
   entry->less = entry->greater = 0;
   entry->hash = hashval;
@@ -1766,7 +1921,7 @@ add_to_stringtab (abfd, str, tab)
   return entry->index;
 }
 
-static void
+static boolean
 emit_strtab (abfd, tab)
      bfd *abfd;
      struct stringtab_data *tab;
@@ -1781,11 +1936,16 @@ emit_strtab (abfd, tab)
   char buffer[BYTES_IN_WORD];
 
   PUT_WORD (abfd, tab->index, (unsigned char *) buffer);
-  bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd);
+  if (bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd) != BYTES_IN_WORD)
+    return false;
 
   for (entry = tab->output_order; entry; entry = entry->next_to_output)
     {
-      bfd_write ((PTR) entry->string, 1, strlen (entry->string) + 1, abfd);
+      size_t len = strlen (entry->string) + 1;
+
+      if (bfd_write ((PTR) entry->string, 1, len, abfd) != len)
+       return false;
+
 #ifdef GATHER_STATISTICS
       count++;
 #endif
@@ -1833,11 +1993,13 @@ emit_strtab (abfd, tab)
        }
       g->KEEPIT = (KEEPITTYPE) count;
     } */
+
+  return true;
 }
 
 boolean
-DEFUN(NAME(aout,write_syms),(abfd),
-      bfd *abfd)
+NAME(aout,write_syms) (abfd)
+     bfd *abfd;
 {
   unsigned int count ;
   asymbol **generic = bfd_get_outsymbols (abfd);
@@ -1881,21 +2043,20 @@ DEFUN(NAME(aout,write_syms),(abfd),
       g->KEEPIT = count;
     }
 
-  emit_strtab (abfd, &strtab);
-
-  return true;
+  return emit_strtab (abfd, &strtab);
 }
 
 \f
-unsigned int
-DEFUN(NAME(aout,get_symtab),(abfd, location),
-      bfd *abfd AND
-      asymbol **location)
+long
+NAME(aout,get_symtab) (abfd, location)
+     bfd *abfd;
+     asymbol **location;
 {
     unsigned int counter = 0;
     aout_symbol_type *symbase;
 
-    if (!NAME(aout,slurp_symbol_table)(abfd)) return 0;
+    if (!NAME(aout,slurp_symbol_table)(abfd))
+      return -1;
 
     for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
       *(location++) = (asymbol *)( symbase++);
@@ -1908,10 +2069,10 @@ DEFUN(NAME(aout,get_symtab),(abfd, location),
 /* Output standard relocation information to a file in target byte order. */
 
 void
-DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr),
-      bfd *abfd AND
-      arelent *g AND
-      struct reloc_std_external *natptr)
+NAME(aout,swap_std_reloc_out) (abfd, g, natptr)
+     bfd *abfd;
+     arelent *g;
+     struct reloc_std_external *natptr;
 {
   int r_index;
   asymbol *sym = *(g->sym_ptr_ptr);
@@ -2004,10 +2165,10 @@ DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr),
 /* Output extended relocation information to a file in target byte order. */
 
 void
-DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr),
-      bfd *abfd AND
-      arelent *g AND
-      register struct reloc_ext_external *natptr)
+NAME(aout,swap_ext_reloc_out) (abfd, g, natptr)
+     bfd *abfd;
+     arelent *g;
+     register struct reloc_ext_external *natptr;
 {
   int r_index;
   int r_extern;
@@ -2116,11 +2277,11 @@ DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr),
   }                                                                    \
 
 void
-DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols),
-      bfd *abfd AND
-      struct reloc_ext_external *bytes AND
-      arelent *cache_ptr AND
-      asymbol **symbols)
+NAME(aout,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols)
+     bfd *abfd;
+     struct reloc_ext_external *bytes;
+     arelent *cache_ptr;
+     asymbol **symbols;
 {
   int r_index;
   int r_extern;
@@ -2151,11 +2312,11 @@ DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols),
 }
 
 void
-DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols),
-  bfd *abfd AND
-  struct reloc_std_external *bytes AND
-  arelent *cache_ptr AND
-  asymbol **symbols)
+NAME(aout,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols)
+     bfd *abfd;
+     struct reloc_std_external *bytes;
+     arelent *cache_ptr;
+     asymbol **symbols;
 {
   int r_index;
   int r_extern;
@@ -2203,93 +2364,100 @@ DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols),
   MOVE_ADDRESS(0);
 }
 
-/* Reloc hackery */
+/* Read and swap the relocs for a section.  */
 
 boolean
-DEFUN(NAME(aout,slurp_reloc_table),(abfd, asect, symbols),
-      bfd *abfd AND
-      sec_ptr asect AND
-      asymbol **symbols)
+NAME(aout,slurp_reloc_table) (abfd, asect, symbols)
+     bfd *abfd;
+     sec_ptr asect;
+     asymbol **symbols;
 {
   unsigned int count;
   bfd_size_type reloc_size;
   PTR relocs;
   arelent *reloc_cache;
   size_t each_size;
+  unsigned int counter = 0;
+  arelent *cache_ptr;
 
-  if (asect->relocation) return true;
+  if (asect->relocation)
+    return true;
 
-  if (asect->flags & SEC_CONSTRUCTOR) return true;
+  if (asect->flags & SEC_CONSTRUCTOR)
+    return true;
 
-  if (asect == obj_datasec (abfd)) {
+  if (asect == obj_datasec (abfd))
     reloc_size = exec_hdr(abfd)->a_drsize;
-  } else if (asect == obj_textsec (abfd)) {
+  else if (asect == obj_textsec (abfd))
     reloc_size = exec_hdr(abfd)->a_trsize;
-  } else {
-    bfd_error = invalid_operation;
+  else
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
+    }
+
+  if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
     return false;
-  }
 
-  bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
   each_size = obj_reloc_entry_size (abfd);
 
   count = reloc_size / each_size;
 
+  reloc_cache = (arelent *) malloc ((size_t) (count * sizeof (arelent)));
+  if (reloc_cache == NULL && count != 0)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
+  memset (reloc_cache, 0, count * sizeof (arelent));
 
-  reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof
-                                                      (arelent)));
-  if (!reloc_cache) {
-nomem:
-    bfd_error = no_memory;
-    return false;
-  }
-
-  relocs = (PTR) bfd_alloc (abfd, reloc_size);
-  if (!relocs) {
-    bfd_release (abfd, reloc_cache);
-    goto nomem;
-  }
+  relocs = malloc (reloc_size);
+  if (relocs == NULL && reloc_size != 0)
+    {
+      free (reloc_cache);
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
 
-  if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) {
-    bfd_release (abfd, relocs);
-    bfd_release (abfd, reloc_cache);
-    bfd_error = system_call_error;
-    return false;
-  }
+  if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size)
+    {
+      free (relocs);
+      free (reloc_cache);
+      return false;
+    }
 
-  if (each_size == RELOC_EXT_SIZE) {
-    register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
-    unsigned int counter = 0;
-    arelent *cache_ptr = reloc_cache;
+  cache_ptr = reloc_cache;
+  if (each_size == RELOC_EXT_SIZE)
+    {
+      register struct reloc_ext_external *rptr =
+       (struct reloc_ext_external *) relocs;
 
-    for (; counter < count; counter++, rptr++, cache_ptr++) {
-      NAME(aout,swap_ext_reloc_in)(abfd, rptr, cache_ptr, symbols);
+      for (; counter < count; counter++, rptr++, cache_ptr++)
+       NAME(aout,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols);
     }
-  } else {
-    register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
-    unsigned int counter = 0;
-    arelent *cache_ptr = reloc_cache;
+  else
+    {
+      register struct reloc_std_external *rptr =
+       (struct reloc_std_external *) relocs;
 
-    for (; counter < count; counter++, rptr++, cache_ptr++) {
-      NAME(aout,swap_std_reloc_in)(abfd, rptr, cache_ptr, symbols);
+      for (; counter < count; counter++, rptr++, cache_ptr++)
+       NAME(aout,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols);
     }
 
-  }
+  free (relocs);
 
-  bfd_release (abfd,relocs);
   asect->relocation = reloc_cache;
-  asect->reloc_count = count;
+  asect->reloc_count = cache_ptr - reloc_cache;
+
   return true;
 }
 
-
-
 /* Write out a relocation section into an object file.  */
 
 boolean
-DEFUN(NAME(aout,squirt_out_relocs),(abfd, section),
-      bfd *abfd AND
-      asection *section)
+NAME(aout,squirt_out_relocs) (abfd, section)
+     bfd *abfd;
+     asection *section;
 {
   arelent **generic;
   unsigned char *native, *natptr;
@@ -2304,7 +2472,7 @@ DEFUN(NAME(aout,squirt_out_relocs),(abfd, section),
   natsize = each_size * count;
   native = (unsigned char *) bfd_zalloc (abfd, natsize);
   if (!native) {
-    bfd_error = no_memory;
+    bfd_set_error (bfd_error_no_memory);
     return false;
   }
 
@@ -2335,18 +2503,18 @@ DEFUN(NAME(aout,squirt_out_relocs),(abfd, section),
 }
 
 /* This is stupid.  This function should be a boolean predicate */
-unsigned int
-DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols),
-      bfd *abfd AND
-      sec_ptr section AND
-      arelent **relptr AND
-      asymbol **symbols)
+long
+NAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols)
+     bfd *abfd;
+     sec_ptr section;
+     arelent **relptr;
+     asymbol **symbols;
 {
   arelent *tblptr = section->relocation;
   unsigned int count;
 
   if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols)))
-    return 0;
+    return -1;
 
   if (section->flags & SEC_CONSTRUCTOR) {
     arelent_chain *chain = section->constructor_chain;
@@ -2357,7 +2525,6 @@ DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols),
   }
   else {
     tblptr = section->relocation;
-    if (!tblptr) return 0;
 
     for (count = 0; count++ < section->reloc_count;)
       {
@@ -2369,59 +2536,59 @@ DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols),
   return section->reloc_count;
 }
 
-unsigned int
-DEFUN(NAME(aout,get_reloc_upper_bound),(abfd, asect),
-     bfd *abfd AND
-     sec_ptr asect)
+long
+NAME(aout,get_reloc_upper_bound) (abfd, asect)
+     bfd *abfd;
+     sec_ptr asect;
 {
   if (bfd_get_format (abfd) != bfd_object) {
-    bfd_error = invalid_operation;
-    return 0;
+    bfd_set_error (bfd_error_invalid_operation);
+    return -1;
   }
   if (asect->flags & SEC_CONSTRUCTOR) {
     return (sizeof (arelent *) * (asect->reloc_count+1));
   }
 
-
   if (asect == obj_datasec (abfd))
-    return (sizeof (arelent *) *
-            ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd))
-             +1));
+    return (sizeof (arelent *)
+           * ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd))
+              + 1));
 
   if (asect == obj_textsec (abfd))
-    return (sizeof (arelent *) *
-            ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
-             +1));
+    return (sizeof (arelent *)
+           * ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
+              + 1));
 
-  bfd_error = invalid_operation;
-  return 0;
+  bfd_set_error (bfd_error_invalid_operation);
+  return -1;
 }
 
 \f
- unsigned int
-DEFUN(NAME(aout,get_symtab_upper_bound),(abfd),
-     bfd *abfd)
+long
+NAME(aout,get_symtab_upper_bound) (abfd)
+     bfd *abfd;
 {
-  if (!NAME(aout,slurp_symbol_table)(abfd)) return 0;
+  if (!NAME(aout,slurp_symbol_table)(abfd))
+    return -1;
 
   return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
 }
 
 /*ARGSUSED*/
  alent *
-DEFUN(NAME(aout,get_lineno),(ignore_abfd, ignore_symbol),
-      bfd *ignore_abfd AND
-      asymbol *ignore_symbol)
+NAME(aout,get_lineno) (ignore_abfd, ignore_symbol)
+     bfd *ignore_abfd;
+     asymbol *ignore_symbol;
 {
 return (alent *)NULL;
 }
 
 /*ARGSUSED*/
 void
-DEFUN(NAME(aout,get_symbol_info),(ignore_abfd, symbol, ret),
-      bfd *ignore_abfd AND
-      asymbol *symbol AND
-      symbol_info *ret)
+NAME(aout,get_symbol_info) (ignore_abfd, symbol, ret)
+     bfd *ignore_abfd;
+     asymbol *symbol;
+     symbol_info *ret;
 {
   bfd_symbol_info (symbol, ret);
 
@@ -2445,11 +2612,11 @@ DEFUN(NAME(aout,get_symbol_info),(ignore_abfd, symbol, ret),
 
 /*ARGSUSED*/
 void
-DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how),
-      bfd *ignore_abfd AND
-      PTR afile AND
-      asymbol *symbol AND
-      bfd_print_symbol_type how)
+NAME(aout,print_symbol) (ignore_abfd, afile, symbol, how)
+     bfd *ignore_abfd;
+     PTR afile;
+     asymbol *symbol;
+     bfd_print_symbol_type how;
 {
   FILE *file = (FILE *)afile;
 
@@ -2489,20 +2656,15 @@ DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how),
 */
 
 boolean
-DEFUN(NAME(aout,find_nearest_line),(abfd,
-                                    section,
-                                    symbols,
-                                    offset,
-                                    filename_ptr,
-                                    functionname_ptr,
-                                    line_ptr),
-      bfd *abfd AND
-      asection *section AND
-      asymbol **symbols AND
-      bfd_vma offset AND
-      CONST char **filename_ptr AND
-      CONST char **functionname_ptr AND
-      unsigned int *line_ptr)
+NAME(aout,find_nearest_line)
+     (abfd, section, symbols, offset, filename_ptr, functionname_ptr, line_ptr)
+     bfd *abfd;
+     asection *section;
+     asymbol **symbols;
+     bfd_vma offset;
+     CONST char **filename_ptr;
+     CONST char **functionname_ptr;
+     unsigned int *line_ptr;
 {
   /* Run down the file looking for the filename, function and linenumber */
   asymbol **p;
@@ -2566,7 +2728,18 @@ DEFUN(NAME(aout,find_nearest_line),(abfd,
          if (*line_ptr && func) {
            CONST char *function = func->name;
            char *p;
-           strncpy(buffer, function, sizeof(buffer)-1);
+
+           /* The caller expects a symbol name.  We actually have a
+              function name, without the leading underscore.  Put the
+              underscore back in, so that the caller gets a symbol
+              name.  */
+           if (bfd_get_symbol_leading_char (abfd) == '\0')
+             strncpy (buffer, function, sizeof (buffer) - 1);
+           else
+             {
+               buffer[0] = bfd_get_symbol_leading_char (abfd);
+               strncpy (buffer + 1, function, sizeof (buffer) - 2);
+             }
            buffer[sizeof(buffer)-1] = 0;
            /* Have to remove : stuff */
            p = strchr(buffer,':');
@@ -2599,12 +2772,35 @@ DEFUN(NAME(aout,find_nearest_line),(abfd,
 
 /*ARGSUSED*/
 int
-DEFUN(NAME(aout,sizeof_headers),(abfd, execable),
-      bfd *abfd AND
-      boolean execable)
+NAME(aout,sizeof_headers) (abfd, execable)
+     bfd *abfd;
+     boolean execable;
 {
   return adata(abfd).exec_bytes_size;
 }
+
+/* Free all information we have cached for this BFD.  We can always
+   read it again later if we need it.  */
+
+boolean
+NAME(aout,bfd_free_cached_info) (abfd)
+     bfd *abfd;
+{
+  asection *o;
+
+  if (bfd_get_format (abfd) != bfd_object)
+    return true;
+
+#define FREE(x) if (x != NULL) { free (x); x = NULL; }
+  FREE (obj_aout_symbols (abfd));
+  FREE (obj_aout_external_syms (abfd));
+  FREE (obj_aout_external_strings (abfd));
+  for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+    FREE (o->relocation);
+#undef FREE
+
+  return true;
+}
 \f
 /* a.out link code.  */
 
@@ -2632,7 +2828,6 @@ static boolean aout_link_add_object_symbols
   PARAMS ((bfd *, struct bfd_link_info *));
 static boolean aout_link_check_archive_element
   PARAMS ((bfd *, struct bfd_link_info *, boolean *));
-static boolean aout_link_get_symbols PARAMS ((bfd *));
 static boolean aout_link_free_symbols PARAMS ((bfd *));
 static boolean aout_link_check_ar_symbols
   PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded));
@@ -2654,14 +2849,19 @@ aout_link_hash_newfunc (entry, table, string)
   if (ret == (struct aout_link_hash_entry *) NULL)
     ret = ((struct aout_link_hash_entry *)
           bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry)));
+  if (ret == (struct aout_link_hash_entry *) NULL)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return (struct bfd_hash_entry *) ret;
+    }
 
   /* Call the allocation method of the superclass.  */
   ret = ((struct aout_link_hash_entry *)
         _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
                                 table, string));
-
-  /* Set local fields.  */
-  ret->indx = -1;
+  if (ret)
+    /* Set local fields.  */
+    ret->indx = -1;
 
   return (struct bfd_hash_entry *) ret;
 }
@@ -2675,7 +2875,12 @@ NAME(aout,link_hash_table_create) (abfd)
   struct aout_link_hash_table *ret;
 
   ret = ((struct aout_link_hash_table *)
-        bfd_xmalloc (sizeof (struct aout_link_hash_table)));
+        malloc (sizeof (struct aout_link_hash_table)));
+  if (ret == (struct aout_link_hash_table *) NULL)
+      {
+       bfd_set_error (bfd_error_no_memory);
+       return (struct bfd_link_hash_table *) NULL;
+      }
   if (! _bfd_link_hash_table_init (&ret->root, abfd,
                                   aout_link_hash_newfunc))
     {
@@ -2720,7 +2925,7 @@ NAME(aout,link_add_symbols) (abfd, info)
       return _bfd_generic_link_add_archive_symbols
        (abfd, info, aout_link_check_archive_element);
     default:
-      bfd_error = wrong_format;
+      bfd_set_error (bfd_error_wrong_format);
       return false;
     }
 }
@@ -2732,7 +2937,7 @@ aout_link_add_object_symbols (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
-  if (! aout_link_get_symbols (abfd))
+  if (! aout_get_external_symbols (abfd))
     return false;
   if (! aout_link_add_symbols (abfd, info))
     return false;
@@ -2755,7 +2960,7 @@ aout_link_check_archive_element (abfd, info, pneeded)
      struct bfd_link_info *info;
      boolean *pneeded;
 {
-  if (! aout_link_get_symbols (abfd))
+  if (! aout_get_external_symbols (abfd))
     return false;
 
   if (! aout_link_check_ar_symbols (abfd, info, pneeded))
@@ -2780,59 +2985,6 @@ aout_link_check_archive_element (abfd, info, pneeded)
   return true;
 }
 
-/* Read the internal symbols from an a.out file.  */
-
-static boolean
-aout_link_get_symbols (abfd)
-     bfd *abfd;
-{
-  bfd_size_type count;
-  struct external_nlist *syms;
-  unsigned char string_chars[BYTES_IN_WORD];
-  bfd_size_type stringsize;
-  char *strings;
-
-  if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
-    {
-      /* We already have them.  */
-      return true;
-    }
-
-  count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE;
-
-  /* We allocate using bfd_xmalloc to make the values easy to free
-     later on.  If we put them on the obstack it might not be possible
-     to free them.  */
-  syms = ((struct external_nlist *)
-         bfd_xmalloc ((size_t) count * EXTERNAL_NLIST_SIZE));
-
-  if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
-      || (bfd_read ((PTR) syms, 1, exec_hdr (abfd)->a_syms, abfd)
-         != exec_hdr (abfd)->a_syms))
-    return false;
-
-  /* Get the size of the strings.  */
-  if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
-      || (bfd_read ((PTR) string_chars, BYTES_IN_WORD, 1, abfd)
-         != BYTES_IN_WORD))
-    return false;
-  stringsize = GET_WORD (abfd, string_chars);
-  strings = (char *) bfd_xmalloc ((size_t) stringsize);
-
-  /* Skip space for the string count in the buffer for convenience
-     when using indexes.  */
-  if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD, abfd)
-      != stringsize - BYTES_IN_WORD)
-    return false;
-
-  /* Save the data.  */
-  obj_aout_external_syms (abfd) = syms;
-  obj_aout_external_sym_count (abfd) = count;
-  obj_aout_external_strings (abfd) = strings;
-
-  return true;
-}
-
 /* Free up the internal symbols read from an a.out file.  */
 
 static boolean
@@ -2883,7 +3035,12 @@ aout_link_check_ar_symbols (abfd, info, pneeded)
 
       /* Ignore symbols that are not externally visible.  */
       if ((type & N_EXT) == 0)
-       continue;
+       {
+         if (type == N_WARNING
+             || type == N_INDR)
+           ++p;
+         continue;
+       }
 
       name = strings + GET_WORD (abfd, p->e_strx);
       h = bfd_link_hash_lookup (info->hash, name, false, false, true);
@@ -2893,9 +3050,17 @@ aout_link_check_ar_symbols (abfd, info, pneeded)
       if (h == (struct bfd_link_hash_entry *) NULL
          || (h->type != bfd_link_hash_undefined
              && h->type != bfd_link_hash_common))
-       continue;
+       {
+         if (type == (N_INDR | N_EXT))
+           ++p;
+         continue;
+       }
 
-      if ((type & (N_TEXT | N_DATA | N_BSS)) != 0)
+      if (type == (N_TEXT | N_EXT)
+         || type == (N_DATA | N_EXT)
+         || type == (N_BSS | N_EXT)
+         || type == (N_ABS | N_EXT)
+         || type == (N_INDR | N_EXT))
        {
          /* This object file defines this symbol.  We must link it
             in.  This is true regardless of whether the current
@@ -2912,7 +3077,7 @@ aout_link_check_ar_symbols (abfd, info, pneeded)
          return true;
        }
 
-      if (type == (N_EXT | N_UNDF))
+      if (type == (N_UNDF | N_EXT))
        {
          bfd_vma value;
 
@@ -2990,6 +3155,11 @@ aout_link_add_symbols (abfd, info)
              bfd_alloc (abfd,
                         ((size_t) sym_count
                          * sizeof (struct aout_link_hash_entry *))));
+  if (!sym_hash)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
   obj_aout_sym_hashes (abfd) = sym_hash;
 
   p = obj_aout_external_syms (abfd);
@@ -3023,7 +3193,10 @@ aout_link_add_symbols (abfd, info)
             which is the symbol to indirect to (actually, an N_INDR
             symbol without N_EXT set is pretty useless).  */
          if (type == N_INDR)
-           ++p;
+           {
+             ++p;
+             ++sym_hash;
+           }
          continue;
        }
 
@@ -3072,21 +3245,21 @@ aout_link_add_symbols (abfd, info)
        case N_COMM | N_EXT:
          section = &bfd_com_section;
          break;
-       case N_SETA:
+       case N_SETA: case N_SETA | N_EXT:
          section = &bfd_abs_section;
          flags |= BSF_CONSTRUCTOR;
          break;
-       case N_SETT:
+       case N_SETT: case N_SETT | N_EXT:
          section = obj_textsec (abfd);
          flags |= BSF_CONSTRUCTOR;
          value -= bfd_get_section_vma (abfd, section);
          break;
-       case N_SETD:
+       case N_SETD: case N_SETD | N_EXT:
          section = obj_datasec (abfd);
          flags |= BSF_CONSTRUCTOR;
          value -= bfd_get_section_vma (abfd, section);
          break;
-       case N_SETB:
+       case N_SETB: case N_SETB | N_EXT:
          section = obj_bsssec (abfd);
          flags |= BSF_CONSTRUCTOR;
          value -= bfd_get_section_vma (abfd, section);
@@ -3105,8 +3278,11 @@ aout_link_add_symbols (abfd, info)
 
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, name, flags, section, value, string, copy, false,
-             ARCH_SIZE, (struct bfd_link_hash_entry **) sym_hash)))
+             (struct bfd_link_hash_entry **) sym_hash)))
        return false;
+
+      if (type == (N_INDR | N_EXT) || type == N_WARNING)
+       ++sym_hash;
     }
 
   return true;
@@ -3149,6 +3325,9 @@ static boolean aout_link_input_section_ext
           bfd_size_type rel_size, bfd_byte *contents, int *symbol_map));
 static INLINE asection *aout_reloc_index_to_section
   PARAMS ((bfd *, int));
+static boolean aout_link_reloc_link_order
+  PARAMS ((struct aout_final_link_info *, asection *,
+          struct bfd_link_order *));
 
 /* Do the final link step.  This is called on the output BFD.  The
    INFO structure should point to a list of BFDs linked through the
@@ -3169,6 +3348,7 @@ NAME(aout,final_link) (abfd, info, callback)
   file_ptr text_end;
   register struct bfd_link_order *p;
   asection *o;
+  boolean have_link_order_relocs;
 
   aout_info.info = info;
   aout_info.output_bfd = abfd;
@@ -3201,10 +3381,18 @@ NAME(aout,final_link) (abfd, info, callback)
              abort ();
            }
        }
+      trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
+                                              ->link_order_head)
+                * obj_reloc_entry_size (abfd));
       exec_hdr (abfd)->a_trsize = trsize;
+      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_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.  */
@@ -3255,19 +3443,13 @@ NAME(aout,final_link) (abfd, info, callback)
   for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
     sub->output_has_begun = false;
 
+  have_link_order_relocs = false;
   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
     {
       for (p = o->link_order_head;
           p != (struct bfd_link_order *) NULL;
           p = p->next)
        {
-         /* If we might be using the C based alloca function, we need
-            to dump the memory allocated by aout_link_input_bfd.  */
-#ifndef __GNUC__
-#ifndef alloca
-         (void) alloca (0);
-#endif
-#endif
          if (p->type == bfd_indirect_link_order
              && (bfd_get_flavour (p->u.indirect.section->owner)
                  == bfd_target_aout_flavour))
@@ -3282,6 +3464,12 @@ NAME(aout,final_link) (abfd, info, callback)
                  input_bfd->output_has_begun = true;
                }
            }
+         else if (p->type == bfd_section_reloc_link_order
+                  || p->type == bfd_symbol_reloc_link_order)
+           {
+             /* These are handled below.  */
+             have_link_order_relocs = true;
+           }
          else
            {
              if (! _bfd_default_link_order (abfd, info, o, p))
@@ -3295,6 +3483,28 @@ NAME(aout,final_link) (abfd, info, callback)
                           aout_link_write_other_symbol,
                           (PTR) &aout_info);
 
+  /* Now handle any relocs we were asked to create by the linker.
+     These did not come from any input file.  We must do these after
+     we have written out all the symbols, so that we know the symbol
+     indices to use.  */
+  if (have_link_order_relocs)
+    {
+      for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+       {
+         for (p = o->link_order_head;
+              p != (struct bfd_link_order *) NULL;
+              p = p->next)
+           {
+             if (p->type == bfd_section_reloc_link_order
+                 || p->type == bfd_symbol_reloc_link_order)
+               {
+                 if (! aout_link_reloc_link_order (&aout_info, o, p))
+                   return false;
+               }
+           }
+       }
+    }
+
   /* Update the header information.  */
   abfd->symcount = obj_aout_external_sym_count (abfd);
   exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE;
@@ -3307,9 +3517,7 @@ 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;
-  emit_strtab (abfd, &aout_info.strtab);
-
-  return true;
+  return emit_strtab (abfd, &aout_info.strtab);
 }
 
 /* Link an a.out input BFD into the output file.  */
@@ -3320,21 +3528,26 @@ aout_link_input_bfd (finfo, input_bfd)
      bfd *input_bfd;
 {
   bfd_size_type sym_count;
-  int *symbol_map;
+  int *symbol_map = NULL;
 
   BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
 
   /* Get the symbols.  We probably have them already, unless
      finfo->info->keep_memory is false.  */
-  if (! aout_link_get_symbols (input_bfd))
+  if (! aout_get_external_symbols (input_bfd))
     return false;
 
   sym_count = obj_aout_external_sym_count (input_bfd);
-  symbol_map = (int *) alloca ((size_t) sym_count * sizeof (int));
+  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))
-    return false;
+    goto error_return;
 
   /* Relocate and write out the sections.  */
   if (! aout_link_input_section (finfo, input_bfd,
@@ -3347,7 +3560,7 @@ aout_link_input_bfd (finfo, input_bfd)
                                    &finfo->dreloff,
                                    exec_hdr (input_bfd)->a_drsize,
                                    symbol_map))
-    return false;
+    goto error_return;
 
   /* 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
@@ -3355,10 +3568,16 @@ aout_link_input_bfd (finfo, input_bfd)
   if (! finfo->info->keep_memory)
     {
       if (! aout_link_free_symbols (input_bfd))
-       return false;
+       goto error_return;
     }
 
+  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
@@ -3375,12 +3594,13 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
   char *strings;
   enum bfd_link_strip strip;
   enum bfd_link_discard discard;
-  struct external_nlist *output_syms;
+  struct external_nlist *output_syms = NULL;
   struct external_nlist *outsym;
   register struct external_nlist *sym;
   struct external_nlist *sym_end;
   struct aout_link_hash_entry **sym_hash;
   boolean pass;
+  boolean skip_indirect;
 
   output_bfd = finfo->output_bfd;
   sym_count = obj_aout_external_sym_count (input_bfd);
@@ -3388,7 +3608,12 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
   strip = finfo->info->strip;
   discard = finfo->info->discard;
   output_syms = ((struct external_nlist *)
-                alloca ((size_t) (sym_count + 1) * EXTERNAL_NLIST_SIZE));
+                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;
 
   /* First write out a symbol for this object file, unless we are
@@ -3407,13 +3632,16 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
                                  &finfo->strtab),
                outsym->e_strx);
       PUT_WORD (output_bfd,
-               bfd_get_section_vma (input_bfd, obj_textsec (input_bfd)),
+               (bfd_get_section_vma (output_bfd,
+                                     obj_textsec (input_bfd)->output_section)
+                + obj_textsec (input_bfd)->output_offset),
                outsym->e_value);
       ++obj_aout_external_sym_count (output_bfd);
       ++outsym;
     }
 
   pass = false;
+  skip_indirect = false;
   sym = obj_aout_external_syms (input_bfd);
   sym_end = sym + sym_count;
   sym_hash = obj_aout_sym_hashes (input_bfd);
@@ -3421,6 +3649,7 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
     {
       const char *name;
       int type;
+      struct aout_link_hash_entry *h;
       boolean skip;
       asection *symsec;
       bfd_vma val = 0;
@@ -3430,15 +3659,26 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
       type = bfd_h_get_8 (input_bfd, sym->e_type);
       name = strings + GET_WORD (input_bfd, sym->e_strx);
 
+      h = NULL;
+
       if (pass)
        {
-         /* Pass this symbol through.  */
+         /* Pass this symbol through.  It is the target of an
+            indirect or warning symbol.  */
          val = GET_WORD (input_bfd, sym->e_value);
          pass = false;
        }
+      else if (skip_indirect)
+       {
+         /* Skip this symbol, which is the target of an indirect
+            symbol that we have changed to no longer be an indirect
+            symbol.  */
+         skip_indirect = false;
+         continue;
+       }
       else
        {
-         struct aout_link_hash_entry *h;
+         struct aout_link_hash_entry *hresolve;
 
          /* We have saved the hash table entry for this symbol, if
             there is one.  Note that we could just look it up again
@@ -3446,6 +3686,22 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
             external symbol. */
          h = *sym_hash;
 
+         /* If this is an indirect or warning symbol, then change
+            hresolve to the base symbol.  We also change *sym_hash so
+            that the relocation routines relocate against the real
+            symbol.  */
+         hresolve = h;
+         if (h != (struct aout_link_hash_entry *) NULL
+             && (h->root.type == bfd_link_hash_indirect
+                 || h->root.type == bfd_link_hash_warning))
+           {
+             hresolve = (struct aout_link_hash_entry *) h->root.u.i.link;
+             while (hresolve->root.type == bfd_link_hash_indirect)
+               hresolve = ((struct aout_link_hash_entry *)
+                           hresolve->root.u.i.link);
+             *sym_hash = hresolve;
+           }
+
          /* If the symbol has already been written out, skip it.  */
          if (h != (struct aout_link_hash_entry *) NULL
              && h->root.written)
@@ -3489,10 +3745,17 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
            symsec = obj_bsssec (input_bfd);
          else if ((type & N_TYPE) == N_ABS)
            symsec = &bfd_abs_section;
-         else if ((type & N_TYPE) == N_INDR
+         else if (((type & N_TYPE) == N_INDR
+                   && (hresolve == (struct aout_link_hash_entry *) NULL
+                       || (hresolve->root.type != bfd_link_hash_defined
+                           && hresolve->root.type != bfd_link_hash_common)))
                   || type == N_WARNING)
            {
-             /* Pass the next symbol through unchanged.  */
+             /* Pass the next symbol through unchanged.  The
+                condition above for indirect symbols is so that if
+                the indirect symbol was defined, we output it with
+                the correct definition so the debugger will
+                understand it.  */
              pass = true;
              val = GET_WORD (input_bfd, sym->e_value);
              symsec = NULL;
@@ -3504,20 +3767,32 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
            }
          else
            {
+             /* If we get here with an indirect symbol, it means that
+                we are outputting it with a real definition.  In such
+                a case we do not want to output the next symbol,
+                which is the target of the indirection.  */
+             if ((type & N_TYPE) == N_INDR)
+               skip_indirect = true;
+
+             /* We need to get the value from the hash table.  We use
+                hresolve so that if we have defined an indirect
+                symbol we output the final definition.  */
              if (h == (struct aout_link_hash_entry *) NULL)
                val = 0;
-             else if (h->root.type == bfd_link_hash_defined)
+             else if (hresolve->root.type == bfd_link_hash_defined)
                {
+                 asection *input_section;
                  asection *output_section;
 
                  /* This case means a common symbol which was turned
                     into a defined symbol.  */
-                 output_section = h->root.u.def.section->output_section;
+                 input_section = hresolve->root.u.def.section;
+                 output_section = input_section->output_section;
                  BFD_ASSERT (output_section == &bfd_abs_section
                              || output_section->owner == output_bfd);
-                 val = (h->root.u.def.value
+                 val = (hresolve->root.u.def.value
                         + bfd_get_section_vma (output_bfd, output_section)
-                        + h->root.u.def.section->output_offset);
+                        + input_section->output_offset);
 
                  /* Get the correct type based on the section.  If
                     this is a constructed set, force it to be
@@ -3539,8 +3814,8 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
                  else
                    type |= N_ABS;
                }
-             else if (h->root.type == bfd_link_hash_common)
-               val = h->root.u.c.size;
+             else if (hresolve->root.type == bfd_link_hash_common)
+               val = hresolve->root.u.c.size;
              else
                val = 0;
 
@@ -3591,6 +3866,22 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
                   outsym->e_other);
       bfd_h_put_16 (output_bfd, bfd_h_get_16 (input_bfd, sym->e_desc),
                    outsym->e_desc);
+      if (! finfo->info->keep_memory)
+       {
+         /* name points into a string table which we are going to
+            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;
+         else
+           {
+             char *n;
+
+             n = bfd_alloc (output_bfd, strlen (name) + 1);
+             strcpy (n, name);
+             name = n;
+           }
+       }
       PUT_WORD (output_bfd,
                add_to_stringtab (output_bfd, name, &finfo->strtab),
                outsym->e_strx);
@@ -3606,16 +3897,22 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
       bfd_size_type outsym_count;
 
       if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0)
-       return false;
+       goto error_return;
       outsym_count = outsym - output_syms;
       if (bfd_write ((PTR) output_syms, (bfd_size_type) EXTERNAL_NLIST_SIZE,
                     (bfd_size_type) outsym_count, output_bfd)
          != outsym_count * EXTERNAL_NLIST_SIZE)
-       return false;
+       goto error_return;
       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
@@ -3635,6 +3932,14 @@ aout_link_write_other_symbol (h, data)
   if (h->root.written)
     return true;
 
+  h->root.written = true;
+
+  if (finfo->info->strip == strip_all
+      || (finfo->info->strip == strip_some
+         && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string,
+                             false, false) == NULL))
+    return true;
+
   output_bfd = finfo->output_bfd;
 
   switch (h->root.type)
@@ -3715,21 +4020,31 @@ aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
      int *symbol_map;
 {
   bfd_size_type input_size;
-  bfd_byte *contents;
-  PTR relocs;
+  bfd_byte *contents = NULL;
+  PTR relocs = NULL;
 
   /* Get the section contents.  */
   input_size = bfd_section_size (input_bfd, input_section);
-  contents = (bfd_byte *) alloca (input_size);
+  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,
                                  (file_ptr) 0, input_size))
-    return false;
+    goto error_return;
 
   /* Read in the relocs.  */
-  relocs = (PTR) alloca (rel_size);
+  relocs = (PTR) malloc (rel_size);
+  if (relocs == NULL && rel_size != 0)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
   if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
       || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size)
-    return false;
+    goto error_return;
 
   /* Relocate the section contents.  */
   if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
@@ -3737,14 +4052,14 @@ 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))
-       return false;
+       goto error_return;
     }
   else
     {
       if (! aout_link_input_section_ext (finfo, input_bfd, input_section,
                                         (struct reloc_ext_external *) relocs,
                                         rel_size, contents, symbol_map))
-       return false;
+       goto error_return;
     }
 
   /* Write out the section contents.  */
@@ -3753,17 +4068,17 @@ aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
                                  (PTR) contents,
                                  input_section->output_offset,
                                  input_size))
-    return false;
+    goto error_return;
 
   /* 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)
-       return false;
+       goto error_return;
       if (bfd_write (relocs, (bfd_size_type) 1, rel_size, finfo->output_bfd)
          != rel_size)
-       return false;
+       goto error_return;
       *reloff_ptr += rel_size;
 
       /* Assert that the relocs have not run into the symbols, and
@@ -3775,7 +4090,17 @@ aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
                          <= obj_datasec (finfo->output_bfd)->rel_filepos)));
     }
 
+  if (relocs != NULL)
+    free (relocs);
+  if (contents != NULL)
+    free (contents);
   return true;
+ error_return:
+  if (relocs != NULL)
+    free (relocs);
+  if (contents != NULL)
+    free (contents);
+  return false;
 }
 
 /* Get the section corresponding to a reloc index.  */
@@ -3794,6 +4119,7 @@ aout_reloc_index_to_section (abfd, indx)
     case N_BSS:
       return obj_bsssec (abfd);
     case N_ABS:
+    case N_UNDF:
       return &bfd_abs_section;
     default:
       abort ();
@@ -4046,9 +4372,24 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
            case bfd_reloc_outofrange:
              abort ();
            case bfd_reloc_overflow:
-             if (! ((*finfo->info->callbacks->reloc_overflow)
-                    (finfo->info, input_bfd, input_section, r_addr)))
-               return false;
+             {
+               const char *name;
+
+               if (r_extern)
+                 name = strings + GET_WORD (input_bfd,
+                                            syms[r_index].e_strx);
+               else
+                 {
+                   asection *s;
+
+                   s = aout_reloc_index_to_section (input_bfd, r_index);
+                   name = bfd_section_name (input_bfd, s);
+                 }
+               if (! ((*finfo->info->callbacks->reloc_overflow)
+                      (finfo->info, name, howto_table_std[howto_idx].name,
+                       (bfd_vma) 0, input_bfd, input_section, r_addr)))
+                 return false;
+             }
              break;
            }
        }
@@ -4332,9 +4673,24 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
                case bfd_reloc_outofrange:
                  abort ();
                case bfd_reloc_overflow:
-                 if (! ((*finfo->info->callbacks->reloc_overflow)
-                        (finfo->info, input_bfd, input_section, r_addr)))
-                   return false;
+                 {
+                   const char *name;
+
+                   if (r_extern)
+                     name = strings + GET_WORD (input_bfd,
+                                                syms[r_index].e_strx);
+                   else
+                     {
+                       asection *s;
+
+                       s = aout_reloc_index_to_section (input_bfd, r_index);
+                       name = bfd_section_name (input_bfd, s);
+                     }
+                   if (! ((*finfo->info->callbacks->reloc_overflow)
+                          (finfo->info, name, howto_table_ext[r_type].name,
+                           r_addend, input_bfd, input_section, r_addr)))
+                     return false;
+                 }
                  break;
                }
            }
@@ -4343,3 +4699,211 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
 
   return true;
 }
+
+/* Handle a link order which is supposed to generate a reloc.  */
+
+static boolean
+aout_link_reloc_link_order (finfo, o, p)
+     struct aout_final_link_info *finfo;
+     asection *o;
+     struct bfd_link_order *p;
+{
+  struct bfd_link_order_reloc *pr;
+  int r_index;
+  int r_extern;
+  const reloc_howto_type *howto;
+  file_ptr *reloff_ptr;
+  struct reloc_std_external srel;
+  struct reloc_ext_external erel;
+  PTR rel_ptr;
+
+  pr = p->u.reloc.p;
+
+  if (p->type == bfd_section_reloc_link_order)
+    {
+      r_extern = 0;
+      if (pr->u.section == &bfd_abs_section)
+       r_index = N_ABS | N_EXT;
+      else
+       {
+         BFD_ASSERT (pr->u.section->owner == finfo->output_bfd);
+         r_index = pr->u.section->target_index;
+       }
+    }
+  else
+    {
+      struct aout_link_hash_entry *h;
+
+      BFD_ASSERT (p->type == bfd_symbol_reloc_link_order);
+      r_extern = 1;
+      h = aout_link_hash_lookup (aout_hash_table (finfo->info),
+                                pr->u.name, false, false, true);
+      if (h != (struct aout_link_hash_entry *) NULL
+         && h->indx == -1)
+       r_index = h->indx;
+      else
+       {
+         if (! ((*finfo->info->callbacks->unattached_reloc)
+                (finfo->info, pr->u.name, (bfd *) NULL,
+                 (asection *) NULL, (bfd_vma) 0)))
+           return false;
+         r_index = 0;
+       }
+    }
+
+  howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc);
+  if (howto == (const reloc_howto_type *) NULL)
+    {
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+
+  if (o == obj_textsec (finfo->output_bfd))
+    reloff_ptr = &finfo->treloff;
+  else if (o == obj_datasec (finfo->output_bfd))
+    reloff_ptr = &finfo->dreloff;
+  else
+    abort ();
+
+  if (obj_reloc_entry_size (finfo->output_bfd) == RELOC_STD_SIZE)
+    {
+      int r_pcrel;
+      int r_baserel;
+      int r_jmptable;
+      int r_relative;
+      int r_length;
+
+      r_pcrel = howto->pc_relative;
+      r_baserel = (howto->type & 8) != 0;
+      r_jmptable = 0;
+      r_relative = 0;
+      r_length = howto->size;
+
+      PUT_WORD (finfo->output_bfd, p->offset, srel.r_address);
+      if (finfo->output_bfd->xvec->header_byteorder_big_p)
+       {
+         srel.r_index[0] = r_index >> 16;
+         srel.r_index[1] = r_index >> 8;
+         srel.r_index[2] = r_index;
+         srel.r_type[0] =
+           ((r_extern ?     RELOC_STD_BITS_EXTERN_BIG : 0)
+            | (r_pcrel ?    RELOC_STD_BITS_PCREL_BIG : 0)
+            | (r_baserel ?  RELOC_STD_BITS_BASEREL_BIG : 0)
+            | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
+            | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
+            | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG));
+       }
+      else
+       {
+         srel.r_index[2] = r_index >> 16;
+         srel.r_index[1] = r_index >> 8;
+         srel.r_index[0] = r_index;
+         srel.r_type[0] =
+           ((r_extern ?     RELOC_STD_BITS_EXTERN_LITTLE : 0)
+            | (r_pcrel ?    RELOC_STD_BITS_PCREL_LITTLE : 0)
+            | (r_baserel ?  RELOC_STD_BITS_BASEREL_LITTLE : 0)
+            | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
+            | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
+            | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE));
+       }
+
+      rel_ptr = (PTR) &srel;
+
+      /* We have to write the addend into the object file, since
+        standard a.out relocs are in place.  It would be more
+        reliable if we had the current contents of the file here,
+        rather than assuming zeroes, but we can't read the file since
+        it was opened using bfd_openw.  */
+      if (pr->addend != 0)
+       {
+         bfd_size_type size;
+         bfd_reloc_status_type r;
+         bfd_byte *buf;
+         boolean ok;
+
+         size = bfd_get_reloc_size (howto);
+         buf = (bfd_byte*) bfd_zmalloc (size);
+         if (buf == (bfd_byte *) NULL)
+           {
+             bfd_set_error (bfd_error_no_memory);
+             return false;
+           }
+         r = _bfd_relocate_contents (howto, finfo->output_bfd,
+                                     pr->addend, buf);
+         switch (r)
+           {
+           case bfd_reloc_ok:
+             break;
+           default:
+           case bfd_reloc_outofrange:
+             abort ();
+           case bfd_reloc_overflow:
+             if (! ((*finfo->info->callbacks->reloc_overflow)
+                    (finfo->info,
+                     (p->type == bfd_section_reloc_link_order
+                      ? bfd_section_name (finfo->output_bfd,
+                                          pr->u.section)
+                      : pr->u.name),
+                     howto->name, pr->addend, (bfd *) NULL,
+                     (asection *) NULL, (bfd_vma) 0)))
+               {
+                 free (buf);
+                 return false;
+               }
+             break;
+           }
+         ok = bfd_set_section_contents (finfo->output_bfd, o,
+                                        (PTR) buf,
+                                        (file_ptr) p->offset,
+                                        size);
+         free (buf);
+         if (! ok)
+           return false;
+       }
+    }
+  else
+    {
+      PUT_WORD (finfo->output_bfd, p->offset, erel.r_address);
+
+      if (finfo->output_bfd->xvec->header_byteorder_big_p)
+       {
+         erel.r_index[0] = r_index >> 16;
+         erel.r_index[1] = r_index >> 8;
+         erel.r_index[2] = r_index;
+         erel.r_type[0] =
+           ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
+            | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG));
+       }
+      else
+       {
+         erel.r_index[2] = r_index >> 16;
+         erel.r_index[1] = r_index >> 8;
+         erel.r_index[0] = r_index;
+         erel.r_type[0] =
+           (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
+             | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
+       }
+
+      PUT_WORD (finfo->output_bfd, pr->addend, erel.r_addend);
+
+      rel_ptr = (PTR) &erel;
+    }
+
+  if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0
+      || (bfd_write (rel_ptr, (bfd_size_type) 1,
+                    obj_reloc_entry_size (finfo->output_bfd),
+                    finfo->output_bfd)
+         != obj_reloc_entry_size (finfo->output_bfd)))
+    return false;
+
+  *reloff_ptr += obj_reloc_entry_size (finfo->output_bfd);
+
+  /* Assert that the relocs have not run into the symbols, and that n
+     the text relocs have not run into the data relocs.  */
+  BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd)
+             && (reloff_ptr != &finfo->treloff
+                 || (*reloff_ptr
+                     <= obj_datasec (finfo->output_bfd)->rel_filepos)));
+
+  return true;
+}
This page took 0.062512 seconds and 4 git commands to generate.