#define KEEPIT flags
#define KEEPITTYPE int
-#include <assert.h>
#include <string.h> /* For strchr and friends */
#include "bfd.h"
#include <sysdep.h>
-#include <ansidecl.h>
#include "bfdlink.h"
#include "libaout.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]))
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]
case 32:
code = BFD_RELOC_32;
break;
+ case 64:
+ code = BFD_RELOC_64;
+ break;
}
if (ext)
switch (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
#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;
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);
@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;
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
*/
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;
}
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;
*/
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;
}
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;
}
*/
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;
*/
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;
}
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;
- return false;
- }
+ if (! NAME(aout,make_sections) (abfd))
+ return false;
+
if (adata(abfd).magic != undecided_magic) return true;
obj_textsec(abfd)->_raw_size =
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;
{
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;
}
}
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;
/* 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 */
static boolean
-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)
+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)
if (!copy || !reloc)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return false;
}
cache_ptr->type = N_BSS;
break;
default:
- bfd_error = bad_value;
+ bfd_set_error (bfd_error_bad_value);
return false;
}
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++;
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;
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_error = nonrepresentable_section;
+ 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 = nonrepresentable_section;
+ bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
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_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return NULL;
}
new->symbol.the_bfd = 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;
hold them all plus all the cached symbol entries. */
boolean
-DEFUN(NAME(aout,slurp_symbol_table),(abfd),
- bfd *abfd)
+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_error = no_symbols;
- return false;
- }
+ if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
+ return true;
+
+ old_external_syms = obj_aout_external_syms (abfd);
- bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
- if (bfd_read ((PTR)string_chars, BYTES_IN_WORD, 1, abfd) != BYTES_IN_WORD)
+ 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_error = no_memory;
+ 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
bfd_alloc_by_size_t (abfd, sizeof (struct stringtab_entry));
if (!entry)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
abort(); /* FIXME */
}
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
-DEFUN(NAME(aout,write_syms),(abfd),
- bfd *abfd)
+NAME(aout,write_syms) (abfd)
+ bfd *abfd;
{
unsigned int count ;
asymbol **generic = bfd_get_outsymbols (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++);
/* 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);
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. */
/* 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;
} \
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;
}
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;
>> 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
-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;
- 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;
reloc_size = exec_hdr(abfd)->a_trsize;
else
{
- bfd_error = invalid_operation;
+ bfd_set_error (bfd_error_invalid_operation);
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_error = no_memory;
+ 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_error = system_call_error;
+ 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;
+ free (relocs);
- 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;
- }
- }
- }
-
- 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
-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;
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;
}
}
/* 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;
}
else {
tblptr = section->relocation;
- if (!tblptr) return 0;
for (count = 0; count++ < section->reloc_count;)
{
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;
{
- bfd_size_type dynrel_count = 0;
-
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 ((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_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);
/*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;
*/
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;
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,':');
/*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. */
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_hash_allocate (table, sizeof (struct aout_link_hash_entry)));
if (ret == (struct aout_link_hash_entry *) NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return (struct bfd_hash_entry *) ret;
}
malloc (sizeof (struct aout_link_hash_table)));
if (ret == (struct aout_link_hash_table *) NULL)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return (struct bfd_link_hash_table *) NULL;
}
if (! _bfd_link_hash_table_init (&ret->root, abfd,
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;
}
}
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)
- {
- 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)
- {
- 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
* sizeof (struct aout_link_hash_entry *))));
if (!sym_hash)
{
- bfd_error = no_memory;
+ bfd_set_error (bfd_error_no_memory);
return false;
}
obj_aout_sym_hashes (abfd) = sym_hash;
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)
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
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;
abort ();
}
}
+ if (obj_textsec (abfd) != (asection *) NULL)
+ trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
+ ->link_order_head)
+ * obj_reloc_entry_size (abfd));
exec_hdr (abfd)->a_trsize = trsize;
+ if (obj_datasec (abfd) != (asection *) NULL)
+ drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd)
+ ->link_order_head)
+ * obj_reloc_entry_size (abfd));
exec_hdr (abfd)->a_drsize = drsize;
}
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))
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))
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;
/* 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. */
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,
&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
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
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;
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
{
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);
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
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)
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. */
(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
<= 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. */
>> 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)
{
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 = (howto->type & 16) != 0;
+ r_relative = (howto->type & 32) != 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;
+}