]> Git Repo - binutils.git/blobdiff - bfd/aoutx.h
* elf.c (_bfd_elf_make_section_from_shdr): New function, based on
[binutils.git] / bfd / aoutx.h
index d46d387c0a1e550a0a43e03c70d482dbeef64bc7..c65924d0c8faa5075e0b99d85e11516065586711 100644 (file)
@@ -121,7 +121,6 @@ DESCRIPTION
 #define KEEPIT flags
 #define KEEPITTYPE int
 
-#include <assert.h>
 #include <string.h>            /* For strchr and friends */
 #include "bfd.h"
 #include <sysdep.h>
@@ -133,11 +132,7 @@ DESCRIPTION
 #include "aout/stab_gnu.h"
 #include "aout/ar.h"
 
-static boolean translate_symbol_table PARAMS ((bfd *, aout_symbol_type *,
-                                              struct external_nlist *,
-                                              bfd_size_type, char *,
-                                              bfd_size_type,
-                                              boolean dynamic));
+static boolean aout_get_external_symbols PARAMS ((bfd *));
 
 /*
 SUBSECTION
@@ -202,6 +197,29 @@ HOWTO( 7,         0,  4,   64, true,  0, complain_overflow_signed,  0,"DISP64",    tr
 { -1 },
 HOWTO( 9,             0,  1,   16, false, 0, complain_overflow_bitfield,0,"BASE16",    false,0xffffffff,0xffffffff, false),
 HOWTO(10,             0,  2,   32, false, 0, complain_overflow_bitfield,0,"BASE32",    false,0xffffffff,0xffffffff, false),
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+  HOWTO(16,           0,  2,    0, false, 0, complain_overflow_bitfield,0,"JMP_TABLE", false,         0,0x00000000, false),
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 },
+  HOWTO(32,           0,  2,    0, false, 0, complain_overflow_bitfield,0,"RELATIVE",  false,         0,0x00000000, false),
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+{ -1 },
+  HOWTO(40,           0,  2,    0, false, 0, complain_overflow_bitfield,0,"BASEREL",   false,         0,0x00000000, false),
 };
 
 #define TABLE_SIZE(TABLE)      (sizeof(TABLE)/sizeof(TABLE[0]))
@@ -338,7 +356,23 @@ NAME(aout,swap_exec_header_out) (abfd, execp, raw_bytes)
   PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
 }
 
+/* Make all the section for an a.out file.  */
 
+boolean
+NAME(aout,make_sections) (abfd)
+     bfd *abfd;
+{
+  if (obj_textsec (abfd) == (asection *) NULL
+      && bfd_make_section (abfd, ".text") == (asection *) NULL)
+    return false;
+  if (obj_datasec (abfd) == (asection *) NULL
+      && bfd_make_section (abfd, ".data") == (asection *) NULL)
+    return false;
+  if (obj_bsssec (abfd) == (asection *) NULL
+      && bfd_make_section (abfd, ".bss") == (asection *) NULL)
+    return false;
+  return true;
+}
 
 /*
 FUNCTION
@@ -424,18 +458,8 @@ NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p)
   obj_aout_external_strings (abfd) = NULL;
   obj_aout_sym_hashes (abfd) = NULL;
 
-  /* Create the sections.  This is raunchy, but bfd_close wants to reclaim
-     them.  */
-
-  obj_textsec (abfd) = bfd_make_section_old_way (abfd, ".text");
-  obj_datasec (abfd) = bfd_make_section_old_way (abfd, ".data");
-  obj_bsssec (abfd) = bfd_make_section_old_way (abfd, ".bss");
-
-#if 0
-  (void)bfd_make_section (abfd, ".text");
-  (void)bfd_make_section (abfd, ".data");
-  (void)bfd_make_section (abfd, ".bss");
-#endif
+  if (! NAME(aout,make_sections) (abfd))
+    return NULL;
 
   obj_datasec (abfd)->_raw_size = execp->a_data;
   obj_bsssec (abfd)->_raw_size = execp->a_bss;
@@ -569,17 +593,9 @@ NAME(aout,mkobject) (abfd)
   abfd->tdata.aout_data = rawptr;
   exec_hdr (abfd) = &(rawptr->e);
 
-  /* For simplicity's sake we just make all the sections right here. */
-
   obj_textsec (abfd) = (asection *)NULL;
   obj_datasec (abfd) = (asection *)NULL;
   obj_bsssec (abfd) = (asection *)NULL;
-  bfd_make_section (abfd, ".text");
-  bfd_make_section (abfd, ".data");
-  bfd_make_section (abfd, ".bss");
-  bfd_make_section (abfd, BFD_ABS_SECTION_NAME);
-  bfd_make_section (abfd, BFD_UND_SECTION_NAME);
-  bfd_make_section (abfd, BFD_COM_SECTION_NAME);
 
   return true;
 }
@@ -882,11 +898,9 @@ NAME(aout,adjust_sizes_and_vmas) (abfd, text_size, text_end)
 {
   struct internal_exec *execp = exec_hdr (abfd);
 
-  if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL))
-    {
-      bfd_set_error (bfd_error_invalid_operation);
-      return false;
-    }
+  if (! NAME(aout,make_sections) (abfd))
+    return false;
+
   if (adata(abfd).magic != undecided_magic) return true;
 
   obj_textsec(abfd)->_raw_size =
@@ -993,19 +1007,19 @@ 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;
       }
 
@@ -1037,7 +1051,8 @@ 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) ?
@@ -1086,6 +1101,82 @@ 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 */
 
@@ -1409,8 +1500,8 @@ NAME(aout,make_empty_symbol) (abfd)
 
 /* Translate a set of internal symbols into external symbols.  */
 
-static boolean
-translate_symbol_table (abfd, in, ext, count, str, strsize, dynamic)
+boolean
+NAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic)
      bfd *abfd;
      aout_symbol_type *in;
      struct external_nlist *ext;
@@ -1465,95 +1556,66 @@ boolean
 NAME(aout,slurp_symbol_table) (abfd)
      bfd *abfd;
 {
-  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 *old_external_syms;
   aout_symbol_type *cached;
-  bfd_size_type dynsym_count = 0;
-  struct external_nlist *dynsyms = NULL;
-  char *dynstrs = NULL;
-  bfd_size_type dynstr_size;
+  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)
-    {
-      bfd_set_error (bfd_error_no_symbols);
-      return false;
-    }
+  if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
+    return true;
 
-  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
-  if (bfd_read ((PTR)string_chars, BYTES_IN_WORD, 1, abfd) != BYTES_IN_WORD)
+  old_external_syms = obj_aout_external_syms (abfd);
+
+  if (! aout_get_external_symbols (abfd))
     return false;
-  string_size = GET_WORD (abfd, string_chars);
 
-  /* If this is a dynamic object, see if we can get the dynamic symbol
-     table.  */
-  if ((bfd_get_file_flags (abfd) & DYNAMIC) != 0
-      && aout_backend_info (abfd)->read_dynamic_symbols)
+  if (obj_aout_external_sym_count (abfd) == 0)
     {
-      dynsym_count = ((*aout_backend_info (abfd)->read_dynamic_symbols)
-                     (abfd, &dynsyms, &dynstrs, &dynstr_size));
-      if (dynsym_count == (bfd_size_type) -1)
-       return false;
+      bfd_set_error (bfd_error_no_symbols);
+      return false;
     }
 
-  strings = (char *) bfd_alloc (abfd, string_size + 1);
-  cached = ((aout_symbol_type *)
-           bfd_zalloc (abfd,
-                       ((bfd_get_symcount (abfd) + dynsym_count)
-                        * 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);
 
-  /* Don't allocate on the obstack, so we can free it easily.  */
-  syms = (struct external_nlist *) malloc(symbol_size);
-  if (!strings || !cached || !syms)
+  if (cached == NULL)
     {
       bfd_set_error (bfd_error_no_memory);
       return false;
     }
-  bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
-  if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_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)))
     {
-    bailout:
-      if (syms)
-       free (syms);
-      if (cached)
-       bfd_release (abfd, cached);
-      if (strings)
-       bfd_release (abfd, strings);
+      free (cached);
       return false;
     }
 
-  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
-  if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size)
-    {
-      goto bailout;
-    }
-  strings[string_size] = 0; /* Just in case. */
+  bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd);
 
-  /* OK, now walk the new symtable, cacheing symbol properties */
-  if (! translate_symbol_table (abfd, cached, syms, bfd_get_symcount (abfd),
-                               strings, string_size, false))
-    goto bailout;
-  if (dynsym_count > 0)
-    {
-      if (! translate_symbol_table (abfd, cached + bfd_get_symcount (abfd),
-                                   dynsyms, dynsym_count, dynstrs,
-                                   dynstr_size, true))
-       goto bailout;
+  obj_aout_symbols (abfd) = cached;
 
-      bfd_get_symcount (abfd) += dynsym_count;
+  /* 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;
     }
 
-  obj_aout_symbols (abfd) =  cached;
-  free((PTR)syms);
-
   return true;
 }
-
 \f
 /* Possible improvements:
    + look for strings matching trailing substrings of other strings
@@ -1862,22 +1924,22 @@ add_to_stringtab (abfd, str, tab)
   entry->count = 1;
 #endif
 
-  assert (*tab->end == 0);
+  BFD_ASSERT (*tab->end == 0);
   *(tab->end) = entry;
   tab->end = &entry->next_to_output;
-  assert (*tab->end == 0);
+  BFD_ASSERT (*tab->end == 0);
 
   {
     tab->index += len + 1;
     if (len == 0)
       tab->empty_string_index = entry->index;
   }
-  assert (*ep == 0);
+  BFD_ASSERT (*ep == 0);
   *ep = entry;
   return entry->index;
 }
 
-static void
+static boolean
 emit_strtab (abfd, tab)
      bfd *abfd;
      struct stringtab_data *tab;
@@ -1892,11 +1954,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
@@ -1944,6 +2011,8 @@ emit_strtab (abfd, tab)
        }
       g->KEEPIT = (KEEPITTYPE) count;
     } */
+
+  return true;
 }
 
 boolean
@@ -1992,13 +2061,11 @@ NAME(aout,write_syms) (abfd)
       g->KEEPIT = count;
     }
 
-  emit_strtab (abfd, &strtab);
-
-  return true;
+  return emit_strtab (abfd, &strtab);
 }
 
 \f
-unsigned int
+long
 NAME(aout,get_symtab) (abfd, location)
      bfd *abfd;
      asymbol **location;
@@ -2006,7 +2073,8 @@ NAME(aout,get_symtab) (abfd, 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++);
@@ -2038,9 +2106,8 @@ NAME(aout,swap_std_reloc_out) (abfd, g, natptr)
   r_pcrel  = (int) g->howto->pc_relative; /* Relative to PC? */
   /* XXX This relies on relocs coming from a.out files.  */
   r_baserel = (g->howto->type & 8) != 0;
-  /* r_jmptable, r_relative???  FIXME-soon */
-  r_jmptable = 0;
-  r_relative = 0;
+  r_jmptable = (g->howto->type & 16) != 0;
+  r_relative = (g->howto->type & 32) != 0;
 
 #if 0
   /* For a standard reloc, the addend is in the object file.  */
@@ -2303,18 +2370,16 @@ NAME(aout,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols)
                        >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
   }
 
-  howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel;
+  howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel
+             + 16 * r_jmptable + 32 * r_relative;
   BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std));
   cache_ptr->howto =  howto_table_std + howto_idx;
   BFD_ASSERT (cache_ptr->howto->type != -1);
-  BFD_ASSERT (r_jmptable == 0);
-  BFD_ASSERT (r_relative == 0);
-  /* FIXME-soon:  Roll jmptable, relative bits into howto setting */
 
   MOVE_ADDRESS(0);
 }
 
-/* Reloc hackery */
+/* Read and swap the relocs for a section.  */
 
 boolean
 NAME(aout,slurp_reloc_table) (abfd, asect, symbols)
@@ -2325,16 +2390,16 @@ NAME(aout,slurp_reloc_table) (abfd, asect, symbols)
   unsigned int count;
   bfd_size_type reloc_size;
   PTR relocs;
-  bfd_size_type dynrel_count = 0;
-  PTR dynrels = NULL;
   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))
     reloc_size = exec_hdr(abfd)->a_drsize;
@@ -2346,43 +2411,33 @@ NAME(aout,slurp_reloc_table) (abfd, asect, symbols)
       return false;
     }
 
-  if ((bfd_get_file_flags (abfd) & DYNAMIC) != 0
-      && aout_backend_info (abfd)->read_dynamic_relocs)
-    {
-      dynrel_count = ((*aout_backend_info (abfd)->read_dynamic_relocs)
-                     (abfd, &dynrels));
-      if (dynrel_count == (bfd_size_type) -1)
-       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 *)
-                bfd_zalloc (abfd,
-                            (size_t) ((count + dynrel_count)
-                                      * sizeof (arelent))));
-  if (!reloc_cache)
+  reloc_cache = (arelent *) malloc ((size_t) (count * sizeof (arelent)));
+  if (reloc_cache == NULL && count != 0)
     {
-    nomem:
       bfd_set_error (bfd_error_no_memory);
       return false;
     }
+  memset (reloc_cache, 0, count * sizeof (arelent));
 
-  relocs = (PTR) bfd_alloc (abfd, reloc_size);
-  if (!relocs)
+  relocs = malloc (reloc_size);
+  if (relocs == NULL && reloc_size != 0)
     {
-      bfd_release (abfd, reloc_cache);
-      goto nomem;
+      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_set_error (bfd_error_system_call);
+      free (relocs);
+      free (reloc_cache);
       return false;
     }
 
@@ -2397,62 +2452,21 @@ NAME(aout,slurp_reloc_table) (abfd, asect, symbols)
     }
   else
     {
-      register struct reloc_std_external *rptr
-       (struct reloc_std_external *) relocs;
+      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);
     }
 
-  if (dynrel_count > 0)
-    {
-      asymbol **dynsyms;
-
-      /* The dynamic symbols are at the end of the symbol table.  */
-      for (dynsyms = symbols;
-          *dynsyms != NULL && ((*dynsyms)->flags & BSF_DYNAMIC) == 0;
-          ++dynsyms)
-       ;
-
-      /* Swap in the dynamic relocs.  These relocs may be for either
-        section, so we must discard ones we don't want.  */
-      counter = 0;
-      if (each_size == RELOC_EXT_SIZE)
-       {
-         register struct reloc_ext_external *rptr
-           = (struct reloc_ext_external *) dynrels;
-
-         for (; counter < dynrel_count; counter++, rptr++, cache_ptr++)
-           {
-             NAME(aout,swap_ext_reloc_in) (abfd, rptr, cache_ptr, dynsyms);
-             cache_ptr->address -= bfd_get_section_vma (abfd, asect);
-             if (cache_ptr->address >= bfd_section_size (abfd, asect))
-               --cache_ptr;
-           }
-       }
-      else
-       {
-         register struct reloc_std_external *rptr
-           = (struct reloc_std_external *) dynrels;
-
-         for (; counter < dynrel_count; counter++, rptr++, cache_ptr++)
-           {
-             NAME(aout,swap_std_reloc_in) (abfd, rptr, cache_ptr, dynsyms);
-             cache_ptr->address -= bfd_get_section_vma (abfd, asect);
-             if (cache_ptr->address >= bfd_section_size (abfd, asect))
-               --cache_ptr;
-           }
-       }
-    }
+  free (relocs);
 
-  bfd_release (abfd,relocs);
   asect->relocation = reloc_cache;
   asect->reloc_count = cache_ptr - reloc_cache;
+
   return true;
 }
 
-
-
 /* Write out a relocation section into an object file.  */
 
 boolean
@@ -2504,7 +2518,7 @@ NAME(aout,squirt_out_relocs) (abfd, section)
 }
 
 /* This is stupid.  This function should be a boolean predicate */
-unsigned int
+long
 NAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols)
      bfd *abfd;
      sec_ptr section;
@@ -2515,7 +2529,7 @@ NAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols)
   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;
@@ -2526,7 +2540,6 @@ NAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols)
   }
   else {
     tblptr = section->relocation;
-    if (!tblptr) return 0;
 
     for (count = 0; count++ < section->reloc_count;)
       {
@@ -2538,52 +2551,40 @@ NAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols)
   return section->reloc_count;
 }
 
-unsigned int
+long
 NAME(aout,get_reloc_upper_bound) (abfd, asect)
      bfd *abfd;
      sec_ptr asect;
 {
-  bfd_size_type dynrel_count = 0;
-
   if (bfd_get_format (abfd) != bfd_object) {
     bfd_set_error (bfd_error_invalid_operation);
-    return 0;
+    return -1;
   }
   if (asect->flags & SEC_CONSTRUCTOR) {
     return (sizeof (arelent *) * (asect->reloc_count+1));
   }
 
-  if ((bfd_get_file_flags (abfd) & DYNAMIC) != 0
-      && aout_backend_info (abfd)->read_dynamic_relocs)
-    {
-      PTR dynrels;
-
-      dynrel_count = ((*aout_backend_info (abfd)->read_dynamic_relocs)
-                     (abfd, &dynrels));
-      if (dynrel_count == (bfd_size_type) -1)
-       return 0;
-    }
-
   if (asect == obj_datasec (abfd))
-    return (sizeof (arelent *) *
-           ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd))
-            + dynrel_count + 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))
-            + dynrel_count + 1));
+    return (sizeof (arelent *)
+           ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
+              + 1));
 
   bfd_set_error (bfd_error_invalid_operation);
-  return 0;
+  return -1;
 }
 
 \f
-unsigned int
+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 *));
 }
@@ -2792,6 +2793,29 @@ NAME(aout,sizeof_headers) (abfd, 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.  */
 
@@ -2819,7 +2843,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));
@@ -2929,7 +2952,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;
@@ -2952,7 +2975,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))
@@ -2977,69 +3000,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 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 ((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 *) malloc ((size_t) stringsize);
-  if (strings == NULL && stringsize != 0)
-    {
-      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)
-    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
@@ -3436,13 +3396,15 @@ 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));
+      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;
-      drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd)
-                                              ->link_order_head)
-                * obj_reloc_entry_size (abfd));
+      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;
     }
 
@@ -3572,9 +3534,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.  */
@@ -3591,7 +3551,7 @@ aout_link_input_bfd (finfo, input_bfd)
 
   /* 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);
@@ -3706,6 +3666,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;
@@ -3715,6 +3676,8 @@ 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.  It is the target of an
@@ -3732,7 +3695,6 @@ aout_link_write_symbols (finfo, input_bfd, symbol_map)
        }
       else
        {
-         struct aout_link_hash_entry *h;
          struct aout_link_hash_entry *hresolve;
 
          /* We have saved the hash table entry for this symbol, if
@@ -3921,6 +3883,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);
@@ -4098,7 +4076,7 @@ aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
       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.  */
@@ -4244,10 +4222,9 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
                       >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
        }
 
-      howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel;
+      howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel
+                 + 16 * r_jmptable + 32 * r_relative;
       BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std));
-      BFD_ASSERT (r_jmptable == 0);
-      BFD_ASSERT (r_relative == 0);
 
       if (relocateable)
        {
@@ -4814,8 +4791,8 @@ aout_link_reloc_link_order (finfo, o, p)
 
       r_pcrel = howto->pc_relative;
       r_baserel = (howto->type & 8) != 0;
-      r_jmptable = 0;
-      r_relative = 0;
+      r_jmptable = (howto->type & 16) != 0;
+      r_relative = (howto->type & 32) != 0;
       r_length = howto->size;
 
       PUT_WORD (finfo->output_bfd, p->offset, srel.r_address);
This page took 0.053528 seconds and 4 git commands to generate.