/* BFD semi-generic back-end for a.out binaries.
- Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
#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 *));
+static boolean translate_from_native_sym_flags
+ PARAMS ((bfd *, aout_symbol_type *));
+static boolean translate_to_native_sym_flags
+ PARAMS ((bfd *, asymbol *, struct external_nlist *));
/*
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;
}
if (N_MAGIC (*execp) == ZMAGIC)
{
- abfd->flags |= D_PAGED|WP_TEXT;
- adata(abfd).magic = z_magic;
+ abfd->flags |= D_PAGED | WP_TEXT;
+ adata (abfd).magic = z_magic;
+ }
+ else if (N_MAGIC (*execp) == QMAGIC)
+ {
+ abfd->flags |= D_PAGED | WP_TEXT;
+ adata (abfd).magic = z_magic;
+ adata (abfd).subformat = q_magic_format;
}
else if (N_MAGIC (*execp) == NMAGIC)
{
abfd->flags |= WP_TEXT;
- adata(abfd).magic = n_magic;
+ adata (abfd).magic = n_magic;
}
+ else if (N_MAGIC (*execp) == OMAGIC)
+ adata (abfd).magic = o_magic;
else
- adata(abfd).magic = o_magic;
+ {
+ /* Should have been checked with N_BADMAG before this routine
+ was called. */
+ abort ();
+ }
bfd_get_start_address (abfd) = execp->a_entry;
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;
#ifdef THIS_IS_ONLY_DOCUMENTATION
/* The common code can't fill in these things because they depend
on either the start address of the text segment, the rounding
- up of virtual addersses between segments, or the starting file
+ up of virtual addresses between segments, or the starting file
position of the text segment -- all of which varies among different
versions of a.out. */
*/
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, unknown)
+ enum bfd_architecture arch;
+ unsigned long machine;
+ boolean *unknown;
{
enum machine_type arch_flags;
arch_flags = M_UNKNOWN;
+ *unknown = true;
switch (arch) {
case bfd_arch_sparc:
case bfd_arch_m68k:
switch (machine) {
case 0: arch_flags = M_68010; break;
- case 68000: arch_flags = M_UNKNOWN; break;
+ case 68000: arch_flags = M_UNKNOWN; *unknown = false; break;
case 68010: arch_flags = M_68010; break;
case 68020: arch_flags = M_68020; break;
default: arch_flags = M_UNKNOWN; break;
default:
arch_flags = M_UNKNOWN;
}
+
+ if (arch_flags != M_UNKNOWN)
+ *unknown = false;
+
return 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;
- if (arch != bfd_arch_unknown &&
- NAME(aout,machine_type) (arch, machine) == M_UNKNOWN)
- return false; /* We can't represent this type */
+ if (arch != bfd_arch_unknown)
+ {
+ boolean unknown;
+
+ NAME(aout,machine_type) (arch, machine, &unknown);
+ if (unknown)
+ return false;
+ }
/* Determine the size of a relocation entry */
switch (arch) {
execp->a_text = obj_textsec(abfd)->_raw_size;
if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted)))
execp->a_text += adata(abfd).exec_bytes_size;
- N_SET_MAGIC (*execp, ZMAGIC);
+ if (obj_aout_subformat (abfd) == q_magic_format)
+ N_SET_MAGIC (*execp, QMAGIC);
+ else
+ N_SET_MAGIC (*execp, ZMAGIC);
/* Spec says data section should be rounded up to page boundary. */
obj_datasec(abfd)->_raw_size
}
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 (adata(abfd).magic != undecided_magic) return true;
+ if (! NAME(aout,make_sections) (abfd))
+ return false;
+
+ if (adata(abfd).magic != undecided_magic)
+ return true;
obj_textsec(abfd)->_raw_size =
align_power(obj_textsec(abfd)->_raw_size,
if (abfd->flags & D_PAGED)
/* Whether or not WP_TEXT is set -- let D_PAGED override. */
- /* @@ What about QMAGIC? */
adata(abfd).magic = z_magic;
else if (abfd->flags & WP_TEXT)
adata(abfd).magic = n_magic;
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) ?
return true;
}
\f
-/* Classify stabs symbols */
+/* Read the external symbols from an a.out file. */
-#define sym_in_text_section(sym) \
- (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
+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;
-#define sym_in_data_section(sym) \
- (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
+ count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE;
-#define sym_in_bss_section(sym) \
- (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
+ /* 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;
+ }
-/* Symbol is undefined if type is N_UNDF|N_EXT and if it has
- zero in the "value" field. Nonzeroes there are fortrancommon
- symbols. */
-#define sym_is_undefined(sym) \
- ((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0)
+ 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;
+ }
-/* Symbol is a global definition if N_EXT is on and if it has
- a nonzero type field. */
-#define sym_is_global_defn(sym) \
- (((sym)->type & N_EXT) && (sym)->type & N_TYPE)
+ obj_aout_external_syms (abfd) = syms;
+ obj_aout_external_sym_count (abfd) = count;
+ }
+
+ if (obj_aout_external_strings (abfd) == NULL
+ && exec_hdr (abfd)->a_syms != 0)
+ {
+ 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);
-/* Symbol is debugger info if any bits outside N_TYPE or N_EXT
- are on. */
-#define sym_is_debugger_info(sym) \
- (((sym)->type & ~(N_EXT | N_TYPE)) || (sym)->type == N_FN)
+ strings = (char *) malloc ((size_t) stringsize + 1);
+ if (strings == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
-#define sym_is_fortrancommon(sym) \
- (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0)
+ /* 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;
+ }
-/* Symbol is absolute if it has N_ABS set */
-#define sym_is_absolute(sym) \
- (((sym)->type & N_TYPE)== N_ABS)
+ /* Sanity preservation. */
+ strings[stringsize] = '\0';
+ obj_aout_external_strings (abfd) = strings;
+ obj_aout_external_string_size (abfd) = stringsize;
+ }
-#define sym_is_indirect(sym) \
- (((sym)->type & N_ABS)== N_ABS)
+ 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 an a.out symbol into a BFD symbol. The desc, other, type
+ and symbol->value fields of CACHE_PTR will be set from the a.out
+ nlist structure. This function is responsible for setting
+ symbol->flags and symbol->section, and adjusting symbol->value. */
-static void
-DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd),
- struct external_nlist *sym_pointer AND
- aout_symbol_type * cache_ptr AND
- bfd * abfd)
+static boolean
+translate_from_native_sym_flags (abfd, cache_ptr)
+ bfd *abfd;
+ aout_symbol_type *cache_ptr;
{
- cache_ptr->symbol.section = 0;
- switch (cache_ptr->type & N_TYPE)
+ flagword visible;
+
+ if ((cache_ptr->type & N_STAB) != 0
+ || cache_ptr->type == N_FN)
+ {
+ asection *sec;
+
+ /* This is a debugging symbol. */
+
+ cache_ptr->symbol.flags = BSF_DEBUGGING;
+
+ /* Work out the symbol section. */
+ switch (cache_ptr->type & N_TYPE)
+ {
+ case N_TEXT:
+ case N_FN:
+ sec = obj_textsec (abfd);
+ break;
+ case N_DATA:
+ sec = obj_datasec (abfd);
+ break;
+ case N_BSS:
+ sec = obj_bsssec (abfd);
+ break;
+ default:
+ case N_ABS:
+ sec = &bfd_abs_section;
+ break;
+ }
+
+ cache_ptr->symbol.section = sec;
+ cache_ptr->symbol.value -= sec->vma;
+
+ return true;
+ }
+
+ /* Get the default visibility. This does not apply to all types, so
+ we just hold it in a local variable to use if wanted. */
+ if ((cache_ptr->type & N_EXT) == 0)
+ visible = BSF_LOCAL;
+ else
+ visible = BSF_GLOBAL;
+
+ switch (cache_ptr->type)
{
+ default:
+ case N_ABS: case N_ABS | N_EXT:
+ cache_ptr->symbol.section = &bfd_abs_section;
+ cache_ptr->symbol.flags = visible;
+ break;
+
+ case N_UNDF | N_EXT:
+ if (cache_ptr->symbol.value != 0)
+ {
+ /* This is a common symbol. */
+ cache_ptr->symbol.flags = BSF_GLOBAL;
+ cache_ptr->symbol.section = &bfd_com_section;
+ }
+ else
+ {
+ cache_ptr->symbol.flags = 0;
+ cache_ptr->symbol.section = &bfd_und_section;
+ }
+ break;
+
+ case N_TEXT: case N_TEXT | N_EXT:
+ cache_ptr->symbol.section = obj_textsec (abfd);
+ cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+ cache_ptr->symbol.flags = visible;
+ break;
+
+ /* N_SETV symbols used to represent set vectors placed in the
+ data section. They are no longer generated. Theoretically,
+ it was possible to extract the entries and combine them with
+ new ones, although I don't know if that was ever actually
+ done. Unless that feature is restored, treat them as data
+ symbols. */
+ case N_SETV: case N_SETV | N_EXT:
+ case N_DATA: case N_DATA | N_EXT:
+ cache_ptr->symbol.section = obj_datasec (abfd);
+ cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+ cache_ptr->symbol.flags = visible;
+ break;
+
+ case N_BSS: case N_BSS | N_EXT:
+ cache_ptr->symbol.section = obj_bsssec (abfd);
+ cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+ cache_ptr->symbol.flags = visible;
+ break;
+
case N_SETA: case N_SETA | N_EXT:
case N_SETT: case N_SETT | N_EXT:
case N_SETD: case N_SETD | N_EXT:
case N_SETB: case N_SETB | N_EXT:
{
- char *copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1);
asection *section;
+ arelent_chain *reloc;
asection *into_section;
- arelent_chain *reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
- strcpy (copy, cache_ptr->symbol.name);
+ /* This is a set symbol. The name of the symbol is the name
+ of the set (e.g., __CTOR_LIST__). The value of the symbol
+ is the value to add to the set. We create a section with
+ the same name as the symbol, and add a reloc to insert the
+ appropriate value into the section.
+
+ This action is actually obsolete; it used to make the
+ linker do the right thing, but the linker no longer uses
+ this function. */
+
+ section = bfd_get_section_by_name (abfd, cache_ptr->symbol.name);
+ if (section == NULL)
+ {
+ char *copy;
+
+ copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1);
+ if (copy == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+
+ strcpy (copy, cache_ptr->symbol.name);
+ section = bfd_make_section (abfd, copy);
+ if (section == NULL)
+ return false;
+ }
- /* Make sure that this bfd has a section with the right contructor
- name */
- section = bfd_get_section_by_name (abfd, copy);
- if (!section)
- section = bfd_make_section (abfd, copy);
+ reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
+ if (reloc == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
- /* Build a relocation entry for the constructor */
- switch ((cache_ptr->type & N_TYPE))
+ /* Build a relocation entry for the constructor. */
+ switch (cache_ptr->type & N_TYPE)
{
- case N_SETA: case N_SETA | N_EXT:
+ case N_SETA:
into_section = &bfd_abs_section;
cache_ptr->type = N_ABS;
break;
- case N_SETT: case N_SETT | N_EXT:
- into_section = (asection *) obj_textsec (abfd);
+ case N_SETT:
+ into_section = obj_textsec (abfd);
cache_ptr->type = N_TEXT;
break;
- case N_SETD: case N_SETD | N_EXT:
- into_section = (asection *) obj_datasec (abfd);
+ case N_SETD:
+ into_section = obj_datasec (abfd);
cache_ptr->type = N_DATA;
break;
- case N_SETB: case N_SETB | N_EXT:
- into_section = (asection *) obj_bsssec (abfd);
+ case N_SETB:
+ into_section = obj_bsssec (abfd);
cache_ptr->type = N_BSS;
break;
- default:
- abort ();
}
- /* Build a relocation pointing into the constuctor section
- pointing at the symbol in the set vector specified */
-
+ /* Build a relocation pointing into the constructor section
+ pointing at the symbol in the set vector specified. */
reloc->relent.addend = cache_ptr->symbol.value;
- cache_ptr->symbol.section = into_section->symbol->section;
+ cache_ptr->symbol.section = into_section;
reloc->relent.sym_ptr_ptr = into_section->symbol_ptr_ptr;
-
- /* We modify the symbol to belong to a section depending upon the
- name of the symbol - probably __CTOR__ or __DTOR__ but we don't
- really care, and add to the size of the section to contain a
- pointer to the symbol. Build a reloc entry to relocate to this
- symbol attached to this section. */
-
- section->flags = SEC_CONSTRUCTOR;
-
+ /* We modify the symbol to belong to a section depending upon
+ the name of the symbol, and add to the size of the section
+ to contain a pointer to the symbol. Build a reloc entry to
+ relocate to this symbol attached to this section. */
+ section->flags = SEC_CONSTRUCTOR | SEC_RELOC;
section->reloc_count++;
section->alignment_power = 2;
reloc->next = section->constructor_chain;
section->constructor_chain = reloc;
reloc->relent.address = section->_raw_size;
- section->_raw_size += sizeof (int *);
+ section->_raw_size += BYTES_IN_WORD;
+
+ if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE)
+ reloc->relent.howto = howto_table_ext + CTOR_TABLE_RELOC_IDX;
+ else
+ reloc->relent.howto = howto_table_std + CTOR_TABLE_RELOC_IDX;
- reloc->relent.howto
- = (obj_reloc_entry_size(abfd) == RELOC_EXT_SIZE
- ? howto_table_ext : howto_table_std)
- + CTOR_TABLE_RELOC_IDX;
cache_ptr->symbol.flags |= BSF_CONSTRUCTOR;
}
break;
- default:
- if (cache_ptr->type == N_WARNING)
- {
- /* This symbol is the text of a warning message, the next symbol
- is the symbol to associate the warning with */
- cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
-
- /* @@ Stuffing pointers into integers is a no-no.
- We can usually get away with it if the integer is
- large enough though. */
- if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
- abort ();
- cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1));
-
- /* We don't use a warning symbol's section, but we need
- it to be nonzero for the sanity check below, so
- pick one arbitrarily. */
- cache_ptr->symbol.section = &bfd_abs_section;
-
- /* We furgle with the next symbol in place.
- We don't want it to be undefined, we'll trample the type */
- (sym_pointer + 1)->e_type[0] = 0xff;
- break;
- }
- if ((cache_ptr->type | N_EXT) == (N_INDR | N_EXT))
- {
- /* Two symbols in a row for an INDR message. The first symbol
- contains the name we will match, the second symbol contains
- the name the first name is translated into. It is supplied to
- us undefined. This is good, since we want to pull in any files
- which define it */
- cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT;
-
- /* @@ Stuffing pointers into integers is a no-no.
- We can usually get away with it if the integer is
- large enough though. */
- if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
- abort ();
-
- cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1));
- cache_ptr->symbol.section = &bfd_ind_section;
- }
- else if (sym_is_debugger_info (cache_ptr))
- {
- cache_ptr->symbol.flags = BSF_DEBUGGING;
- /* Work out the section correct for this symbol */
- switch (cache_ptr->type & N_TYPE)
- {
- case N_TEXT:
- case N_FN:
- cache_ptr->symbol.section = obj_textsec (abfd);
- cache_ptr->symbol.value -= obj_textsec (abfd)->vma;
- break;
- case N_DATA:
- cache_ptr->symbol.value -= obj_datasec (abfd)->vma;
- cache_ptr->symbol.section = obj_datasec (abfd);
- break;
- case N_BSS:
- cache_ptr->symbol.section = obj_bsssec (abfd);
- cache_ptr->symbol.value -= obj_bsssec (abfd)->vma;
- break;
- default:
- case N_ABS:
- cache_ptr->symbol.section = &bfd_abs_section;
- break;
- }
- }
- else
- {
+ case N_WARNING:
+ /* This symbol is the text of a warning message. The next
+ symbol is the symbol to associate the warning with. If a
+ reference is made to that symbol, a warning is issued. */
+ cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
- if (sym_is_fortrancommon (cache_ptr))
- {
- cache_ptr->symbol.flags = 0;
- cache_ptr->symbol.section = &bfd_com_section;
- }
- else
- {
+ /* @@ Stuffing pointers into integers is a no-no. We can
+ usually get away with it if the integer is large enough
+ though. */
+ if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
+ abort ();
+ cache_ptr->symbol.value = (bfd_vma) (cache_ptr + 1);
+ cache_ptr->symbol.section = &bfd_abs_section;
- }
+ break;
- /* In a.out, the value of a symbol is always relative to the
- * start of the file, if this is a data symbol we'll subtract
- * the size of the text section to get the section relative
- * value. If this is a bss symbol (which would be strange)
- * we'll subtract the size of the previous two sections
- * to find the section relative address.
- */
+ case N_INDR: case N_INDR | N_EXT:
+ /* An indirect symbol. This consists of two symbols in a row.
+ The first symbol is the name of the indirection. The second
+ symbol is the name of the target. A reference to the first
+ symbol becomes a reference to the second. */
+ cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible;
- if (sym_in_text_section (cache_ptr))
- {
- cache_ptr->symbol.value -= obj_textsec (abfd)->vma;
- cache_ptr->symbol.section = obj_textsec (abfd);
- }
- else if (sym_in_data_section (cache_ptr))
- {
- cache_ptr->symbol.value -= obj_datasec (abfd)->vma;
- cache_ptr->symbol.section = obj_datasec (abfd);
- }
- else if (sym_in_bss_section (cache_ptr))
- {
- cache_ptr->symbol.section = obj_bsssec (abfd);
- cache_ptr->symbol.value -= obj_bsssec (abfd)->vma;
- }
- else if (sym_is_undefined (cache_ptr))
- {
- cache_ptr->symbol.flags = 0;
- cache_ptr->symbol.section = &bfd_und_section;
- }
- else if (sym_is_absolute (cache_ptr))
- {
- cache_ptr->symbol.section = &bfd_abs_section;
- }
+ /* @@ Stuffing pointers into integers is a no-no. We can
+ usually get away with it if the integer is large enough
+ though. */
+ if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
+ abort ();
+ cache_ptr->symbol.value = (bfd_vma) (cache_ptr + 1);
- if (sym_is_global_defn (cache_ptr))
- {
- cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
- }
- else if (! sym_is_undefined (cache_ptr))
- {
- cache_ptr->symbol.flags = BSF_LOCAL;
- }
- }
+ cache_ptr->symbol.section = &bfd_ind_section;
+
+ break;
+
+ case N_WEAKU:
+ cache_ptr->symbol.section = &bfd_und_section;
+ cache_ptr->symbol.flags = BSF_WEAK;
+ break;
+
+ case N_WEAKA:
+ cache_ptr->symbol.section = &bfd_abs_section;
+ cache_ptr->symbol.flags = BSF_WEAK;
+ break;
+
+ case N_WEAKT:
+ cache_ptr->symbol.section = obj_textsec (abfd);
+ cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+ cache_ptr->symbol.flags = BSF_WEAK;
+ break;
+
+ case N_WEAKD:
+ cache_ptr->symbol.section = obj_datasec (abfd);
+ cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+ cache_ptr->symbol.flags = BSF_WEAK;
+ break;
+
+ case N_WEAKB:
+ cache_ptr->symbol.section = obj_bsssec (abfd);
+ cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
+ cache_ptr->symbol.flags = BSF_WEAK;
+ break;
}
- if (cache_ptr->symbol.section == 0)
- abort ();
-}
+ return true;
+}
+/* Set the fields of SYM_POINTER according to CACHE_PTR. */
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 (abfd, cache_ptr, sym_pointer)
+ bfd *abfd;
+ asymbol *cache_ptr;
+ struct external_nlist *sym_pointer;
{
bfd_vma value = cache_ptr->value;
- /* mask out any existing type bits in case copying from one section
- to another */
+ /* Mask out any existing type bits in case copying from one section
+ to another. */
sym_pointer->e_type[0] &= ~N_TYPE;
- /* We attempt to order these tests by decreasing frequency of success,
- according to tcov when linking the linker. */
- if (bfd_get_output_section(cache_ptr) == &bfd_abs_section) {
+ if (bfd_get_section (cache_ptr) == &bfd_abs_section)
sym_pointer->e_type[0] |= N_ABS;
- }
- else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
+ else if (bfd_get_section (cache_ptr) == obj_textsec (abfd)
+ || (bfd_get_section (cache_ptr)->output_section
+ == obj_textsec (abfd)))
sym_pointer->e_type[0] |= N_TEXT;
- }
- else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
+ else if (bfd_get_section (cache_ptr) == obj_datasec (abfd)
+ || (bfd_get_section (cache_ptr)->output_section
+ == obj_datasec (abfd)))
sym_pointer->e_type[0] |= N_DATA;
- }
- else if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
+ else if (bfd_get_section (cache_ptr) == obj_bsssec (abfd)
+ || (bfd_get_section (cache_ptr)->output_section
+ == obj_bsssec (abfd)))
sym_pointer->e_type[0] |= N_BSS;
- }
- else if (bfd_get_output_section(cache_ptr) == &bfd_und_section) {
- sym_pointer->e_type[0] = (N_UNDF | N_EXT);
- }
- else if (bfd_get_output_section(cache_ptr) == &bfd_ind_section) {
+ else if (bfd_get_section (cache_ptr) == &bfd_und_section)
+ sym_pointer->e_type[0] = N_UNDF | N_EXT;
+ else if (bfd_get_section (cache_ptr) == &bfd_ind_section)
sym_pointer->e_type[0] = N_INDR;
- }
- else if (bfd_get_output_section(cache_ptr) == NULL) {
- /* Protect the bfd_is_com_section call.
- This case occurs, e.g., for the *DEBUG* section of a COFF file. */
- bfd_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;
- return false;
- }
+ else if (bfd_get_section (cache_ptr) == NULL)
+ {
+ /* Protect the bfd_is_com_section call. This case occurs, e.g.,
+ for the *DEBUG* section of a COFF file. */
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+ else if (bfd_is_com_section (bfd_get_section (cache_ptr)))
+ sym_pointer->e_type[0] = N_UNDF | N_EXT;
+ else
+ {
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
/* Turn the symbol from section relative to absolute again */
+ value += cache_ptr->section->vma;
- value += cache_ptr->section->output_section->vma + cache_ptr->section->output_offset ;
-
-
- if (cache_ptr->flags & (BSF_WARNING)) {
+ if ((cache_ptr->flags & BSF_WARNING) != 0)
sym_pointer->e_type[0] = N_WARNING;
- (sym_pointer+1)->e_type[0] = 1;
- }
- if (cache_ptr->flags & BSF_DEBUGGING) {
- sym_pointer->e_type[0] = ((aout_symbol_type *)cache_ptr)->type;
- }
- else if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
+ if ((cache_ptr->flags & BSF_DEBUGGING) != 0)
+ sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type;
+ else if ((cache_ptr->flags & BSF_GLOBAL) != 0)
sym_pointer->e_type[0] |= N_EXT;
- }
- if (cache_ptr->flags & BSF_CONSTRUCTOR) {
- int type = ((aout_symbol_type *)cache_ptr)->type;
- switch (type)
- {
- case N_ABS: type = N_SETA; break;
- case N_TEXT: type = N_SETT; break;
- case N_DATA: type = N_SETD; break;
- case N_BSS: type = N_SETB; break;
- }
- sym_pointer->e_type[0] = type;
- }
+
+ if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0)
+ {
+ int type = ((aout_symbol_type *) cache_ptr)->type;
+ switch (type)
+ {
+ case N_ABS: type = N_SETA; break;
+ case N_TEXT: type = N_SETT; break;
+ case N_DATA: type = N_SETD; break;
+ case N_BSS: type = N_SETB; break;
+ }
+ sym_pointer->e_type[0] = type;
+ }
+
+ if ((cache_ptr->flags & BSF_WEAK) != 0)
+ {
+ int type;
+
+ switch (sym_pointer->e_type[0] & N_TYPE)
+ {
+ default:
+ case N_ABS: type = N_WEAKA; break;
+ case N_TEXT: type = N_WEAKT; break;
+ case N_DATA: type = N_WEAKD; break;
+ case N_BSS: type = N_WEAKB; break;
+ case N_UNDF: type = N_WEAKU; break;
+ }
+ sym_pointer->e_type[0] = type;
+ }
PUT_WORD(abfd, value, sym_pointer->e_value);
\f
/* Native-level interface to symbols. */
-
asymbol *
-DEFUN(NAME(aout,make_empty_symbol),(abfd),
- bfd *abfd)
+NAME(aout,make_empty_symbol) (abfd)
+ bfd *abfd;
{
aout_symbol_type *new =
(aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
+ if (!new)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
new->symbol.the_bfd = abfd;
return &new->symbol;
/* Translate a set of internal symbols into external symbols. */
-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;
in->type = bfd_h_get_8 (abfd, ext->e_type);
in->symbol.udata = 0;
- translate_from_native_sym_flags (ext, in, abfd);
+ if (! translate_from_native_sym_flags (abfd, in))
+ return false;
if (dynamic)
in->symbol.flags |= BSF_DYNAMIC;
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;
- 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))));
-
- /* Don't allocate on the obstack, so we can free it easily. */
- syms = (struct external_nlist *) bfd_xmalloc(symbol_size);
- bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
- if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size)
+ cached_size = (obj_aout_external_sym_count (abfd)
+ * sizeof (aout_symbol_type));
+ cached = (aout_symbol_type *) malloc (cached_size);
+ if (cached == NULL)
{
- bailout:
- if (syms)
- free (syms);
- if (cached)
- bfd_release (abfd, cached);
- if (strings)
- bfd_release (abfd, strings);
+ bfd_set_error (bfd_error_no_memory);
return false;
}
-
- bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
- if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size)
+ memset (cached, 0, cached_size);
+
+ /* Convert from external symbol information to internal. */
+ if (! (NAME(aout,translate_symbol_table)
+ (abfd, cached,
+ obj_aout_external_syms (abfd),
+ obj_aout_external_sym_count (abfd),
+ obj_aout_external_strings (abfd),
+ obj_aout_external_string_size (abfd),
+ false)))
{
- goto bailout;
+ free (cached);
+ return false;
}
- strings[string_size] = 0; /* Just in case. */
- /* OK, now walk the new symtable, cacheing symbol properties */
- 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;
+ bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd);
- bfd_get_symcount (abfd) += dynsym_count;
- }
+ obj_aout_symbols (abfd) = cached;
- obj_aout_symbols (abfd) = cached;
- free((PTR)syms);
+ /* It is very likely that anybody who calls this function will not
+ want the external symbol information, so if it was allocated
+ because of our call to aout_get_external_symbols, we free it up
+ right away to save space. */
+ if (old_external_syms == (struct external_nlist *) NULL
+ && obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
+ {
+ free (obj_aout_external_syms (abfd));
+ obj_aout_external_syms (abfd) = NULL;
+ }
return true;
}
-
\f
-/* Possible improvements:
+/* We use a hash table when writing out symbols so that we only write
+ out a particular string once. This helps particularly when the
+ linker writes out stabs debugging entries, because each different
+ contributing object file tends to have many duplicate stabs
+ strings.
+
+ Possible improvements:
+ look for strings matching trailing substrings of other strings
+ better data structures? balanced trees?
- + smaller per-string or per-symbol data? re-use some of the symbol's
- data fields?
- + also look at reducing memory use elsewhere -- maybe if we didn't have to
- construct the entire symbol table at once, we could get by with smaller
- amounts of VM? (What effect does that have on the string table
- reductions?)
- + rip this out of here, put it into its own file in bfd or libiberty, so
- coff and elf can use it too. I'll work on this soon, but have more
- pressing tasks right now.
-
- A hash table might(?) be more efficient for handling exactly the cases that
- are handled now, but for trailing substring matches, I think we want to
- examine the `nearest' values (reverse-)lexically, not merely impose a strict
- order, nor look only for exact-match or not-match. I don't think a hash
- table would be very useful for that, and I don't feel like fleshing out two
- completely different implementations. [raeburn:930419.0331EDT] */
-
-struct stringtab_entry {
- /* Hash value for this string. Only useful so long as we aren't doing
- substring matches. */
- unsigned int hash;
-
- /* Next node to look at, depending on whether the hash value of the string
- being searched for is less than or greater than the hash value of the
- current node. For now, `equal to' is lumped in with `greater than', for
- space efficiency. It's not a common enough case to warrant another field
- to be used for all nodes. */
- struct stringtab_entry *less;
- struct stringtab_entry *greater;
-
- /* The string itself. */
- CONST char *string;
-
- /* The index allocated for this string. */
- bfd_size_type index;
+ + look at reducing memory use elsewhere -- maybe if we didn't have
+ to construct the entire symbol table at once, we could get by
+ with smaller amounts of VM? (What effect does that have on the
+ string table reductions?)
-#ifdef GATHER_STATISTICS
- /* How many references have there been to this string? (Not currently used;
- could be dumped out for anaylsis, if anyone's interested.) */
- unsigned long count;
-#endif
+ This hash table code breaks dbx on SunOS 4.1.3, so we don't do it
+ if BFD_TRADITIONAL_FORMAT is set. */
- /* Next node in linked list, in suggested output order. */
- struct stringtab_entry *next_to_output;
-};
-
-struct stringtab_data {
- /* Tree of string table entries. */
- struct stringtab_entry *strings;
-
- /* Fudge factor used to center top node of tree. */
- int hash_zero;
+/* An entry in the strtab hash table. */
- /* Next index value to issue. */
+struct strtab_hash_entry
+{
+ struct bfd_hash_entry root;
+ /* Index in string table. */
bfd_size_type index;
-
- /* Index used for empty strings. Cached here because checking for them
- is really easy, and we can avoid searching the tree. */
- bfd_size_type empty_string_index;
-
- /* These fields indicate the two ends of a singly-linked list that indicates
- the order strings should be written out in. Use this order, and no
- seeking will need to be done, so output efficiency should be maximized. */
- struct stringtab_entry **end;
- struct stringtab_entry *output_order;
-
-#ifdef GATHER_STATISTICS
- /* Number of strings which duplicate strings already in the table. */
- unsigned long duplicates;
-
- /* Number of bytes saved by not having to write all the duplicate strings. */
- unsigned long bytes_saved;
-
- /* Number of zero-length strings. Currently, these all turn into
- references to the null byte at the end of the first string. In some
- cases (possibly not all? explore this...), it should be possible to
- simply write out a zero index value. */
- unsigned long empty_strings;
-
- /* Number of times the hash values matched but the strings were different.
- Note that this includes the number of times the other string(s) occurs, so
- there may only be two strings hashing to the same value, even if this
- number is very large. */
- unsigned long bad_hash_matches;
-
- /* Null strings aren't counted in this one.
- This will probably only be nonzero if we've got an input file
- which was produced by `ld -r' (i.e., it's already been processed
- through this code). Under some operating systems, native tools
- may make all empty strings have the same index; but the pointer
- check won't catch those, because to get to that stage we'd already
- have to compute the checksum, which requires reading the string,
- so we short-circuit that case with empty_string_index above. */
- unsigned long pointer_matches;
-
- /* Number of comparisons done. I figure with the algorithms in use below,
- the average number of comparisons done (per symbol) should be roughly
- log-base-2 of the number of unique strings. */
- unsigned long n_compares;
-#endif
+ /* Next string in strtab. */
+ struct strtab_hash_entry *next;
};
-/* Some utility functions for the string table code. */
+/* The strtab hash table. */
-/* For speed, only hash on the first this many bytes of strings.
- This number was chosen by profiling ld linking itself, with -g. */
-#define HASHMAXLEN 25
+struct strtab_hash
+{
+ struct bfd_hash_table table;
+ /* Size of strtab--also next available index. */
+ bfd_size_type size;
+ /* First string in strtab. */
+ struct strtab_hash_entry *first;
+ /* Last string in strtab. */
+ struct strtab_hash_entry *last;
+};
-#define HASH_CHAR(c) (sum ^= sum >> 20, sum ^= sum << 7, sum += (c))
+static struct bfd_hash_entry *strtab_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static boolean stringtab_init PARAMS ((struct strtab_hash *));
+static bfd_size_type add_to_stringtab
+ PARAMS ((bfd *, struct strtab_hash *, const char *, boolean));
+static boolean emit_stringtab PARAMS ((bfd *, struct strtab_hash *));
-static INLINE unsigned int
-hash (string, len)
- unsigned char *string;
- register unsigned int len;
+/* Routine to create an entry in a strtab. */
+
+static struct bfd_hash_entry *
+strtab_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
{
- register unsigned int sum = 0;
+ struct strtab_hash_entry *ret = (struct strtab_hash_entry *) entry;
- if (len > HASHMAXLEN)
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct strtab_hash_entry *) NULL)
+ ret = ((struct strtab_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct strtab_hash_entry)));
+ if (ret == (struct strtab_hash_entry *) NULL)
{
- HASH_CHAR (len);
- len = HASHMAXLEN;
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
}
- while (len--)
+ /* Call the allocation method of the superclass. */
+ ret = ((struct strtab_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+ if (ret)
{
- HASH_CHAR (*string++);
+ /* Initialize the local fields. */
+ ret->index = (bfd_size_type) -1;
+ ret->next = NULL;
}
- return sum;
-}
-static INLINE void
-stringtab_init (tab)
- struct stringtab_data *tab;
-{
- tab->strings = 0;
- tab->output_order = 0;
- tab->hash_zero = 0;
- tab->end = &tab->output_order;
-
- /* Initial string table length includes size of length field. */
- tab->index = BYTES_IN_WORD;
- tab->empty_string_index = -1;
-#ifdef GATHER_STATISTICS
- tab->duplicates = 0;
- tab->empty_strings = 0;
- tab->bad_hash_matches = 0;
- tab->pointer_matches = 0;
- tab->bytes_saved = 0;
- tab->n_compares = 0;
-#endif
+ return (struct bfd_hash_entry *) ret;
}
-static INLINE int
-compare (entry, str, hash)
- struct stringtab_entry *entry;
- CONST char *str;
- unsigned int hash;
-{
- return hash - entry->hash;
-}
+/* Look up an entry in an strtab. */
+
+#define strtab_hash_lookup(t, string, create, copy) \
+ ((struct strtab_hash_entry *) \
+ bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
-#ifdef GATHER_STATISTICS
-/* Don't want to have to link in math library with all bfd applications... */
-static INLINE double
-log2 (num)
- int num;
+/* Create a new strtab. */
+
+static boolean
+stringtab_init (table)
+ struct strtab_hash *table;
{
- double d = num;
- int n = 0;
- while (d >= 2.0)
- n++, d /= 2.0;
- return ((d > 1.41) ? 0.5 : 0) + n;
+ if (! bfd_hash_table_init (&table->table, strtab_hash_newfunc))
+ return false;
+
+ /* Leave space for the size of the string table. */
+ table->size = BYTES_IN_WORD;
+
+ table->first = NULL;
+ table->last = NULL;
+
+ return true;
}
-#endif
-/* Main string table routines. */
-/* Returns index in string table. Whether or not this actually adds an
- entry into the string table should be irrelevant -- it just has to
- return a valid index. */
-static bfd_size_type
-add_to_stringtab (abfd, str, tab)
+/* Free a strtab. */
+
+#define stringtab_free(tab) bfd_hash_table_free (&(tab)->table)
+
+/* Get the index of a string in a strtab, adding it if it is not
+ already present. If HASH is false, we don't really use the hash
+ table, and we don't eliminate duplicate strings. */
+
+static INLINE bfd_size_type
+add_to_stringtab (abfd, tab, str, copy)
bfd *abfd;
- CONST char *str;
- struct stringtab_data *tab;
+ struct strtab_hash *tab;
+ const char *str;
+ boolean copy;
{
- struct stringtab_entry **ep;
- register struct stringtab_entry *entry;
- unsigned int hashval, len;
-
- if (str[0] == 0)
- {
- bfd_size_type index;
- CONST bfd_size_type minus_one = -1;
+ register struct strtab_hash_entry *entry;
-#ifdef GATHER_STATISTICS
- tab->empty_strings++;
-#endif
- index = tab->empty_string_index;
- if (index != minus_one)
- {
- got_empty:
-#ifdef GATHER_STATISTICS
- tab->bytes_saved++;
- tab->duplicates++;
-#endif
- return index;
- }
+ /* An index of 0 always means the empty string. */
+ if (*str == '\0')
+ return 0;
- /* Need to find it. */
- entry = tab->strings;
- if (entry)
- {
- index = entry->index + strlen (entry->string);
- tab->empty_string_index = index;
- goto got_empty;
- }
- len = 0;
- }
- else
- len = strlen (str);
-
- /* The hash_zero value is chosen such that the first symbol gets a value of
- zero. With a balanced tree, this wouldn't be very useful, but without it,
- we might get a more even split at the top level, instead of skewing it
- badly should hash("/usr/lib/crt0.o") (or whatever) be far from zero. */
- hashval = hash (str, len) ^ tab->hash_zero;
- ep = &tab->strings;
- if (!*ep)
+ if ((abfd->flags & BFD_TRADITIONAL_FORMAT) == 0)
{
- tab->hash_zero = hashval;
- hashval = 0;
- goto add_it;
+ entry = strtab_hash_lookup (tab, str, true, copy);
+ if (entry == NULL)
+ return (bfd_size_type) -1;
}
-
- while (*ep)
+ else
{
- register int cmp;
-
- entry = *ep;
-#ifdef GATHER_STATISTICS
- tab->n_compares++;
-#endif
- cmp = compare (entry, str, hashval);
- /* The not-equal cases are more frequent, so check them first. */
- if (cmp > 0)
- ep = &entry->greater;
- else if (cmp < 0)
- ep = &entry->less;
+ entry = ((struct strtab_hash_entry *)
+ bfd_hash_allocate (&tab->table,
+ sizeof (struct strtab_hash_entry)));
+ if (entry == NULL)
+ return (bfd_size_type) -1;
+ if (! copy)
+ entry->root.string = str;
else
{
- if (entry->string == str)
- {
-#ifdef GATHER_STATISTICS
- tab->pointer_matches++;
-#endif
- goto match;
- }
- /* Compare the first bytes to save a function call if they
- don't match. */
- if (entry->string[0] == str[0] && !strcmp (entry->string, str))
- {
- match:
-#ifdef GATHER_STATISTICS
- entry->count++;
- tab->bytes_saved += len + 1;
- tab->duplicates++;
-#endif
- /* If we're in the linker, and the new string is from a new
- input file which might have already had these reductions
- run over it, we want to keep the new string pointer. I
- don't think we're likely to see any (or nearly as many,
- at least) cases where a later string is in the same location
- as an earlier one rather than this one. */
- entry->string = str;
- return entry->index;
- }
-#ifdef GATHER_STATISTICS
- tab->bad_hash_matches++;
-#endif
- ep = &entry->greater;
+ char *n;
+
+ n = (char *) bfd_hash_allocate (&tab->table, strlen (str) + 1);
+ if (n == NULL)
+ return (bfd_size_type) -1;
+ entry->root.string = n;
}
+ entry->index = (bfd_size_type) -1;
+ entry->next = NULL;
}
- /* If we get here, nothing that's in the table already matched.
- EP points to the `next' field at the end of the chain; stick a
- new entry on here. */
- add_it:
- entry = (struct stringtab_entry *)
- bfd_alloc_by_size_t (abfd, sizeof (struct stringtab_entry));
-
- entry->less = entry->greater = 0;
- entry->hash = hashval;
- entry->index = tab->index;
- entry->string = str;
- entry->next_to_output = 0;
-#ifdef GATHER_STATISTICS
- entry->count = 1;
-#endif
-
- assert (*tab->end == 0);
- *(tab->end) = entry;
- tab->end = &entry->next_to_output;
- assert (*tab->end == 0);
+ if (entry->index == (bfd_size_type) -1)
+ {
+ entry->index = tab->size;
+ tab->size += strlen (str) + 1;
+ if (tab->first == NULL)
+ tab->first = entry;
+ else
+ tab->last->next = entry;
+ tab->last = entry;
+ }
- {
- tab->index += len + 1;
- if (len == 0)
- tab->empty_string_index = entry->index;
- }
- assert (*ep == 0);
- *ep = entry;
return entry->index;
}
-static void
-emit_strtab (abfd, tab)
- bfd *abfd;
- struct stringtab_data *tab;
-{
- struct stringtab_entry *entry;
-#ifdef GATHER_STATISTICS
- int count = 0;
-#endif
+/* Write out a strtab. ABFD is already at the right location in the
+ file. */
- /* Be sure to put string length into correct byte ordering before writing
- it out. */
- char buffer[BYTES_IN_WORD];
+static boolean
+emit_stringtab (abfd, tab)
+ register bfd *abfd;
+ struct strtab_hash *tab;
+{
+ bfd_byte buffer[BYTES_IN_WORD];
+ register struct strtab_hash_entry *entry;
- PUT_WORD (abfd, tab->index, (unsigned char *) buffer);
- bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd);
+ PUT_WORD (abfd, tab->size, buffer);
+ 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)
+ for (entry = tab->first; entry != NULL; entry = entry->next)
{
- bfd_write ((PTR) entry->string, 1, strlen (entry->string) + 1, abfd);
-#ifdef GATHER_STATISTICS
- count++;
-#endif
- }
+ register const char *str;
+ register size_t len;
-#ifdef GATHER_STATISTICS
- /* Short form only, for now.
- To do: Specify output file. Conditionalize on environment? Detailed
- analysis if desired. */
- {
- int n_syms = bfd_get_symcount (abfd);
-
- fprintf (stderr, "String table data for output file:\n");
- fprintf (stderr, " %8d symbols output\n", n_syms);
- fprintf (stderr, " %8d duplicate strings\n", tab->duplicates);
- fprintf (stderr, " %8d empty strings\n", tab->empty_strings);
- fprintf (stderr, " %8d unique strings output\n", count);
- fprintf (stderr, " %8d pointer matches\n", tab->pointer_matches);
- fprintf (stderr, " %8d bytes saved\n", tab->bytes_saved);
- fprintf (stderr, " %8d bad hash matches\n", tab->bad_hash_matches);
- fprintf (stderr, " %8d hash-val comparisons\n", tab->n_compares);
- if (n_syms)
- {
- double n_compares = tab->n_compares;
- double avg_compares = n_compares / n_syms;
- /* The second value here should usually be near one. */
- fprintf (stderr,
- "\t average %f comparisons per symbol (%f * log2 nstrings)\n",
- avg_compares, avg_compares / log2 (count));
- }
- }
-#endif
-
-/* Old code:
- unsigned int count;
- generic = bfd_get_outsymbols(abfd);
- for (count = 0; count < bfd_get_symcount(abfd); count++)
- {
- asymbol *g = *(generic++);
+ str = entry->root.string;
+ len = strlen (str) + 1;
+ if (bfd_write ((PTR) str, 1, len, abfd) != len)
+ return false;
+ }
- if (g->name)
- {
- size_t length = strlen(g->name)+1;
- bfd_write((PTR)g->name, 1, length, abfd);
- }
- g->KEEPIT = (KEEPITTYPE) count;
- } */
+ return true;
}
-
+\f
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);
- struct stringtab_data strtab;
+ struct strtab_hash strtab;
- stringtab_init (&strtab);
+ if (! stringtab_init (&strtab))
+ return false;
for (count = 0; count < bfd_get_symcount (abfd); count++)
{
asymbol *g = generic[count];
+ bfd_size_type indx;
struct external_nlist nsp;
- if (g->name)
- PUT_WORD (abfd, add_to_stringtab (abfd, g->name, &strtab),
- (unsigned char *) nsp.e_strx);
- else
- PUT_WORD (abfd, 0, (unsigned char *)nsp.e_strx);
+ indx = add_to_stringtab (abfd, &strtab, g->name, false);
+ if (indx == (bfd_size_type) -1)
+ goto error_return;
+ PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx);
if (bfd_asymbol_flavour(g) == abfd->xvec->flavour)
{
bfd_h_put_8(abfd, 0, nsp.e_type);
}
- if (! translate_to_native_sym_flags (&nsp, g, abfd))
- return false;
+ if (! translate_to_native_sym_flags (abfd, g, &nsp))
+ goto error_return;
if (bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd)
!= EXTERNAL_NLIST_SIZE)
- return false;
+ goto error_return;
/* NB: `KEEPIT' currently overlays `flags', so set this only
here, at the end. */
g->KEEPIT = count;
}
- emit_strtab (abfd, &strtab);
+ if (! emit_stringtab (abfd, &strtab))
+ goto error_return;
+
+ stringtab_free (&strtab);
return true;
+
+error_return:
+ stringtab_free (&strtab);
+ return false;
}
\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 (section == obj_bsssec (abfd))
+ {
+ *relptr = NULL;
+ return 0;
+ }
+
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));
+
+ if (asect == obj_bsssec (abfd))
+ return sizeof (arelent *);
- 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;
}
-\f
-/* a.out link code. */
-/* a.out linker hash table entries. */
+/* Free all information we have cached for this BFD. We can always
+ read it again later if we need it. */
-struct aout_link_hash_entry
+boolean
+NAME(aout,bfd_free_cached_info) (abfd)
+ bfd *abfd;
{
- struct bfd_link_hash_entry root;
- /* Symbol index in output file. */
- int indx;
-};
+ asection *o;
-/* a.out linker hash table. */
+ if (bfd_get_format (abfd) != bfd_object)
+ return true;
-struct aout_link_hash_table
-{
- struct bfd_link_hash_table root;
-};
+#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. */
-static struct bfd_hash_entry *aout_link_hash_newfunc
- PARAMS ((struct bfd_hash_entry *entry,
- struct bfd_hash_table *table,
- const char *string));
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));
/* Routine to create an entry in an a.out link hash table. */
-static struct bfd_hash_entry *
-aout_link_hash_newfunc (entry, table, string)
+struct bfd_hash_entry *
+NAME(aout,link_hash_newfunc) (entry, table, string)
struct bfd_hash_entry *entry;
struct bfd_hash_table *table;
const char *string;
if (ret == (struct aout_link_hash_entry *) NULL)
ret = ((struct aout_link_hash_entry *)
bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry)));
+ if (ret == (struct aout_link_hash_entry *) NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return (struct bfd_hash_entry *) ret;
+ }
/* Call the allocation method of the superclass. */
ret = ((struct aout_link_hash_entry *)
_bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
table, string));
+ if (ret)
+ {
+ /* Set local fields. */
+ ret->written = false;
+ ret->indx = -1;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
- /* Set local fields. */
- ret->indx = -1;
+/* Initialize an a.out link hash table. */
- return (struct bfd_hash_entry *) ret;
+boolean
+NAME(aout,link_hash_table_init) (table, abfd, newfunc)
+ struct aout_link_hash_table *table;
+ bfd *abfd;
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+{
+ return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
}
/* Create an a.out link hash table. */
struct aout_link_hash_table *ret;
ret = ((struct aout_link_hash_table *)
- bfd_xmalloc (sizeof (struct aout_link_hash_table)));
- if (! _bfd_link_hash_table_init (&ret->root, abfd,
- aout_link_hash_newfunc))
+ malloc (sizeof (struct aout_link_hash_table)));
+ if (ret == (struct aout_link_hash_table *) NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+ if (! NAME(aout,link_hash_table_init) (ret, abfd,
+ NAME(aout,link_hash_newfunc)))
{
free (ret);
return (struct bfd_link_hash_table *) NULL;
return &ret->root;
}
-/* Look up an entry in an a.out link hash table. */
-
-#define aout_link_hash_lookup(table, string, create, copy, follow) \
- ((struct aout_link_hash_entry *) \
- bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow)))
-
-/* Traverse an a.out link hash table. */
-
-#define aout_link_hash_traverse(table, func, info) \
- (bfd_link_hash_traverse \
- (&(table)->root, \
- (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
- (info)))
-
-/* Get the a.out link hash table from the info structure. This is
- just a cast. */
-
-#define aout_hash_table(p) ((struct aout_link_hash_table *) ((p)->hash))
-
/* Given an a.out BFD, add symbols to the global hash table as
appropriate. */
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 bfd_xmalloc to make the values easy to free
- later on. If we put them on the obstack it might not be possible
- to free them. */
- syms = ((struct external_nlist *)
- bfd_xmalloc ((size_t) count * EXTERNAL_NLIST_SIZE));
-
- if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
- || (bfd_read ((PTR) syms, 1, exec_hdr (abfd)->a_syms, abfd)
- != exec_hdr (abfd)->a_syms))
- return false;
-
- /* Get the size of the strings. */
- if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
- || (bfd_read ((PTR) string_chars, BYTES_IN_WORD, 1, abfd)
- != BYTES_IN_WORD))
- return false;
- stringsize = GET_WORD (abfd, string_chars);
- strings = (char *) bfd_xmalloc ((size_t) stringsize);
-
- /* Skip space for the string count in the buffer for convenience
- when using indexes. */
- if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD, abfd)
- != stringsize - BYTES_IN_WORD)
- return false;
-
- /* Save the data. */
- obj_aout_external_syms (abfd) = syms;
- obj_aout_external_sym_count (abfd) = count;
- obj_aout_external_strings (abfd) = strings;
-
- return true;
-}
-
/* Free up the internal symbols read from an a.out file. */
static boolean
const char *name;
struct bfd_link_hash_entry *h;
- /* Ignore symbols that are not externally visible. */
- if ((type & N_EXT) == 0)
+ /* Ignore symbols that are not externally visible. This is an
+ optimization only, as we check the type more thoroughly
+ below. */
+ if ((type & N_EXT) == 0
+ && type != N_WEAKA
+ && type != N_WEAKT
+ && type != N_WEAKD
+ && type != N_WEAKB)
{
if (type == N_WARNING
|| type == N_INDR)
int a;
and this object file from the archive includes
int a = 5;
- In such a case we must include this object file. */
+ In such a case we must include this object file.
+
+ FIXME: The SunOS 4.1.3 linker will pull in the archive
+ element if the symbol is defined in the .data section,
+ but not if it is defined in the .text section. That
+ seems a bit crazy to me, and I haven't implemented it.
+ However, it might be correct. */
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
return false;
*pneeded = true;
}
}
}
+
+ if (type == N_WEAKA
+ || type == N_WEAKT
+ || type == N_WEAKD
+ || type == N_WEAKB)
+ {
+ /* This symbol is weak but defined. We must pull it in if
+ the current link symbol is undefined, but we don't want
+ it if the current link symbol is common. */
+ if (h->type == bfd_link_hash_undefined)
+ {
+ if (! (*info->callbacks->add_archive_element) (info, abfd, name))
+ return false;
+ *pneeded = true;
+ return true;
+ }
+ }
}
/* We do not need this object file. */
bfd *abfd;
struct bfd_link_info *info;
{
+ boolean (*add_one_symbol) PARAMS ((struct bfd_link_info *, bfd *,
+ const char *, flagword, asection *,
+ bfd_vma, const char *, boolean,
+ boolean,
+ struct bfd_link_hash_entry **));
bfd_size_type sym_count;
char *strings;
boolean copy;
bfd_alloc (abfd,
((size_t) sym_count
* sizeof (struct aout_link_hash_entry *))));
+ if (sym_hash == NULL && sym_count != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
obj_aout_sym_hashes (abfd) = sym_hash;
+ if ((abfd->flags & DYNAMIC) != 0
+ && aout_backend_info (abfd)->add_dynamic_symbols != NULL)
+ {
+ if (! (*aout_backend_info (abfd)->add_dynamic_symbols) (abfd, info))
+ return false;
+ }
+
+ add_one_symbol = aout_backend_info (abfd)->add_one_symbol;
+ if (add_one_symbol == NULL)
+ add_one_symbol = _bfd_generic_link_add_one_symbol;
+
p = obj_aout_external_syms (abfd);
pend = p + sym_count;
for (; p < pend; p++, sym_hash++)
if ((type & N_STAB) != 0)
continue;
- /* Ignore symbols that are not external. */
- if ((type & N_EXT) == 0
- && type != N_WARNING
- && type != N_SETA
- && type != N_SETT
- && type != N_SETD
- && type != N_SETB)
- {
- /* If this is an N_INDR symbol we must skip the next entry,
- which is the symbol to indirect to (actually, an N_INDR
- symbol without N_EXT set is pretty useless). */
- if (type == N_INDR)
- {
- ++p;
- ++sym_hash;
- }
- continue;
- }
-
- /* Ignore N_FN symbols (these appear to have N_EXT set). */
- if (type == N_FN)
- continue;
-
name = strings + GET_WORD (abfd, p->e_strx);
value = GET_WORD (abfd, p->e_value);
flags = BSF_GLOBAL;
{
default:
abort ();
+
+ case N_UNDF:
+ case N_ABS:
+ case N_TEXT:
+ case N_DATA:
+ case N_BSS:
+ case N_FN_SEQ:
+ case N_COMM:
+ case N_SETV:
+ case N_FN:
+ /* Ignore symbols that are not externally visible. */
+ continue;
+ case N_INDR:
+ /* Ignore local indirect symbol. */
+ ++p;
+ ++sym_hash;
+ continue;
+
case N_UNDF | N_EXT:
- if (value != 0)
- section = &bfd_com_section;
+ if (value == 0)
+ {
+ section = &bfd_und_section;
+ flags = 0;
+ }
else
- section = &bfd_und_section;
+ section = &bfd_com_section;
break;
case N_ABS | N_EXT:
section = &bfd_abs_section;
value -= bfd_get_section_vma (abfd, section);
break;
case N_DATA | N_EXT:
+ case N_SETV | N_EXT:
+ /* Treat N_SETV symbols as N_DATA symbol; see comment in
+ translate_from_native_sym_flags. */
section = obj_datasec (abfd);
value -= bfd_get_section_vma (abfd, section);
break;
section = &bfd_und_section;
flags |= BSF_WARNING;
break;
+ case N_WEAKU:
+ section = &bfd_und_section;
+ flags = BSF_WEAK;
+ break;
+ case N_WEAKA:
+ section = &bfd_abs_section;
+ flags = BSF_WEAK;
+ break;
+ case N_WEAKT:
+ section = obj_textsec (abfd);
+ value -= bfd_get_section_vma (abfd, section);
+ flags = BSF_WEAK;
+ break;
+ case N_WEAKD:
+ section = obj_datasec (abfd);
+ value -= bfd_get_section_vma (abfd, section);
+ flags = BSF_WEAK;
+ break;
+ case N_WEAKB:
+ section = obj_bsssec (abfd);
+ value -= bfd_get_section_vma (abfd, section);
+ flags = BSF_WEAK;
+ break;
}
- if (! (_bfd_generic_link_add_one_symbol
+ if (! ((*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)
/* File position of symbols. */
file_ptr symoff;
/* String table. */
- struct stringtab_data strtab;
+ struct strtab_hash strtab;
};
static boolean aout_link_input_bfd
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;
}
obj_aout_external_sym_count (abfd) = 0;
/* We accumulate the string table as we write out the symbols. */
- stringtab_init (&aout_info.strtab);
+ if (! stringtab_init (&aout_info.strtab))
+ return false;
/* The most time efficient way to do the link would be to read all
the input object files into memory and then sort out the
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;
+ }
+ }
+ }
+ }
+
+ /* Finish up any dynamic linking we may be doing. */
+ if (aout_backend_info (abfd)->finish_dynamic_link != NULL)
+ {
+ if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info))
+ return false;
+ }
+
/* 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_stringtab (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);
+ /* If this is a dynamic object, it may need special handling. */
+ if ((input_bfd->flags & DYNAMIC) != 0
+ && aout_backend_info (input_bfd)->link_dynamic_object != NULL)
+ {
+ return ((*aout_backend_info (input_bfd)->link_dynamic_object)
+ (finfo->info, 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);
- 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;
+ bfd_size_type strtab_index;
register struct external_nlist *sym;
struct external_nlist *sym_end;
struct aout_link_hash_entry **sym_hash;
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
bfd_h_put_8 (output_bfd, N_TEXT, outsym->e_type);
bfd_h_put_8 (output_bfd, 0, outsym->e_other);
bfd_h_put_16 (output_bfd, (bfd_vma) 0, outsym->e_desc);
- PUT_WORD (output_bfd,
- add_to_stringtab (output_bfd, input_bfd->filename,
- &finfo->strtab),
- outsym->e_strx);
+ strtab_index = add_to_stringtab (output_bfd, &finfo->strtab,
+ input_bfd->filename, false);
+ if (strtab_index == (bfd_size_type) -1)
+ goto error_return;
+ PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
PUT_WORD (output_bfd,
(bfd_get_section_vma (output_bfd,
obj_textsec (input_bfd)->output_section)
{
const char *name;
int type;
+ struct aout_link_hash_entry *h;
boolean skip;
asection *symsec;
bfd_vma val = 0;
+ boolean copy;
*symbol_map = -1;
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
|| h->root.type == bfd_link_hash_warning))
{
hresolve = (struct aout_link_hash_entry *) h->root.u.i.link;
- while (hresolve->root.type == bfd_link_hash_indirect)
+ while (hresolve->root.type == bfd_link_hash_indirect
+ || hresolve->root.type == bfd_link_hash_warning)
hresolve = ((struct aout_link_hash_entry *)
hresolve->root.u.i.link);
*sym_hash = hresolve;
/* If the symbol has already been written out, skip it. */
if (h != (struct aout_link_hash_entry *) NULL
- && h->root.written)
+ && h->root.type != bfd_link_hash_warning
+ && h->written)
{
+ if ((type & N_TYPE) == N_INDR)
+ skip_indirect = true;
*symbol_map = h->indx;
continue;
}
if (skip)
{
if (h != (struct aout_link_hash_entry *) NULL)
- h->root.written = true;
+ h->written = true;
continue;
}
/* Get the value of the symbol. */
- if ((type & N_TYPE) == N_TEXT)
+ if ((type & N_TYPE) == N_TEXT
+ || type == N_WEAKT)
symsec = obj_textsec (input_bfd);
- else if ((type & N_TYPE) == N_DATA)
+ else if ((type & N_TYPE) == N_DATA
+ || type == N_WEAKD)
symsec = obj_datasec (input_bfd);
- else if ((type & N_TYPE) == N_BSS)
+ else if ((type & N_TYPE) == N_BSS
+ || type == N_WEAKB)
symsec = obj_bsssec (input_bfd);
- else if ((type & N_TYPE) == N_ABS)
+ else if ((type & N_TYPE) == N_ABS
+ || type == N_WEAKA)
symsec = &bfd_abs_section;
else if (((type & N_TYPE) == N_INDR
&& (hresolve == (struct aout_link_hash_entry *) NULL
}
else if (hresolve->root.type == bfd_link_hash_common)
val = hresolve->root.u.c.size;
+ else if (hresolve->root.type == bfd_link_hash_weak)
+ {
+ val = 0;
+ type = N_WEAKU;
+ }
else
val = 0;
it is a local symbol see if we should discard it. */
if (h != (struct aout_link_hash_entry *) NULL)
{
- h->root.written = true;
+ h->written = true;
h->indx = obj_aout_external_sym_count (output_bfd);
}
else
outsym->e_other);
bfd_h_put_16 (output_bfd, bfd_h_get_16 (input_bfd, sym->e_desc),
outsym->e_desc);
- PUT_WORD (output_bfd,
- add_to_stringtab (output_bfd, name, &finfo->strtab),
- outsym->e_strx);
+ copy = false;
+ 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
+ copy = true;
+ }
+ strtab_index = add_to_stringtab (output_bfd, &finfo->strtab,
+ name, copy);
+ if (strtab_index == (bfd_size_type) -1)
+ goto error_return;
+ PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
PUT_WORD (output_bfd, val, outsym->e_value);
*symbol_map = obj_aout_external_sym_count (output_bfd);
++obj_aout_external_sym_count (output_bfd);
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 type;
bfd_vma val;
struct external_nlist outsym;
+ bfd_size_type indx;
+
+ output_bfd = finfo->output_bfd;
+
+ if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL)
+ {
+ if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol)
+ (output_bfd, finfo->info, h)))
+ {
+ /* FIXME: No way to handle errors. */
+ abort ();
+ }
+ }
- if (h->root.written)
+ if (h->written)
return true;
- output_bfd = finfo->output_bfd;
+ h->written = true;
+
+ if (finfo->info->strip == strip_all
+ || (finfo->info->strip == strip_some
+ && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string,
+ false, false) == NULL))
+ return true;
switch (h->root.type)
{
{
asection *sec;
- sec = h->root.u.def.section;
+ sec = h->root.u.def.section->output_section;
BFD_ASSERT (sec == &bfd_abs_section
|| sec->owner == output_bfd);
if (sec == obj_textsec (output_bfd))
else
type = N_ABS | N_EXT;
val = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
+ + sec->vma
+ + h->root.u.def.section->output_offset);
}
break;
case bfd_link_hash_common:
type = N_UNDF | N_EXT;
val = h->root.u.c.size;
break;
+ case bfd_link_hash_weak:
+ type = N_WEAKU;
+ val = 0;
case bfd_link_hash_indirect:
case bfd_link_hash_warning:
/* FIXME: Ignore these for now. The circumstances under which
bfd_h_put_8 (output_bfd, type, outsym.e_type);
bfd_h_put_8 (output_bfd, 0, outsym.e_other);
bfd_h_put_16 (output_bfd, 0, outsym.e_desc);
- PUT_WORD (output_bfd,
- add_to_stringtab (output_bfd, h->root.root.string, &finfo->strtab),
- outsym.e_strx);
+ indx = add_to_stringtab (output_bfd, &finfo->strtab, h->root.root.string,
+ false);
+ if (indx == (bfd_size_type) -1)
+ {
+ /* FIXME: No way to handle errors. */
+ abort ();
+ }
+ PUT_WORD (output_bfd, indx, outsym.e_strx);
PUT_WORD (output_bfd, val, outsym.e_value);
if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0
int *symbol_map;
{
bfd_size_type input_size;
- bfd_byte *contents;
+ bfd_byte *contents = NULL;
PTR relocs;
+ PTR free_relocs = NULL;
/* Get the section contents. */
input_size = bfd_section_size (input_bfd, input_section);
- contents = (bfd_byte *) 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);
- if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
- || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size)
- return false;
+ /* Read in the relocs if we haven't already done it. */
+ if (aout_section_data (input_section) != NULL
+ && aout_section_data (input_section)->relocs != NULL)
+ relocs = aout_section_data (input_section)->relocs;
+ else
+ {
+ relocs = free_relocs = (PTR) malloc (rel_size);
+ if (relocs == NULL && rel_size != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+ if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
+ || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size)
+ goto error_return;
+ }
/* 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 (free_relocs != NULL)
+ free (free_relocs);
+ if (contents != NULL)
+ free (contents);
return true;
+ error_return:
+ if (free_relocs != NULL)
+ free (free_relocs);
+ if (contents != NULL)
+ free (contents);
+ return false;
}
/* Get the section corresponding to a reloc index. */
bfd_byte *contents;
int *symbol_map;
{
+ boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *,
+ bfd *, asection *,
+ struct aout_link_hash_entry *,
+ PTR, boolean *));
bfd *output_bfd;
boolean relocateable;
struct external_nlist *syms;
struct reloc_std_external *rel_end;
output_bfd = finfo->output_bfd;
+ check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE);
BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p
>> 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)
{
struct aout_link_hash_entry *h;
h = sym_hashes[r_index];
+
+ if (check_dynamic_reloc != NULL)
+ {
+ boolean skip;
+
+ if (! ((*check_dynamic_reloc)
+ (finfo->info, input_bfd, input_section, h,
+ (PTR) rel, &skip)))
+ return false;
+ if (skip)
+ continue;
+ }
+
if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type == bfd_link_hash_defined)
{
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
}
+ else if (h != (struct aout_link_hash_entry *) NULL
+ && h->root.type == bfd_link_hash_weak)
+ relocation = 0;
else
{
const char *name;
bfd_byte *contents;
int *symbol_map;
{
+ boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *,
+ bfd *, asection *,
+ struct aout_link_hash_entry *,
+ PTR, boolean *));
bfd *output_bfd;
boolean relocateable;
struct external_nlist *syms;
struct reloc_ext_external *rel_end;
output_bfd = finfo->output_bfd;
+ check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE);
BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p
struct aout_link_hash_entry *h;
h = sym_hashes[r_index];
+
+ if (check_dynamic_reloc != NULL)
+ {
+ boolean skip;
+
+ if (! ((*check_dynamic_reloc)
+ (finfo->info, input_bfd, input_section, h,
+ (PTR) rel, &skip)))
+ return false;
+ if (skip)
+ continue;
+ }
+
if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type == bfd_link_hash_defined)
{
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
}
+ else if (h != (struct aout_link_hash_entry *) NULL
+ && h->root.type == bfd_link_hash_weak)
+ relocation = 0;
else
{
const char *name;
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;
+}