/* BFD semi-generic back-end for a.out binaries.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
#define KEEPIT udata.i
#include <string.h> /* For strchr and friends */
+#include <ctype.h>
#include "bfd.h"
#include <sysdep.h>
#include "bfdlink.h"
HOWTO(RELOC_LO10, 0, 2, 10, false, 0, complain_overflow_dont,0,"LO10", false, 0,0x000003ff, false),
HOWTO(RELOC_SFA_BASE,0, 2, 32, false, 0, complain_overflow_bitfield,0,"SFA_BASE", false, 0,0xffffffff, false),
HOWTO(RELOC_SFA_OFF13,0,2, 32, false, 0, complain_overflow_bitfield,0,"SFA_OFF13",false, 0,0xffffffff, false),
- HOWTO(RELOC_BASE10, 0, 2, 16, false, 0, complain_overflow_bitfield,0,"BASE10", false, 0,0x0000ffff, false),
+ HOWTO(RELOC_BASE10, 0, 2, 10, false, 0, complain_overflow_dont,0,"BASE10", false, 0,0x000003ff, false),
HOWTO(RELOC_BASE13, 0, 2, 13, false, 0, complain_overflow_bitfield,0,"BASE13", false, 0,0x00001fff, false),
- HOWTO(RELOC_BASE22, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"BASE22", false, 0,0x00000000, false),
+ HOWTO(RELOC_BASE22, 10, 2, 22, false, 0, complain_overflow_bitfield,0,"BASE22", false, 0,0x003fffff, false),
HOWTO(RELOC_PC10, 0, 2, 10, true, 0, complain_overflow_dont,0,"PC10", false, 0,0x000003ff, true),
HOWTO(RELOC_PC22, 10, 2, 22, true, 0, complain_overflow_signed,0,"PC22", false, 0,0x003fffff, true),
HOWTO(RELOC_JMP_TBL,2, 2, 30, true, 0, complain_overflow_signed,0,"JMP_TBL", false, 0,0x3fffffff, false),
the default text start (obj_textsec(abfd)->vma) and
(obj_textsec(abfd)->vma) + text size. This is not just a mach
issue. Many kernels are loaded at non standard addresses. */
- if (abfd->iostream
+ if (abfd->iostream != NULL
+ && (abfd->flags & BFD_IN_MEMORY) == 0
&& (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
&& ((stat_buf.st_mode & 0111) != 0))
abfd->flags |= EXEC_P;
}
/* now the fun stuff */
- if (abfd->xvec->header_byteorder_big_p != false) {
+ if (bfd_header_big_endian (abfd)) {
natptr->r_index[0] = r_index >> 16;
natptr->r_index[1] = r_index >> 8;
natptr->r_index[2] = r_index;
}
/* now the fun stuff */
- if (abfd->xvec->header_byteorder_big_p != false) {
+ if (bfd_header_big_endian (abfd)) {
natptr->r_index[0] = r_index >> 16;
natptr->r_index[1] = r_index >> 8;
natptr->r_index[2] = r_index;
cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
/* now the fun stuff */
- if (abfd->xvec->header_byteorder_big_p != false) {
+ if (bfd_header_big_endian (abfd)) {
r_index = (bytes->r_index[0] << 16)
| (bytes->r_index[1] << 8)
| bytes->r_index[2];
cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
/* now the fun stuff */
- if (abfd->xvec->header_byteorder_big_p != false) {
+ if (bfd_header_big_endian (abfd)) {
r_index = (bytes->r_index[0] << 16)
| (bytes->r_index[1] << 8)
| bytes->r_index[2];
stab_name = buf;
}
ret->type = '-';
+ ret->stab_type = type_code;
ret->stab_other = (unsigned)(aout_symbol(symbol)->other & 0xff);
ret->stab_desc = (unsigned)(aout_symbol(symbol)->desc & 0xffff);
ret->stab_name = stab_name;
return true;
}
+\f
+/* A hash table used for header files with N_BINCL entries. */
+
+struct aout_link_includes_table
+{
+ struct bfd_hash_table root;
+};
+
+/* A linked list of totals that we have found for a particular header
+ file. */
+
+struct aout_link_includes_totals
+{
+ struct aout_link_includes_totals *next;
+ bfd_vma total;
+};
+
+/* An entry in the header file hash table. */
+
+struct aout_link_includes_entry
+{
+ struct bfd_hash_entry root;
+ /* List of totals we have found for this file. */
+ struct aout_link_includes_totals *totals;
+};
+
+/* Look up an entry in an the header file hash table. */
+
+#define aout_link_includes_lookup(table, string, create, copy) \
+ ((struct aout_link_includes_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
/* During the final link step we need to pass around a bunch of
information, so we do it in an instance of this structure. */
file_ptr symoff;
/* String table. */
struct bfd_strtab_hash *strtab;
+ /* Header file hash table. */
+ struct aout_link_includes_table includes;
/* A buffer large enough to hold the contents of any section. */
bfd_byte *contents;
/* A buffer large enough to hold the relocs of any section. */
struct external_nlist *output_syms;
};
+static struct bfd_hash_entry *aout_link_includes_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
static boolean aout_link_input_bfd
PARAMS ((struct aout_final_link_info *, bfd *input_bfd));
static boolean aout_link_write_symbols
PARAMS ((struct aout_final_link_info *, asection *,
struct bfd_link_order *));
+/* The function to create a new entry in the header file hash table. */
+
+static struct bfd_hash_entry *
+aout_link_includes_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct aout_link_includes_entry *ret =
+ (struct aout_link_includes_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct aout_link_includes_entry *) NULL)
+ ret = ((struct aout_link_includes_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct aout_link_includes_entry)));
+ if (ret == (struct aout_link_includes_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct aout_link_includes_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+ if (ret)
+ {
+ /* Set local fields. */
+ ret->totals = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
/* 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
link_next field which can be used to find each BFD which takes part
void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
{
struct aout_final_link_info aout_info;
+ boolean includes_hash_initialized = false;
register bfd *sub;
bfd_size_type trsize, drsize;
size_t max_contents_size;
aout_info.output_bfd = abfd;
aout_info.contents = NULL;
aout_info.relocs = NULL;
+ aout_info.symbol_map = NULL;
+ aout_info.output_syms = NULL;
+
+ if (! bfd_hash_table_init_n (&aout_info.includes.root,
+ aout_link_includes_newfunc,
+ 251))
+ goto error_return;
+ includes_hash_initialized = true;
/* Figure out the largest section size. Also, if generating
relocateable output, count the relocs. */
free (aout_info.output_syms);
aout_info.output_syms = NULL;
}
+ if (includes_hash_initialized)
+ {
+ bfd_hash_table_free (&aout_info.includes.root);
+ includes_hash_initialized = false;
+ }
/* Finish up any dynamic linking we may be doing. */
if (aout_backend_info (abfd)->finish_dynamic_link != NULL)
free (aout_info.symbol_map);
if (aout_info.output_syms != NULL)
free (aout_info.output_syms);
+ if (includes_hash_initialized)
+ bfd_hash_table_free (&aout_info.includes.root);
return false;
}
sym_end = sym + sym_count;
sym_hash = obj_aout_sym_hashes (input_bfd);
symbol_map = finfo->symbol_map;
+ memset (symbol_map, 0, sym_count * sizeof *symbol_map);
for (; sym < sym_end; sym++, sym_hash++, symbol_map++)
{
const char *name;
bfd_vma val = 0;
boolean copy;
+ /* We set *symbol_map to 0 above for all symbols. If it has
+ already been set to -1 for this symbol, it means that we are
+ discarding it because it appears in a duplicate header file.
+ See the N_BINCL code below. */
+ if (*symbol_map == -1)
+ continue;
+
+ /* Initialize *symbol_map to -1, which means that the symbol was
+ not copied into the output file. We will change it later if
+ we do copy the symbol over. */
*symbol_map = -1;
type = bfd_h_get_8 (input_bfd, sym->e_type);
continue;
}
}
+
+ /* An N_BINCL symbol indicates the start of the stabs
+ entries for a header file. We need to scan ahead to the
+ next N_EINCL symbol, ignoring nesting, adding up all the
+ characters in the symbol names, not including the file
+ numbers in types (the first number after an open
+ parenthesis). */
+ if (type == N_BINCL)
+ {
+ struct external_nlist *incl_sym;
+ int nest;
+ struct aout_link_includes_entry *incl_entry;
+ struct aout_link_includes_totals *t;
+
+ val = 0;
+ nest = 0;
+ for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++)
+ {
+ int incl_type;
+
+ incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type);
+ if (incl_type == N_EINCL)
+ {
+ if (nest == 0)
+ break;
+ --nest;
+ }
+ else if (incl_type == N_BINCL)
+ ++nest;
+ else if (nest == 0)
+ {
+ const char *s;
+
+ s = strings + GET_WORD (input_bfd, incl_sym->e_strx);
+ for (; *s != '\0'; s++)
+ {
+ val += *s;
+ if (*s == '(')
+ {
+ /* Skip the file number. */
+ ++s;
+ while (isdigit ((unsigned char) *s))
+ ++s;
+ --s;
+ }
+ }
+ }
+ }
+
+ /* If we have already included a header file with the
+ same value, then replace this one with an N_EXCL
+ symbol. */
+ copy = ! finfo->info->keep_memory;
+ incl_entry = aout_link_includes_lookup (&finfo->includes,
+ name, true, copy);
+ if (incl_entry == NULL)
+ return false;
+ for (t = incl_entry->totals; t != NULL; t = t->next)
+ if (t->total == val)
+ break;
+ if (t == NULL)
+ {
+ /* This is the first time we have seen this header
+ file with this set of stabs strings. */
+ t = ((struct aout_link_includes_totals *)
+ bfd_hash_allocate (&finfo->includes.root,
+ sizeof *t));
+ if (t == NULL)
+ return false;
+ t->total = val;
+ t->next = incl_entry->totals;
+ incl_entry->totals = t;
+ }
+ else
+ {
+ int *incl_map;
+
+ /* This is a duplicate header file. We must change
+ it to be an N_EXCL entry, and mark all the
+ included symbols to prevent outputting them. */
+ type = N_EXCL;
+
+ nest = 0;
+ for (incl_sym = sym + 1, incl_map = symbol_map + 1;
+ incl_sym < sym_end;
+ incl_sym++, incl_map++)
+ {
+ int incl_type;
+
+ incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type);
+ if (incl_type == N_EINCL)
+ {
+ if (nest == 0)
+ {
+ *incl_map = -1;
+ break;
+ }
+ --nest;
+ }
+ else if (incl_type == N_BINCL)
+ ++nest;
+ else if (nest == 0)
+ *incl_map = -1;
+ }
+ }
+ }
}
/* Copy this symbol into the list of symbols we are going to
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
- == output_bfd->xvec->header_byteorder_big_p);
+ BFD_ASSERT (input_bfd->xvec->header_byteorder
+ == output_bfd->xvec->header_byteorder);
relocateable = finfo->info->relocateable;
syms = obj_aout_external_syms (input_bfd);
int r_length;
unsigned int howto_idx;
- if (input_bfd->xvec->header_byteorder_big_p)
+ if (bfd_header_big_endian (input_bfd))
{
r_index = ((rel->r_index[0] << 16)
| (rel->r_index[1] << 8)
asection *output_section;
/* Change the r_extern value. */
- if (output_bfd->xvec->header_byteorder_big_p)
+ if (bfd_header_big_endian (output_bfd))
rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG;
else
rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE;
}
/* Write out the new r_index value. */
- if (output_bfd->xvec->header_byteorder_big_p)
+ if (bfd_header_big_endian (output_bfd))
{
rel->r_index[0] = r_index >> 16;
rel->r_index[1] = r_index >> 8;
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
- == output_bfd->xvec->header_byteorder_big_p);
+ BFD_ASSERT (input_bfd->xvec->header_byteorder
+ == output_bfd->xvec->header_byteorder);
relocateable = finfo->info->relocateable;
syms = obj_aout_external_syms (input_bfd);
r_addr = GET_SWORD (input_bfd, rel->r_address);
- if (input_bfd->xvec->header_byteorder_big_p)
+ if (bfd_header_big_endian (input_bfd))
{
r_index = ((rel->r_index[0] << 16)
| (rel->r_index[1] << 8)
asection *output_section;
/* Change the r_extern value. */
- if (output_bfd->xvec->header_byteorder_big_p)
+ if (bfd_header_big_endian (output_bfd))
rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG;
else
rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE;
}
/* Write out the new r_index value. */
- if (output_bfd->xvec->header_byteorder_big_p)
+ if (bfd_header_big_endian (output_bfd))
{
rel->r_index[0] = r_index >> 16;
rel->r_index[1] = r_index >> 8;
r_length = howto->size;
PUT_WORD (finfo->output_bfd, p->offset, srel.r_address);
- if (finfo->output_bfd->xvec->header_byteorder_big_p)
+ if (bfd_header_big_endian (finfo->output_bfd))
{
srel.r_index[0] = r_index >> 16;
srel.r_index[1] = r_index >> 8;
{
PUT_WORD (finfo->output_bfd, p->offset, erel.r_address);
- if (finfo->output_bfd->xvec->header_byteorder_big_p)
+ if (bfd_header_big_endian (finfo->output_bfd))
{
erel.r_index[0] = r_index >> 16;
erel.r_index[1] = r_index >> 8;