#define KEEPIT flags
#define KEEPITTYPE int
-#include <assert.h>
#include <string.h> /* For strchr and friends */
#include "bfd.h"
#include <sysdep.h>
#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
{ -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]))
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
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;
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;
}
{
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 =
{
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;
}
/* 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) ?
#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 */
/* 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;
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
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;
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
}
g->KEEPIT = (KEEPITTYPE) count;
} */
+
+ return true;
}
boolean
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;
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++);
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. */
>> 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)
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;
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;
}
}
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
}
/* 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;
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;
}
else {
tblptr = section->relocation;
- if (!tblptr) return 0;
for (count = 0; count++ < section->reloc_count;)
{
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 *));
}
{
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. */
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));
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;
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))
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
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;
}
/* 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. */
/* 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);
{
const char *name;
int type;
+ struct aout_link_hash_entry *h;
boolean skip;
asection *symsec;
bfd_vma val = 0;
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
}
else
{
- struct aout_link_hash_entry *h;
struct aout_link_hash_entry *hresolve;
/* We have saved the hash table entry for this symbol, if
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);
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. */
>> 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)
{
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);