#include "coff/ecoff.h"
#include "libcoff.h"
#include "libecoff.h"
-\f
-/* Prototypes for static functions. */
-
-static int ecoff_get_magic
- PARAMS ((bfd *));
-static long ecoff_sec_to_styp_flags
- PARAMS ((const char *, flagword));
-static bfd_boolean ecoff_slurp_symbolic_header
- PARAMS ((bfd *));
-static bfd_boolean ecoff_set_symbol_info
- PARAMS ((bfd *, SYMR *, asymbol *, int, int));
-static void ecoff_emit_aggregate
- PARAMS ((bfd *, FDR *, char *, RNDXR *, long, const char *));
-static char *ecoff_type_to_string
- PARAMS ((bfd *, FDR *, unsigned int));
-static bfd_boolean ecoff_slurp_reloc_table
- PARAMS ((bfd *, asection *, asymbol **));
-static int ecoff_sort_hdrs
- PARAMS ((const PTR, const PTR));
-static bfd_boolean ecoff_compute_section_file_positions
- PARAMS ((bfd *));
-static bfd_size_type ecoff_compute_reloc_file_positions
- PARAMS ((bfd *));
-static bfd_boolean ecoff_get_extr
- PARAMS ((asymbol *, EXTR *));
-static void ecoff_set_index
- PARAMS ((asymbol *, bfd_size_type));
-static unsigned int ecoff_armap_hash
- PARAMS ((const char *, unsigned int *, unsigned int, unsigned int));
+#include "libiberty.h"
+
+#define streq(a, b) (strcmp ((a), (b)) == 0)
+#define strneq(a, b, n) (strncmp ((a), (b), (n)) == 0)
+
\f
/* This stuff is somewhat copied from coffcode.h. */
static asection bfd_debug_section =
/* target_index, used_by_bfd, constructor_chain, owner, */
0, NULL, NULL, NULL,
/* symbol, */
- (struct bfd_symbol *) NULL,
+ NULL,
/* symbol_ptr_ptr, */
- (struct bfd_symbol **) NULL,
+ NULL,
/* link_order_head, link_order_tail */
NULL, NULL
};
/* Create an ECOFF object. */
bfd_boolean
-_bfd_ecoff_mkobject (abfd)
- bfd *abfd;
+_bfd_ecoff_mkobject (bfd *abfd)
{
bfd_size_type amt = sizeof (ecoff_data_type);
- abfd->tdata.ecoff_obj_data = (struct ecoff_tdata *) bfd_zalloc (abfd, amt);
+ abfd->tdata.ecoff_obj_data = bfd_zalloc (abfd, amt);
if (abfd->tdata.ecoff_obj_data == NULL)
return FALSE;
/* This is a hook called by coff_real_object_p to create any backend
specific information. */
-PTR
-_bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
- bfd *abfd;
- PTR filehdr;
- PTR aouthdr;
+void *
+_bfd_ecoff_mkobject_hook (bfd *abfd, void * filehdr, void * aouthdr)
{
struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
ecoff->gp_size = 8;
ecoff->sym_filepos = internal_f->f_symptr;
- if (internal_a != (struct internal_aouthdr *) NULL)
+ if (internal_a != NULL)
{
int i;
fprmask) and let the swapping routines ensure that only relevant
information is written out. */
- return (PTR) ecoff;
+ return (void *) ecoff;
}
/* Initialize a new section. */
bfd_boolean
-_bfd_ecoff_new_section_hook (abfd, section)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *section;
+_bfd_ecoff_new_section_hook (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *section)
{
+ unsigned int i;
+ static struct
+ {
+ const char * name;
+ flagword flags;
+ }
+ section_flags [] =
+ {
+ { _TEXT, SEC_ALLOC | SEC_CODE | SEC_LOAD },
+ { _INIT, SEC_ALLOC | SEC_CODE | SEC_LOAD },
+ { _FINI, SEC_ALLOC | SEC_CODE | SEC_LOAD },
+ { _DATA, SEC_ALLOC | SEC_DATA | SEC_LOAD },
+ { _SDATA, SEC_ALLOC | SEC_DATA | SEC_LOAD },
+ { _RDATA, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
+ { _LIT8, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
+ { _LIT4, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
+ { _RCONST, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
+ { _PDATA, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY},
+ { _BSS, SEC_ALLOC},
+ { _SBSS, SEC_ALLOC},
+ /* An Irix 4 shared libary. */
+ { _LIB, SEC_COFF_SHARED_LIBRARY}
+ };
+
section->alignment_power = 4;
- if (strcmp (section->name, _TEXT) == 0
- || strcmp (section->name, _INIT) == 0
- || strcmp (section->name, _FINI) == 0)
- section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
- else if (strcmp (section->name, _DATA) == 0
- || strcmp (section->name, _SDATA) == 0)
- section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
- else if (strcmp (section->name, _RDATA) == 0
- || strcmp (section->name, _LIT8) == 0
- || strcmp (section->name, _LIT4) == 0
- || strcmp (section->name, _RCONST) == 0
- || strcmp (section->name, _PDATA) == 0)
- section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
- else if (strcmp (section->name, _BSS) == 0
- || strcmp (section->name, _SBSS) == 0)
- section->flags |= SEC_ALLOC;
- else if (strcmp (section->name, _LIB) == 0)
- /* An Irix 4 shared libary. */
- section->flags |= SEC_COFF_SHARED_LIBRARY;
+ for (i = 0; i < ARRAY_SIZE (section_flags); i++)
+ if (streq (section->name, section_flags[i].name))
+ {
+ section->flags |= section_flags[i].flags;
+ break;
+ }
+
/* Probably any other section name is SEC_NEVER_LOAD, but I'm
uncertain about .init on some systems and I don't know how shared
for each target, but there aren't all that many ECOFF targets. */
bfd_boolean
-_bfd_ecoff_set_arch_mach_hook (abfd, filehdr)
- bfd *abfd;
- PTR filehdr;
+_bfd_ecoff_set_arch_mach_hook (bfd *abfd, void * filehdr)
{
- struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+ struct internal_filehdr *internal_f = filehdr;
enum bfd_architecture arch;
unsigned long mach;
This is the inverse of _bfd_ecoff_set_arch_mach_hook, above. */
static int
-ecoff_get_magic (abfd)
- bfd *abfd;
+ecoff_get_magic (bfd *abfd)
{
int big, little;
/* Get the section s_flags to use for a section. */
static long
-ecoff_sec_to_styp_flags (name, flags)
- const char *name;
- flagword flags;
+ecoff_sec_to_styp_flags (const char *name, flagword flags)
{
- long styp;
-
- styp = 0;
-
- if (strcmp (name, _TEXT) == 0)
- styp = STYP_TEXT;
- else if (strcmp (name, _DATA) == 0)
- styp = STYP_DATA;
- else if (strcmp (name, _SDATA) == 0)
- styp = STYP_SDATA;
- else if (strcmp (name, _RDATA) == 0)
- styp = STYP_RDATA;
- else if (strcmp (name, _LITA) == 0)
- styp = STYP_LITA;
- else if (strcmp (name, _LIT8) == 0)
- styp = STYP_LIT8;
- else if (strcmp (name, _LIT4) == 0)
- styp = STYP_LIT4;
- else if (strcmp (name, _BSS) == 0)
- styp = STYP_BSS;
- else if (strcmp (name, _SBSS) == 0)
- styp = STYP_SBSS;
- else if (strcmp (name, _INIT) == 0)
- styp = STYP_ECOFF_INIT;
- else if (strcmp (name, _FINI) == 0)
- styp = STYP_ECOFF_FINI;
- else if (strcmp (name, _PDATA) == 0)
- styp = STYP_PDATA;
- else if (strcmp (name, _XDATA) == 0)
- styp = STYP_XDATA;
- else if (strcmp (name, _LIB) == 0)
- styp = STYP_ECOFF_LIB;
- else if (strcmp (name, _GOT) == 0)
- styp = STYP_GOT;
- else if (strcmp (name, _HASH) == 0)
- styp = STYP_HASH;
- else if (strcmp (name, _DYNAMIC) == 0)
- styp = STYP_DYNAMIC;
- else if (strcmp (name, _LIBLIST) == 0)
- styp = STYP_LIBLIST;
- else if (strcmp (name, _RELDYN) == 0)
- styp = STYP_RELDYN;
- else if (strcmp (name, _CONFLIC) == 0)
- styp = STYP_CONFLIC;
- else if (strcmp (name, _DYNSTR) == 0)
- styp = STYP_DYNSTR;
- else if (strcmp (name, _DYNSYM) == 0)
- styp = STYP_DYNSYM;
- else if (strcmp (name, _COMMENT) == 0)
+ unsigned int i;
+ static struct
+ {
+ const char * name;
+ long flags;
+ }
+ styp_flags [] =
+ {
+ { _TEXT, STYP_TEXT },
+ { _DATA, STYP_DATA },
+ { _SDATA, STYP_SDATA },
+ { _RDATA, STYP_RDATA },
+ { _LITA, STYP_LITA },
+ { _LIT8, STYP_LIT8 },
+ { _LIT4, STYP_LIT4 },
+ { _BSS, STYP_BSS },
+ { _SBSS, STYP_SBSS },
+ { _INIT, STYP_ECOFF_INIT },
+ { _FINI, STYP_ECOFF_FINI },
+ { _PDATA, STYP_PDATA },
+ { _XDATA, STYP_XDATA },
+ { _LIB, STYP_ECOFF_LIB },
+ { _GOT, STYP_GOT },
+ { _HASH, STYP_HASH },
+ { _DYNAMIC, STYP_DYNAMIC },
+ { _LIBLIST, STYP_LIBLIST },
+ { _RELDYN, STYP_RELDYN },
+ { _CONFLIC, STYP_CONFLIC },
+ { _DYNSTR, STYP_DYNSTR },
+ { _DYNSYM, STYP_DYNSYM },
+ { _RCONST, STYP_RCONST }
+ };
+ long styp = 0;
+
+ for (i = 0; i < ARRAY_SIZE (styp_flags); i++)
+ if (streq (name, styp_flags[i].name))
+ {
+ styp = styp_flags[i].flags;
+ break;
+ }
+
+ if (styp == 0)
{
- styp = STYP_COMMENT;
- flags &=~ SEC_NEVER_LOAD;
+ if (streq (name, _COMMENT))
+ {
+ styp = STYP_COMMENT;
+ flags &=~ SEC_NEVER_LOAD;
+ }
+ else if (flags & SEC_CODE)
+ styp = STYP_TEXT;
+ else if (flags & SEC_DATA)
+ styp = STYP_DATA;
+ else if (flags & SEC_READONLY)
+ styp = STYP_RDATA;
+ else if (flags & SEC_LOAD)
+ styp = STYP_REG;
+ else
+ styp = STYP_BSS;
}
- else if (strcmp (name, _RCONST) == 0)
- styp = STYP_RCONST;
- else if (flags & SEC_CODE)
- styp = STYP_TEXT;
- else if (flags & SEC_DATA)
- styp = STYP_DATA;
- else if (flags & SEC_READONLY)
- styp = STYP_RDATA;
- else if (flags & SEC_LOAD)
- styp = STYP_REG;
- else
- styp = STYP_BSS;
if (flags & SEC_NEVER_LOAD)
styp |= STYP_NOLOAD;
/* Get the BFD flags to use for a section. */
bfd_boolean
-_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name, section, flags_ptr)
- bfd *abfd ATTRIBUTE_UNUSED;
- PTR hdr;
- const char *name ATTRIBUTE_UNUSED;
- asection *section ATTRIBUTE_UNUSED;
- flagword * flags_ptr;
+_bfd_ecoff_styp_to_sec_flags (bfd *abfd ATTRIBUTE_UNUSED,
+ void * hdr,
+ const char *name ATTRIBUTE_UNUSED,
+ asection *section ATTRIBUTE_UNUSED,
+ flagword * flags_ptr)
{
- struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
+ struct internal_scnhdr *internal_s = hdr;
long styp_flags = internal_s->s_flags;
flagword sec_flags = 0;
/* Read in the symbolic header for an ECOFF object file. */
static bfd_boolean
-ecoff_slurp_symbolic_header (abfd)
- bfd *abfd;
+ecoff_slurp_symbolic_header (bfd *abfd)
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
bfd_size_type external_hdr_size;
- PTR raw = NULL;
+ void * raw = NULL;
HDRR *internal_symhdr;
/* See if we've already read it in. */
}
/* Read the symbolic information header. */
- raw = (PTR) bfd_malloc (external_hdr_size);
+ raw = bfd_malloc (external_hdr_size);
if (raw == NULL)
goto error_return;
point in the backend structure. */
bfd_boolean
-_bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug)
- bfd *abfd;
- asection *ignore ATTRIBUTE_UNUSED;
- struct ecoff_debug_info *debug;
+_bfd_ecoff_slurp_symbolic_info (bfd *abfd,
+ asection *ignore ATTRIBUTE_UNUSED,
+ struct ecoff_debug_info *debug)
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
HDRR *internal_symhdr;
bfd_size_type raw_base;
bfd_size_type raw_size;
- PTR raw;
+ void * raw;
bfd_size_type external_fdr_size;
char *fraw_src;
char *fraw_end;
/* Check whether we've already gotten it, and whether there's any to
get. */
- if (ecoff_data (abfd)->raw_syments != (PTR) NULL)
+ if (ecoff_data (abfd)->raw_syments != NULL)
return TRUE;
if (ecoff_data (abfd)->sym_filepos == 0)
{
UPDATE_RAW_END (cbPdOffset, ipdMax, backend->debug_swap.external_pdr_size);
UPDATE_RAW_END (cbSymOffset, isymMax, backend->debug_swap.external_sym_size);
/* eraxxon@alumni.rice.edu: ioptMax refers to the size of the
- optimization symtab, not the number of entries */
+ optimization symtab, not the number of entries. */
UPDATE_RAW_END (cbOptOffset, ioptMax, sizeof (char));
UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext));
UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char));
ecoff_data (abfd)->sym_filepos = 0;
return TRUE;
}
- raw = (PTR) bfd_alloc (abfd, raw_size);
+ raw = bfd_alloc (abfd, raw_size);
if (raw == NULL)
return FALSE;
ecoff_data (abfd)->raw_syments = raw;
/* Get pointers for the numeric offsets in the HDRR structure. */
-#define FIX(off1, off2, type) \
- if (internal_symhdr->off1 == 0) \
- debug->off2 = (type) NULL; \
- else \
- debug->off2 = (type) ((char *) raw \
- + (internal_symhdr->off1 \
+#define FIX(off1, off2, type) \
+ if (internal_symhdr->off1 == 0) \
+ debug->off2 = NULL; \
+ else \
+ debug->off2 = (type) ((char *) raw \
+ + (internal_symhdr->off1 \
- raw_base))
FIX (cbLineOffset, line, unsigned char *);
- FIX (cbDnOffset, external_dnr, PTR);
- FIX (cbPdOffset, external_pdr, PTR);
- FIX (cbSymOffset, external_sym, PTR);
- FIX (cbOptOffset, external_opt, PTR);
+ FIX (cbDnOffset, external_dnr, void *);
+ FIX (cbPdOffset, external_pdr, void *);
+ FIX (cbSymOffset, external_sym, void *);
+ FIX (cbOptOffset, external_opt, void *);
FIX (cbAuxOffset, external_aux, union aux_ext *);
FIX (cbSsOffset, ss, char *);
FIX (cbSsExtOffset, ssext, char *);
- FIX (cbFdOffset, external_fdr, PTR);
- FIX (cbRfdOffset, external_rfd, PTR);
- FIX (cbExtOffset, external_ext, PTR);
+ FIX (cbFdOffset, external_fdr, void *);
+ FIX (cbRfdOffset, external_rfd, void *);
+ FIX (cbExtOffset, external_ext, void *);
#undef FIX
/* I don't want to always swap all the data, because it will just
the symbols, so we swap them here. */
amt = internal_symhdr->ifdMax;
amt *= sizeof (struct fdr);
- debug->fdr = (struct fdr *) bfd_alloc (abfd, amt);
+ debug->fdr = bfd_alloc (abfd, amt);
if (debug->fdr == NULL)
return FALSE;
external_fdr_size = backend->debug_swap.external_fdr_size;
fraw_src = (char *) debug->external_fdr;
fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size;
for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
- (*backend->debug_swap.swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
+ (*backend->debug_swap.swap_fdr_in) (abfd, (void *) fraw_src, fdr_ptr);
return TRUE;
}
/* Create an empty symbol. */
asymbol *
-_bfd_ecoff_make_empty_symbol (abfd)
- bfd *abfd;
+_bfd_ecoff_make_empty_symbol (bfd *abfd)
{
ecoff_symbol_type *new;
bfd_size_type amt = sizeof (ecoff_symbol_type);
- new = (ecoff_symbol_type *) bfd_zalloc (abfd, amt);
- if (new == (ecoff_symbol_type *) NULL)
- return (asymbol *) NULL;
- new->symbol.section = (asection *) NULL;
- new->fdr = (FDR *) NULL;
+ new = bfd_zalloc (abfd, amt);
+ if (new == NULL)
+ return NULL;
+ new->symbol.section = NULL;
+ new->fdr = NULL;
new->local = FALSE;
new->native = NULL;
new->symbol.the_bfd = abfd;
/* Set the BFD flags and section for an ECOFF symbol. */
static bfd_boolean
-ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, weak)
- bfd *abfd;
- SYMR *ecoff_sym;
- asymbol *asym;
- int ext;
- int weak;
+ecoff_set_symbol_info (bfd *abfd,
+ SYMR *ecoff_sym,
+ asymbol *asym,
+ int ext,
+ int weak)
{
asym->the_bfd = abfd;
asym->value = ecoff_sym->value;
asym->flags = BSF_LOCAL;
break;
case scText:
- asym->section = bfd_make_section_old_way (abfd, ".text");
+ asym->section = bfd_make_section_old_way (abfd, _TEXT);
asym->value -= asym->section->vma;
break;
case scData:
- asym->section = bfd_make_section_old_way (abfd, ".data");
+ asym->section = bfd_make_section_old_way (abfd, _DATA);
asym->value -= asym->section->vma;
break;
case scBss:
- asym->section = bfd_make_section_old_way (abfd, ".bss");
+ asym->section = bfd_make_section_old_way (abfd, _BSS);
asym->value -= asym->section->vma;
break;
case scRegister:
case N_SETT:
case N_SETD:
case N_SETB:
- {
- /* Mark the symbol as a constructor. */
- asym->flags |= BSF_CONSTRUCTOR;
- }
+ /* Mark the symbol as a constructor. */
+ asym->flags |= BSF_CONSTRUCTOR;
break;
}
}
/* Read an ECOFF symbol table. */
bfd_boolean
-_bfd_ecoff_slurp_symbol_table (abfd)
- bfd *abfd;
+_bfd_ecoff_slurp_symbol_table (bfd *abfd)
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
const bfd_size_type external_ext_size
= backend->debug_swap.external_ext_size;
const bfd_size_type external_sym_size
= backend->debug_swap.external_sym_size;
- void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *))
+ void (* const swap_ext_in) (bfd *, void *, EXTR *)
= backend->debug_swap.swap_ext_in;
- void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ void (* const swap_sym_in) (bfd *, void *, SYMR *)
= backend->debug_swap.swap_sym_in;
bfd_size_type internal_size;
ecoff_symbol_type *internal;
return TRUE;
/* Get the symbolic information. */
- if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL,
+ if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL,
&ecoff_data (abfd)->debug_info))
return FALSE;
if (bfd_get_symcount (abfd) == 0)
internal_size = bfd_get_symcount (abfd);
internal_size *= sizeof (ecoff_symbol_type);
- internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size);
+ internal = bfd_alloc (abfd, internal_size);
if (internal == NULL)
return FALSE;
{
EXTR internal_esym;
- (*swap_ext_in) (abfd, (PTR) eraw_src, &internal_esym);
+ (*swap_ext_in) (abfd, (void *) eraw_src, &internal_esym);
internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext
+ internal_esym.asym.iss);
if (!ecoff_set_symbol_info (abfd, &internal_esym.asym,
else
internal_ptr->fdr = NULL;
internal_ptr->local = FALSE;
- internal_ptr->native = (PTR) eraw_src;
+ internal_ptr->native = (void *) eraw_src;
}
/* The local symbols must be accessed via the fdr's, because the
{
SYMR internal_sym;
- (*swap_sym_in) (abfd, (PTR) lraw_src, &internal_sym);
+ (*swap_sym_in) (abfd, (void *) lraw_src, &internal_sym);
internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ss
+ fdr_ptr->issBase
+ internal_sym.iss);
return FALSE;
internal_ptr->fdr = fdr_ptr;
internal_ptr->local = TRUE;
- internal_ptr->native = (PTR) lraw_src;
+ internal_ptr->native = (void *) lraw_src;
}
}
/* Return the amount of space needed for the canonical symbols. */
long
-_bfd_ecoff_get_symtab_upper_bound (abfd)
- bfd *abfd;
+_bfd_ecoff_get_symtab_upper_bound (bfd *abfd)
{
- if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL,
+ if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL,
&ecoff_data (abfd)->debug_info))
return -1;
/* Get the canonical symbols. */
long
-_bfd_ecoff_canonicalize_symtab (abfd, alocation)
- bfd *abfd;
- asymbol **alocation;
+_bfd_ecoff_canonicalize_symtab (bfd *abfd, asymbol **alocation)
{
unsigned int counter = 0;
ecoff_symbol_type *symbase;
*(location++) = symbase++;
counter++;
}
- *location++ = (ecoff_symbol_type *) NULL;
+ *location++ = NULL;
return bfd_get_symcount (abfd);
}
/* Write aggregate information to a string. */
static void
-ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which)
- bfd *abfd;
- FDR *fdr;
- char *string;
- RNDXR *rndx;
- long isym;
- const char *which;
+ecoff_emit_aggregate (bfd *abfd,
+ FDR *fdr,
+ char *string,
+ RNDXR *rndx,
+ long isym,
+ const char *which)
{
const struct ecoff_debug_swap * const debug_swap =
&ecoff_backend (abfd)->debug_swap;
/* Convert the type information to string format. */
static char *
-ecoff_type_to_string (abfd, fdr, indx)
- bfd *abfd;
- FDR *fdr;
- unsigned int indx;
+ecoff_type_to_string (bfd *abfd, FDR *fdr, unsigned int indx)
{
union aux_ext *aux_ptr;
int bigendian;
AUXU u;
- struct qual {
+ struct qual
+ {
unsigned int type;
int low_bound;
int high_bound;
/* Return information about ECOFF symbol SYMBOL in RET. */
void
-_bfd_ecoff_get_symbol_info (abfd, symbol, ret)
- bfd *abfd ATTRIBUTE_UNUSED;
- asymbol *symbol;
- symbol_info *ret;
+_bfd_ecoff_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
+ asymbol *symbol,
+ symbol_info *ret)
{
bfd_symbol_info (symbol, ret);
}
/* Return whether this is a local label. */
bfd_boolean
-_bfd_ecoff_bfd_is_local_label_name (abfd, name)
- bfd *abfd ATTRIBUTE_UNUSED;
- const char *name;
+_bfd_ecoff_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *name)
{
return name[0] == '$';
}
/* Print information about an ECOFF symbol. */
void
-_bfd_ecoff_print_symbol (abfd, filep, symbol, how)
- bfd *abfd;
- PTR filep;
- asymbol *symbol;
- bfd_print_symbol_type how;
+_bfd_ecoff_print_symbol (bfd *abfd,
+ void * filep,
+ asymbol *symbol,
+ bfd_print_symbol_type how)
{
const struct ecoff_debug_swap * const debug_swap
= &ecoff_backend (abfd)->debug_swap;
/* Read in the relocs for a section. */
static bfd_boolean
-ecoff_slurp_reloc_table (abfd, section, symbols)
- bfd *abfd;
- asection *section;
- asymbol **symbols;
+ecoff_slurp_reloc_table (bfd *abfd,
+ asection *section,
+ asymbol **symbols)
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
arelent *internal_relocs;
arelent *rptr;
unsigned int i;
- if (section->relocation != (arelent *) NULL
+ if (section->relocation != NULL
|| section->reloc_count == 0
|| (section->flags & SEC_CONSTRUCTOR) != 0)
return TRUE;
amt = section->reloc_count;
amt *= sizeof (arelent);
- internal_relocs = (arelent *) bfd_alloc (abfd, amt);
+ internal_relocs = bfd_alloc (abfd, amt);
external_reloc_size = backend->external_reloc_size;
amt = external_reloc_size * section->reloc_count;
- external_relocs = (char *) bfd_alloc (abfd, amt);
- if (internal_relocs == (arelent *) NULL
- || external_relocs == (char *) NULL)
+ external_relocs = bfd_alloc (abfd, amt);
+ if (internal_relocs == NULL || external_relocs == NULL)
return FALSE;
if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0)
return FALSE;
/* r_symndx is a section key. */
switch (intern.r_symndx)
{
- case RELOC_SECTION_TEXT: sec_name = ".text"; break;
- case RELOC_SECTION_RDATA: sec_name = ".rdata"; break;
- case RELOC_SECTION_DATA: sec_name = ".data"; break;
- case RELOC_SECTION_SDATA: sec_name = ".sdata"; break;
- case RELOC_SECTION_SBSS: sec_name = ".sbss"; break;
- case RELOC_SECTION_BSS: sec_name = ".bss"; break;
- case RELOC_SECTION_INIT: sec_name = ".init"; break;
- case RELOC_SECTION_LIT8: sec_name = ".lit8"; break;
- case RELOC_SECTION_LIT4: sec_name = ".lit4"; break;
- case RELOC_SECTION_XDATA: sec_name = ".xdata"; break;
- case RELOC_SECTION_PDATA: sec_name = ".pdata"; break;
- case RELOC_SECTION_FINI: sec_name = ".fini"; break;
- case RELOC_SECTION_LITA: sec_name = ".lita"; break;
- case RELOC_SECTION_RCONST: sec_name = ".rconst"; break;
+ case RELOC_SECTION_TEXT: sec_name = _TEXT; break;
+ case RELOC_SECTION_RDATA: sec_name = _RDATA; break;
+ case RELOC_SECTION_DATA: sec_name = _DATA; break;
+ case RELOC_SECTION_SDATA: sec_name = _SDATA; break;
+ case RELOC_SECTION_SBSS: sec_name = _SBSS; break;
+ case RELOC_SECTION_BSS: sec_name = _BSS; break;
+ case RELOC_SECTION_INIT: sec_name = _INIT; break;
+ case RELOC_SECTION_LIT8: sec_name = _LIT8; break;
+ case RELOC_SECTION_LIT4: sec_name = _LIT4; break;
+ case RELOC_SECTION_XDATA: sec_name = _XDATA; break;
+ case RELOC_SECTION_PDATA: sec_name = _PDATA; break;
+ case RELOC_SECTION_FINI: sec_name = _FINI; break;
+ case RELOC_SECTION_LITA: sec_name = _LITA; break;
+ case RELOC_SECTION_RCONST: sec_name = _RCONST; break;
default: abort ();
}
sec = bfd_get_section_by_name (abfd, sec_name);
- if (sec == (asection *) NULL)
+ if (sec == NULL)
abort ();
rptr->sym_ptr_ptr = sec->symbol_ptr_ptr;
/* Get a canonical list of relocs. */
long
-_bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
- bfd *abfd;
- asection *section;
- arelent **relptr;
- asymbol **symbols;
+_bfd_ecoff_canonicalize_reloc (bfd *abfd,
+ asection *section,
+ arelent **relptr,
+ asymbol **symbols)
{
unsigned int count;
*relptr++ = tblptr++;
}
- *relptr = (arelent *) NULL;
+ *relptr = NULL;
return section->reloc_count;
}
wanted location. */
bfd_boolean
-_bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
- filename_ptr, functionname_ptr, retline_ptr)
- bfd *abfd;
- asection *section;
- asymbol **ignore_symbols ATTRIBUTE_UNUSED;
- bfd_vma offset;
- const char **filename_ptr;
- const char **functionname_ptr;
- unsigned int *retline_ptr;
+_bfd_ecoff_find_nearest_line (bfd *abfd,
+ asection *section,
+ asymbol **ignore_symbols ATTRIBUTE_UNUSED,
+ bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *retline_ptr)
{
const struct ecoff_debug_swap * const debug_swap
= &ecoff_backend (abfd)->debug_swap;
struct ecoff_find_line *line_info;
/* Make sure we have the FDR's. */
- if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
+ if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL, debug_info)
|| bfd_get_symcount (abfd) == 0)
return FALSE;
if (ecoff_data (abfd)->find_line_info == NULL)
{
bfd_size_type amt = sizeof (struct ecoff_find_line);
- ecoff_data (abfd)->find_line_info
- = (struct ecoff_find_line *) bfd_zalloc (abfd, amt);
+
+ ecoff_data (abfd)->find_line_info = bfd_zalloc (abfd, amt);
if (ecoff_data (abfd)->find_line_info == NULL)
return FALSE;
}
information. */
bfd_boolean
-_bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd)
- bfd *ibfd;
- bfd *obfd;
+_bfd_ecoff_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
{
struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info;
struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info;
- register int i;
+ int i;
asymbol **sym_ptr_ptr;
size_t c;
bfd_boolean local;
/* If there are no symbols, don't copy any debugging information. */
c = bfd_get_symcount (obfd);
sym_ptr_ptr = bfd_get_outsymbols (obfd);
- if (c == 0 || sym_ptr_ptr == (asymbol **) NULL)
+ if (c == 0 || sym_ptr_ptr == NULL)
return TRUE;
/* See if there are any local symbols. */
callers ignore the return value. */
bfd_boolean
-_bfd_ecoff_set_arch_mach (abfd, arch, machine)
- bfd *abfd;
- enum bfd_architecture arch;
- unsigned long machine;
+_bfd_ecoff_set_arch_mach (bfd *abfd,
+ enum bfd_architecture arch,
+ unsigned long machine)
{
bfd_default_set_arch_mach (abfd, arch, machine);
return arch == ecoff_backend (abfd)->arch;
/* Get the size of the section headers. */
int
-_bfd_ecoff_sizeof_headers (abfd, reloc)
- bfd *abfd;
- bfd_boolean reloc ATTRIBUTE_UNUSED;
+_bfd_ecoff_sizeof_headers (bfd *abfd, bfd_boolean reloc ATTRIBUTE_UNUSED)
{
asection *current;
int c;
c = 0;
for (current = abfd->sections;
- current != (asection *)NULL;
+ current != NULL;
current = current->next)
++c;
/* Get the contents of a section. */
bfd_boolean
-_bfd_ecoff_get_section_contents (abfd, section, location, offset, count)
- bfd *abfd;
- asection *section;
- PTR location;
- file_ptr offset;
- bfd_size_type count;
+_bfd_ecoff_get_section_contents (bfd *abfd,
+ asection *section,
+ void * location,
+ file_ptr offset,
+ bfd_size_type count)
{
return _bfd_generic_get_section_contents (abfd, section, location,
offset, count);
called via qsort. */
static int
-ecoff_sort_hdrs (arg1, arg2)
- const PTR arg1;
- const PTR arg2;
+ecoff_sort_hdrs (const void * arg1, const void * arg2)
{
const asection *hdr1 = *(const asection **) arg1;
const asection *hdr2 = *(const asection **) arg2;
reloc_filepos. */
static bfd_boolean
-ecoff_compute_section_file_positions (abfd)
- bfd *abfd;
+ecoff_compute_section_file_positions (bfd *abfd)
{
file_ptr sofar, file_sofar;
asection **sorted_hdrs;
/* Sort the sections by VMA. */
amt = abfd->section_count;
amt *= sizeof (asection *);
- sorted_hdrs = (asection **) bfd_malloc (amt);
+ sorted_hdrs = bfd_malloc (amt);
if (sorted_hdrs == NULL)
return FALSE;
for (current = abfd->sections, i = 0;
for (i = 0; i < abfd->section_count; i++)
{
current = sorted_hdrs[i];
- if (strcmp (current->name, _RDATA) == 0)
+ if (streq (current->name, _RDATA))
break;
if ((current->flags & SEC_CODE) == 0
- && strcmp (current->name, _PDATA) != 0
- && strcmp (current->name, _RCONST) != 0)
+ && ! streq (current->name, _PDATA)
+ && ! streq (current->name, _RCONST))
{
rdata_in_text = FALSE;
break;
supposed to indicate the number of .pdata entries that are
really in the section. Each entry is 8 bytes. We store this
away in line_filepos before increasing the section size. */
- if (strcmp (current->name, _PDATA) == 0)
+ if (streq (current->name, _PDATA))
current->line_filepos = current->size / 8;
alignment_power = current->alignment_power;
&& ! first_data
&& (current->flags & SEC_CODE) == 0
&& (! rdata_in_text
- || strcmp (current->name, _RDATA) != 0)
- && strcmp (current->name, _PDATA) != 0
- && strcmp (current->name, _RCONST) != 0)
+ || ! streq (current->name, _RDATA))
+ && ! streq (current->name, _PDATA)
+ && ! streq (current->name, _RCONST))
{
sofar = (sofar + round - 1) &~ (round - 1);
file_sofar = (file_sofar + round - 1) &~ (round - 1);
first_data = FALSE;
}
- else if (strcmp (current->name, _LIB) == 0)
+ else if (streq (current->name, _LIB))
{
/* On Irix 4, the location of contents of the .lib section
from a shared library section is also rounded up to a
information. */
static bfd_size_type
-ecoff_compute_reloc_file_positions (abfd)
- bfd *abfd;
+ecoff_compute_reloc_file_positions (bfd *abfd)
{
const bfd_size_type external_reloc_size =
ecoff_backend (abfd)->external_reloc_size;
reloc_size = 0;
for (current = abfd->sections;
- current != (asection *)NULL;
+ current != NULL;
current = current->next)
{
if (current->reloc_count == 0)
/* Set the contents of a section. */
bfd_boolean
-_bfd_ecoff_set_section_contents (abfd, section, location, offset, count)
- bfd *abfd;
- asection *section;
- const PTR location;
- file_ptr offset;
- bfd_size_type count;
+_bfd_ecoff_set_section_contents (bfd *abfd,
+ asection *section,
+ const void * location,
+ file_ptr offset,
+ bfd_size_type count)
{
file_ptr pos;
/* This must be done first, because bfd_set_section_contents is
going to set output_has_begun to TRUE. */
- if (! abfd->output_has_begun)
- {
- if (! ecoff_compute_section_file_positions (abfd))
- return FALSE;
- }
+ if (! abfd->output_has_begun
+ && ! ecoff_compute_section_file_positions (abfd))
+ return FALSE;
/* Handle the .lib section specially so that Irix 4 shared libraries
work out. See coff_set_section_contents in coffcode.h. */
- if (strcmp (section->name, _LIB) == 0)
+ if (streq (section->name, _LIB))
{
bfd_byte *rec, *recend;
nlmconv. */
bfd_vma
-bfd_ecoff_get_gp_value (abfd)
- bfd *abfd;
+bfd_ecoff_get_gp_value (bfd *abfd)
{
if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
|| bfd_get_format (abfd) != bfd_object)
assembler. */
bfd_boolean
-bfd_ecoff_set_gp_value (abfd, gp_value)
- bfd *abfd;
- bfd_vma gp_value;
+bfd_ecoff_set_gp_value (bfd *abfd, bfd_vma gp_value)
{
if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
|| bfd_get_format (abfd) != bfd_object)
the assembler. */
bfd_boolean
-bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask)
- bfd *abfd;
- unsigned long gprmask;
- unsigned long fprmask;
- unsigned long *cprmask;
+bfd_ecoff_set_regmasks (bfd *abfd,
+ unsigned long gprmask,
+ unsigned long fprmask,
+ unsigned long *cprmask)
{
ecoff_data_type *tdata;
tdata = ecoff_data (abfd);
tdata->gprmask = gprmask;
tdata->fprmask = fprmask;
- if (cprmask != (unsigned long *) NULL)
+ if (cprmask != NULL)
{
int i;
is passed to bfd_ecoff_debug_externals. */
static bfd_boolean
-ecoff_get_extr (sym, esym)
- asymbol *sym;
- EXTR *esym;
+ecoff_get_extr (asymbol *sym, EXTR *esym)
{
ecoff_symbol_type *ecoff_sym_ptr;
bfd *input_bfd;
input_debug = &ecoff_data (input_bfd)->debug_info;
BFD_ASSERT (esym->ifd < input_debug->symbolic_header.ifdMax);
- if (input_debug->ifdmap != (RFDT *) NULL)
+ if (input_debug->ifdmap != NULL)
esym->ifd = input_debug->ifdmap[esym->ifd];
}
bfd_ecoff_debug_externals. */
static void
-ecoff_set_index (sym, indx)
- asymbol *sym;
- bfd_size_type indx;
+ecoff_set_index (asymbol *sym, bfd_size_type indx)
{
ecoff_set_sym_index (sym, indx);
}
/* Write out an ECOFF file. */
bfd_boolean
-_bfd_ecoff_write_object_contents (abfd)
- bfd *abfd;
+_bfd_ecoff_write_object_contents (bfd *abfd)
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
const bfd_vma round = backend->round;
const bfd_size_type external_hdr_size
= backend->debug_swap.external_hdr_size;
const bfd_size_type external_reloc_size = backend->external_reloc_size;
- void (* const adjust_reloc_out)
- PARAMS ((bfd *, const arelent *, struct internal_reloc *))
+ void (* const adjust_reloc_out) (bfd *, const arelent *, struct internal_reloc *)
= backend->adjust_reloc_out;
- void (* const swap_reloc_out)
- PARAMS ((bfd *, const struct internal_reloc *, PTR))
+ void (* const swap_reloc_out) (bfd *, const struct internal_reloc *, void *)
= backend->swap_reloc_out;
struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info;
HDRR * const symhdr = &debug->symbolic_header;
bfd_vma data_start;
bfd_boolean set_data_start;
bfd_size_type bss_size;
- PTR buff = NULL;
- PTR reloc_buff = NULL;
+ void * buff = NULL;
+ void * reloc_buff = NULL;
struct internal_filehdr internal_f;
struct internal_aouthdr internal_a;
int i;
count = 1;
for (current = abfd->sections;
- current != (asection *)NULL;
+ current != NULL;
current = current->next)
{
current->target_index = count;
file header, or a.out header. */
{
bfd_size_type siz;
+
siz = scnhsz;
if (siz < filhsz)
siz = filhsz;
if (siz < aoutsz)
siz = aoutsz;
- buff = (PTR) bfd_malloc (siz);
+ buff = bfd_malloc (siz);
if (buff == NULL)
goto error_return;
}
internal_f.f_nscns = 0;
if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0)
goto error_return;
+
for (current = abfd->sections;
- current != (asection *) NULL;
+ current != NULL;
current = current->next)
{
struct internal_scnhdr section;
/* This seems to be correct for Irix 4 shared libraries. */
vma = bfd_get_section_vma (abfd, current);
- if (strcmp (current->name, _LIB) == 0)
+ if (streq (current->name, _LIB))
section.s_vaddr = 0;
else
section.s_vaddr = vma;
want the linker to compute the best size to use, or
something. I don't know what happens if the information is
not present. */
- if (strcmp (current->name, _PDATA) != 0)
+ if (! streq (current->name, _PDATA))
section.s_lnnoptr = 0;
else
{
section.s_flags = ecoff_sec_to_styp_flags (current->name,
current->flags);
- if (bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff) == 0
+ if (bfd_coff_swap_scnhdr_out (abfd, (void *) §ion, buff) == 0
|| bfd_bwrite (buff, scnhsz, abfd) != scnhsz)
goto error_return;
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
goto error_return;
- bfd_coff_swap_filehdr_out (abfd, (PTR) &internal_f, buff);
+ bfd_coff_swap_filehdr_out (abfd, (void *) &internal_f, buff);
if (bfd_bwrite (buff, filhsz, abfd) != filhsz)
goto error_return;
- bfd_coff_swap_aouthdr_out (abfd, (PTR) &internal_a, buff);
+ bfd_coff_swap_aouthdr_out (abfd, (void *) &internal_a, buff);
if (bfd_bwrite (buff, aoutsz, abfd) != aoutsz)
goto error_return;
/* Write out the relocs. */
for (current = abfd->sections;
- current != (asection *) NULL;
+ current != NULL;
current = current->next)
{
arelent **reloc_ptr_ptr;
asymbol *sym;
struct internal_reloc in;
- memset ((PTR) &in, 0, sizeof in);
+ memset ((void *) &in, 0, sizeof in);
reloc = *reloc_ptr_ptr;
sym = *reloc->sym_ptr_ptr;
else
{
const char *name;
+ unsigned int i;
+ static struct
+ {
+ const char * name;
+ long r_symndx;
+ }
+ section_symndx [] =
+ {
+ { _TEXT, RELOC_SECTION_TEXT },
+ { _RDATA, RELOC_SECTION_RDATA },
+ { _DATA, RELOC_SECTION_DATA },
+ { _SDATA, RELOC_SECTION_SDATA },
+ { _SBSS, RELOC_SECTION_SBSS },
+ { _BSS, RELOC_SECTION_BSS },
+ { _INIT, RELOC_SECTION_INIT },
+ { _LIT8, RELOC_SECTION_LIT8 },
+ { _LIT4, RELOC_SECTION_LIT4 },
+ { _XDATA, RELOC_SECTION_XDATA },
+ { _PDATA, RELOC_SECTION_PDATA },
+ { _FINI, RELOC_SECTION_FINI },
+ { _LITA, RELOC_SECTION_LITA },
+ { "*ABS*", RELOC_SECTION_ABS },
+ { _RCONST, RELOC_SECTION_RCONST }
+ };
name = bfd_get_section_name (abfd, bfd_get_section (sym));
- if (strcmp (name, ".text") == 0)
- in.r_symndx = RELOC_SECTION_TEXT;
- else if (strcmp (name, ".rdata") == 0)
- in.r_symndx = RELOC_SECTION_RDATA;
- else if (strcmp (name, ".data") == 0)
- in.r_symndx = RELOC_SECTION_DATA;
- else if (strcmp (name, ".sdata") == 0)
- in.r_symndx = RELOC_SECTION_SDATA;
- else if (strcmp (name, ".sbss") == 0)
- in.r_symndx = RELOC_SECTION_SBSS;
- else if (strcmp (name, ".bss") == 0)
- in.r_symndx = RELOC_SECTION_BSS;
- else if (strcmp (name, ".init") == 0)
- in.r_symndx = RELOC_SECTION_INIT;
- else if (strcmp (name, ".lit8") == 0)
- in.r_symndx = RELOC_SECTION_LIT8;
- else if (strcmp (name, ".lit4") == 0)
- in.r_symndx = RELOC_SECTION_LIT4;
- else if (strcmp (name, ".xdata") == 0)
- in.r_symndx = RELOC_SECTION_XDATA;
- else if (strcmp (name, ".pdata") == 0)
- in.r_symndx = RELOC_SECTION_PDATA;
- else if (strcmp (name, ".fini") == 0)
- in.r_symndx = RELOC_SECTION_FINI;
- else if (strcmp (name, ".lita") == 0)
- in.r_symndx = RELOC_SECTION_LITA;
- else if (strcmp (name, "*ABS*") == 0)
- in.r_symndx = RELOC_SECTION_ABS;
- else if (strcmp (name, ".rconst") == 0)
- in.r_symndx = RELOC_SECTION_RCONST;
- else
+
+ for (i = 0; i < ARRAY_SIZE (section_symndx); i++)
+ if (streq (name, section_symndx[i].name))
+ {
+ in.r_symndx = section_symndx[i].r_symndx;
+ break;
+ }
+
+ if (i == ARRAY_SIZE (section_symndx))
abort ();
in.r_extern = 0;
}
(*adjust_reloc_out) (abfd, reloc, &in);
- (*swap_reloc_out) (abfd, &in, (PTR) out_ptr);
+ (*swap_reloc_out) (abfd, &in, (void *) out_ptr);
}
if (bfd_seek (abfd, current->rel_filepos, SEEK_SET) != 0)
The Alpha seems to use ________64E[BL]E[BL]_. */
-#define ARMAP_BIG_ENDIAN 'B'
-#define ARMAP_LITTLE_ENDIAN 'L'
-#define ARMAP_MARKER 'E'
-#define ARMAP_START_LENGTH 10
-#define ARMAP_HEADER_MARKER_INDEX 10
-#define ARMAP_HEADER_ENDIAN_INDEX 11
-#define ARMAP_OBJECT_MARKER_INDEX 12
-#define ARMAP_OBJECT_ENDIAN_INDEX 13
-#define ARMAP_END_INDEX 14
-#define ARMAP_END "_ "
+#define ARMAP_BIG_ENDIAN 'B'
+#define ARMAP_LITTLE_ENDIAN 'L'
+#define ARMAP_MARKER 'E'
+#define ARMAP_START_LENGTH 10
+#define ARMAP_HEADER_MARKER_INDEX 10
+#define ARMAP_HEADER_ENDIAN_INDEX 11
+#define ARMAP_OBJECT_MARKER_INDEX 12
+#define ARMAP_OBJECT_ENDIAN_INDEX 13
+#define ARMAP_END_INDEX 14
+#define ARMAP_END "_ "
/* This is a magic number used in the hashing algorithm. */
-#define ARMAP_HASH_MAGIC 0x9dd68ab5
+#define ARMAP_HASH_MAGIC 0x9dd68ab5
/* This returns the hash value to use for a string. It also sets
*REHASH to the rehash adjustment if the first slot is taken. SIZE
base 2 of SIZE. */
static unsigned int
-ecoff_armap_hash (s, rehash, size, hlog)
- const char *s;
- unsigned int *rehash;
- unsigned int size;
- unsigned int hlog;
+ecoff_armap_hash (const char *s,
+ unsigned int *rehash,
+ unsigned int size,
+ unsigned int hlog)
{
unsigned int hash;
/* Read in the armap. */
bfd_boolean
-_bfd_ecoff_slurp_armap (abfd)
- bfd *abfd;
+_bfd_ecoff_slurp_armap (bfd *abfd)
{
char nextname[17];
unsigned int i;
bfd_size_type amt;
/* Get the name of the first element. */
- i = bfd_bread ((PTR) nextname, (bfd_size_type) 16, abfd);
+ i = bfd_bread ((void *) nextname, (bfd_size_type) 16, abfd);
if (i == 0)
return TRUE;
if (i != 16)
bfd_slurp_armap, but that seems inappropriate since no other
target uses this format. Instead, we check directly for a COFF
armap. */
- if (strncmp (nextname, "/ ", 16) == 0)
+ if (strneq (nextname, "/ ", 16))
return bfd_slurp_armap (abfd);
/* See if the first element is an armap. */
- if (strncmp (nextname, ecoff_backend (abfd)->armap_start,
- ARMAP_START_LENGTH) != 0
+ if (! strneq (nextname, ecoff_backend (abfd)->armap_start, ARMAP_START_LENGTH)
|| nextname[ARMAP_HEADER_MARKER_INDEX] != ARMAP_MARKER
|| (nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN
&& nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN)
|| nextname[ARMAP_OBJECT_MARKER_INDEX] != ARMAP_MARKER
|| (nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN
&& nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN)
- || strncmp (nextname + ARMAP_END_INDEX,
- ARMAP_END, sizeof ARMAP_END - 1) != 0)
+ || ! strneq (nextname + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1))
{
bfd_has_map (abfd) = FALSE;
return TRUE;
/* Read in the armap. */
ardata = bfd_ardata (abfd);
mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
- if (mapdata == (struct areltdata *) NULL)
+ if (mapdata == NULL)
return FALSE;
parsed_size = mapdata->parsed_size;
- bfd_release (abfd, (PTR) mapdata);
+ bfd_release (abfd, (void *) mapdata);
- raw_armap = (char *) bfd_alloc (abfd, parsed_size);
- if (raw_armap == (char *) NULL)
+ raw_armap = bfd_alloc (abfd, parsed_size);
+ if (raw_armap == NULL)
return FALSE;
- if (bfd_bread ((PTR) raw_armap, parsed_size, abfd) != parsed_size)
+ if (bfd_bread ((void *) raw_armap, parsed_size, abfd) != parsed_size)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_malformed_archive);
- bfd_release (abfd, (PTR) raw_armap);
+ bfd_release (abfd, (void *) raw_armap);
return FALSE;
}
- ardata->tdata = (PTR) raw_armap;
+ ardata->tdata = (void *) raw_armap;
count = H_GET_32 (abfd, raw_armap);
ardata->symdef_count = 0;
- ardata->cache = (struct ar_cache *) NULL;
+ ardata->cache = NULL;
/* This code used to overlay the symdefs over the raw archive data,
but that doesn't work on a 64 bit host. */
amt = ardata->symdef_count;
amt *= sizeof (struct symdef);
- symdef_ptr = (struct symdef *) bfd_alloc (abfd, amt);
+ symdef_ptr = bfd_alloc (abfd, amt);
if (!symdef_ptr)
return FALSE;
/* Write out an armap. */
bfd_boolean
-_bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
- bfd *abfd;
- unsigned int elength;
- struct orl *map;
- unsigned int orl_count;
- int stridx;
+_bfd_ecoff_write_armap (bfd *abfd,
+ unsigned int elength,
+ struct orl *map,
+ unsigned int orl_count,
+ int stridx)
{
unsigned int hashsize, hashlog;
bfd_size_type symdefsize;
firstreal = SARMAG + sizeof (struct ar_hdr) + mapsize + elength;
- memset ((PTR) &hdr, 0, sizeof hdr);
+ memset ((void *) &hdr, 0, sizeof hdr);
/* Work out the ECOFF armap name. */
strcpy (hdr.ar_name, ecoff_backend (abfd)->armap_start);
if (((char *) (&hdr))[i] == '\0')
(((char *) (&hdr))[i]) = ' ';
- if (bfd_bwrite ((PTR) &hdr, (bfd_size_type) sizeof (struct ar_hdr), abfd)
+ if (bfd_bwrite ((void *) &hdr, (bfd_size_type) sizeof (struct ar_hdr), abfd)
!= sizeof (struct ar_hdr))
return FALSE;
H_PUT_32 (abfd, hashsize, temp);
- if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
+ if (bfd_bwrite ((void *) temp, (bfd_size_type) 4, abfd) != 4)
return FALSE;
- hashtable = (bfd_byte *) bfd_zalloc (abfd, symdefsize);
+ hashtable = bfd_zalloc (abfd, symdefsize);
if (!hashtable)
return FALSE;
H_PUT_32 (abfd, firstreal, (hashtable + hash * 8 + 4));
}
- if (bfd_bwrite ((PTR) hashtable, symdefsize, abfd) != symdefsize)
+ if (bfd_bwrite ((void *) hashtable, symdefsize, abfd) != symdefsize)
return FALSE;
bfd_release (abfd, hashtable);
/* Now write the strings. */
H_PUT_32 (abfd, stringsize, temp);
- if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
+ if (bfd_bwrite ((void *) temp, (bfd_size_type) 4, abfd) != 4)
return FALSE;
for (i = 0; i < orl_count; i++)
{
bfd_size_type len;
len = strlen (*map[i].name) + 1;
- if (bfd_bwrite ((PTR) (*map[i].name), len, abfd) != len)
+ if (bfd_bwrite ((void *) (*map[i].name), len, abfd) != len)
return FALSE;
}
and the extended name table. */
const bfd_target *
-_bfd_ecoff_archive_p (abfd)
- bfd *abfd;
+_bfd_ecoff_archive_p (bfd *abfd)
{
struct artdata *tdata_hold;
char armag[SARMAG + 1];
bfd_size_type amt;
- if (bfd_bread ((PTR) armag, (bfd_size_type) SARMAG, abfd) != SARMAG)
+ if (bfd_bread ((void *) armag, (bfd_size_type) SARMAG, abfd) != SARMAG)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_wrong_format);
- return (const bfd_target *) NULL;
+ return NULL;
}
- if (strncmp (armag, ARMAG, SARMAG) != 0)
+ if (! strneq (armag, ARMAG, SARMAG))
{
bfd_set_error (bfd_error_wrong_format);
return NULL;
tdata_hold = bfd_ardata (abfd);
amt = sizeof (struct artdata);
- bfd_ardata (abfd) = (struct artdata *) bfd_zalloc (abfd, amt);
- if (bfd_ardata (abfd) == (struct artdata *) NULL)
+ bfd_ardata (abfd) = bfd_zalloc (abfd, amt);
+ if (bfd_ardata (abfd) == NULL)
{
bfd_ardata (abfd) = tdata_hold;
- return (const bfd_target *) NULL;
+ return NULL;
}
bfd_ardata (abfd)->first_file_filepos = SARMAG;
{
bfd_release (abfd, bfd_ardata (abfd));
bfd_ardata (abfd) = tdata_hold;
- return (const bfd_target *) NULL;
+ return NULL;
}
if (bfd_has_map (abfd))
the first file is not an object file, somebody is doing
something weird, and we permit it so that ar -t will work. */
- first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
+ first = bfd_openr_next_archived_file (abfd, NULL);
if (first != NULL)
{
first->target_defaulted = FALSE;
\f
/* ECOFF linker code. */
-static struct bfd_hash_entry *ecoff_link_hash_newfunc
- PARAMS ((struct bfd_hash_entry *entry,
- struct bfd_hash_table *table,
- const char *string));
-static bfd_boolean ecoff_link_add_archive_symbols
- PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean ecoff_link_check_archive_element
- PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *pneeded));
-static bfd_boolean ecoff_link_add_object_symbols
- PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean ecoff_link_add_externals
- PARAMS ((bfd *, struct bfd_link_info *, PTR, char *));
-
/* Routine to create an entry in an ECOFF link hash table. */
static struct bfd_hash_entry *
-ecoff_link_hash_newfunc (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
+ecoff_link_hash_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table,
+ const char *string)
{
struct ecoff_link_hash_entry *ret = (struct ecoff_link_hash_entry *) entry;
/* Allocate the structure if it has not already been allocated by a
subclass. */
- if (ret == (struct ecoff_link_hash_entry *) NULL)
+ if (ret == NULL)
ret = ((struct ecoff_link_hash_entry *)
bfd_hash_allocate (table, sizeof (struct ecoff_link_hash_entry)));
- if (ret == (struct ecoff_link_hash_entry *) NULL)
+ if (ret == NULL)
return NULL;
/* Call the allocation method of the superclass. */
ret->written = 0;
ret->small = 0;
}
- memset ((PTR) &ret->esym, 0, sizeof ret->esym);
+ memset ((void *) &ret->esym, 0, sizeof ret->esym);
return (struct bfd_hash_entry *) ret;
}
/* Create an ECOFF link hash table. */
struct bfd_link_hash_table *
-_bfd_ecoff_bfd_link_hash_table_create (abfd)
- bfd *abfd;
+_bfd_ecoff_bfd_link_hash_table_create (bfd *abfd)
{
struct ecoff_link_hash_table *ret;
bfd_size_type amt = sizeof (struct ecoff_link_hash_table);
- ret = (struct ecoff_link_hash_table *) bfd_malloc (amt);
+ ret = bfd_malloc (amt);
if (ret == NULL)
return NULL;
if (! _bfd_link_hash_table_init (&ret->root, abfd,
ecoff_link_hash_newfunc))
{
free (ret);
- return (struct bfd_link_hash_table *) NULL;
+ return NULL;
}
return &ret->root;
}
#define ecoff_link_hash_traverse(table, func, info) \
(bfd_link_hash_traverse \
(&(table)->root, \
- (bfd_boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
+ (bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \
(info)))
/* Get the ECOFF link hash table from the info structure. This is
#define ecoff_hash_table(p) ((struct ecoff_link_hash_table *) ((p)->hash))
-/* Given an ECOFF BFD, add symbols to the global hash table as
- appropriate. */
-
-bfd_boolean
-_bfd_ecoff_bfd_link_add_symbols (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- switch (bfd_get_format (abfd))
- {
- case bfd_object:
- return ecoff_link_add_object_symbols (abfd, info);
- case bfd_archive:
- return ecoff_link_add_archive_symbols (abfd, info);
- default:
- bfd_set_error (bfd_error_wrong_format);
- return FALSE;
- }
-}
-
-/* Add the symbols from an archive file to the global hash table.
- This looks through the undefined symbols, looks each one up in the
- archive hash table, and adds any associated object file. We do not
- use _bfd_generic_link_add_archive_symbols because ECOFF archives
- already have a hash table, so there is no reason to construct
- another one. */
+/* Add the external symbols of an object file to the global linker
+ hash table. The external symbols and strings we are passed are
+ just allocated on the stack, and will be discarded. We must
+ explicitly save any information we may need later on in the link.
+ We do not want to read the external symbol information again. */
static bfd_boolean
-ecoff_link_add_archive_symbols (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+ecoff_link_add_externals (bfd *abfd,
+ struct bfd_link_info *info,
+ void * external_ext,
+ char *ssext)
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
- const bfd_byte *raw_armap;
- struct bfd_link_hash_entry **pundef;
- unsigned int armap_count;
- unsigned int armap_log;
- unsigned int i;
- const bfd_byte *hashtable;
- const char *stringbase;
-
- if (! bfd_has_map (abfd))
- {
- /* An empty archive is a special case. */
- if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
- return TRUE;
- bfd_set_error (bfd_error_no_armap);
- return FALSE;
- }
-
- /* If we don't have any raw data for this archive, as can happen on
- Irix 4.0.5F, we call the generic routine.
- FIXME: We should be more clever about this, since someday tdata
- may get to something for a generic archive. */
- raw_armap = (const bfd_byte *) bfd_ardata (abfd)->tdata;
- if (raw_armap == (bfd_byte *) NULL)
- return (_bfd_generic_link_add_archive_symbols
- (abfd, info, ecoff_link_check_archive_element));
-
- armap_count = H_GET_32 (abfd, raw_armap);
+ void (* const swap_ext_in) (bfd *, void *, EXTR *)
+ = backend->debug_swap.swap_ext_in;
+ bfd_size_type external_ext_size = backend->debug_swap.external_ext_size;
+ unsigned long ext_count;
+ struct bfd_link_hash_entry **sym_hash;
+ char *ext_ptr;
+ char *ext_end;
+ bfd_size_type amt;
- armap_log = 0;
- for (i = 1; i < armap_count; i <<= 1)
- armap_log++;
- BFD_ASSERT (i == armap_count);
+ ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
- hashtable = raw_armap + 4;
- stringbase = (const char *) raw_armap + armap_count * 8 + 8;
+ amt = ext_count;
+ amt *= sizeof (struct bfd_link_hash_entry *);
+ sym_hash = bfd_alloc (abfd, amt);
+ if (!sym_hash)
+ return FALSE;
+ ecoff_data (abfd)->sym_hashes = (struct ecoff_link_hash_entry **) sym_hash;
- /* Look through the list of undefined symbols. */
- pundef = &info->hash->undefs;
- while (*pundef != (struct bfd_link_hash_entry *) NULL)
+ ext_ptr = (char *) external_ext;
+ ext_end = ext_ptr + ext_count * external_ext_size;
+ for (; ext_ptr < ext_end; ext_ptr += external_ext_size, sym_hash++)
{
- struct bfd_link_hash_entry *h;
- unsigned int hash, rehash;
- unsigned int file_offset;
+ EXTR esym;
+ bfd_boolean skip;
+ bfd_vma value;
+ asection *section;
const char *name;
- bfd *element;
+ struct ecoff_link_hash_entry *h;
- h = *pundef;
+ *sym_hash = NULL;
- /* When a symbol is defined, it is not necessarily removed from
- the list. */
- if (h->type != bfd_link_hash_undefined
- && h->type != bfd_link_hash_common)
- {
- /* Remove this entry from the list, for general cleanliness
- and because we are going to look through the list again
- if we search any more libraries. We can't remove the
- entry if it is the tail, because that would lose any
- entries we add to the list later on. */
- if (*pundef != info->hash->undefs_tail)
- *pundef = (*pundef)->u.undef.next;
- else
- pundef = &(*pundef)->u.undef.next;
- continue;
- }
+ (*swap_ext_in) (abfd, (void *) ext_ptr, &esym);
- /* Native ECOFF linkers do not pull in archive elements merely
- to satisfy common definitions, so neither do we. We leave
- them on the list, though, in case we are linking against some
- other object format. */
- if (h->type != bfd_link_hash_undefined)
+ /* Skip debugging symbols. */
+ skip = FALSE;
+ switch (esym.asym.st)
{
- pundef = &(*pundef)->u.undef.next;
- continue;
+ case stGlobal:
+ case stStatic:
+ case stLabel:
+ case stProc:
+ case stStaticProc:
+ break;
+ default:
+ skip = TRUE;
+ break;
}
- /* Look for this symbol in the archive hash table. */
- hash = ecoff_armap_hash (h->root.string, &rehash, armap_count,
- armap_log);
-
- file_offset = H_GET_32 (abfd, hashtable + (hash * 8) + 4);
- if (file_offset == 0)
- {
- /* Nothing in this slot. */
- pundef = &(*pundef)->u.undef.next;
- continue;
- }
+ if (skip)
+ continue;
- name = stringbase + H_GET_32 (abfd, hashtable + (hash * 8));
- if (name[0] != h->root.string[0]
- || strcmp (name, h->root.string) != 0)
+ /* Get the information for this symbol. */
+ value = esym.asym.value;
+ switch (esym.asym.sc)
{
- unsigned int srch;
- bfd_boolean found;
-
- /* That was the wrong symbol. Try rehashing. */
- found = FALSE;
- for (srch = (hash + rehash) & (armap_count - 1);
- srch != hash;
- srch = (srch + rehash) & (armap_count - 1))
+ default:
+ case scNil:
+ case scRegister:
+ case scCdbLocal:
+ case scBits:
+ case scCdbSystem:
+ case scRegImage:
+ case scInfo:
+ case scUserStruct:
+ case scVar:
+ case scVarRegister:
+ case scVariant:
+ case scBasedVar:
+ case scXData:
+ case scPData:
+ section = NULL;
+ break;
+ case scText:
+ section = bfd_make_section_old_way (abfd, _TEXT);
+ value -= section->vma;
+ break;
+ case scData:
+ section = bfd_make_section_old_way (abfd, _DATA);
+ value -= section->vma;
+ break;
+ case scBss:
+ section = bfd_make_section_old_way (abfd, _BSS);
+ value -= section->vma;
+ break;
+ case scAbs:
+ section = bfd_abs_section_ptr;
+ break;
+ case scUndefined:
+ section = bfd_und_section_ptr;
+ break;
+ case scSData:
+ section = bfd_make_section_old_way (abfd, _SDATA);
+ value -= section->vma;
+ break;
+ case scSBss:
+ section = bfd_make_section_old_way (abfd, _SBSS);
+ value -= section->vma;
+ break;
+ case scRData:
+ section = bfd_make_section_old_way (abfd, _RDATA);
+ value -= section->vma;
+ break;
+ case scCommon:
+ if (value > ecoff_data (abfd)->gp_size)
{
- file_offset = H_GET_32 (abfd, hashtable + (srch * 8) + 4);
- if (file_offset == 0)
- break;
- name = stringbase + H_GET_32 (abfd, hashtable + (srch * 8));
- if (name[0] == h->root.string[0]
- && strcmp (name, h->root.string) == 0)
- {
- found = TRUE;
- break;
- }
+ section = bfd_com_section_ptr;
+ break;
}
-
- if (! found)
+ /* Fall through. */
+ case scSCommon:
+ if (ecoff_scom_section.name == NULL)
{
- pundef = &(*pundef)->u.undef.next;
- continue;
+ /* Initialize the small common section. */
+ ecoff_scom_section.name = SCOMMON;
+ ecoff_scom_section.flags = SEC_IS_COMMON;
+ ecoff_scom_section.output_section = &ecoff_scom_section;
+ ecoff_scom_section.symbol = &ecoff_scom_symbol;
+ ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr;
+ ecoff_scom_symbol.name = SCOMMON;
+ ecoff_scom_symbol.flags = BSF_SECTION_SYM;
+ ecoff_scom_symbol.section = &ecoff_scom_section;
+ ecoff_scom_symbol_ptr = &ecoff_scom_symbol;
}
-
- hash = srch;
+ section = &ecoff_scom_section;
+ break;
+ case scSUndefined:
+ section = bfd_und_section_ptr;
+ break;
+ case scInit:
+ section = bfd_make_section_old_way (abfd, _INIT);
+ value -= section->vma;
+ break;
+ case scFini:
+ section = bfd_make_section_old_way (abfd, _FINI);
+ value -= section->vma;
+ break;
+ case scRConst:
+ section = bfd_make_section_old_way (abfd, _RCONST);
+ value -= section->vma;
+ break;
}
- element = (*backend->get_elt_at_filepos) (abfd, (file_ptr) file_offset);
- if (element == (bfd *) NULL)
- return FALSE;
+ if (section == NULL)
+ continue;
- if (! bfd_check_format (element, bfd_object))
- return FALSE;
+ name = ssext + esym.asym.iss;
- /* Unlike the generic linker, we know that this element provides
- a definition for an undefined symbol and we know that we want
- to include it. We don't need to check anything. */
- if (! (*info->callbacks->add_archive_element) (info, element, name))
- return FALSE;
- if (! ecoff_link_add_object_symbols (element, info))
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, name,
+ (flagword) (esym.weakext ? BSF_WEAK : BSF_GLOBAL),
+ section, value, NULL, TRUE, TRUE, sym_hash)))
return FALSE;
- pundef = &(*pundef)->u.undef.next;
+ h = (struct ecoff_link_hash_entry *) *sym_hash;
+
+ /* If we are building an ECOFF hash table, save the external
+ symbol information. */
+ if (info->hash->creator->flavour == bfd_get_flavour (abfd))
+ {
+ if (h->abfd == NULL
+ || (! bfd_is_und_section (section)
+ && (! bfd_is_com_section (section)
+ || (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak))))
+ {
+ h->abfd = abfd;
+ h->esym = esym;
+ }
+
+ /* Remember whether this symbol was small undefined. */
+ if (esym.asym.sc == scSUndefined)
+ h->small = 1;
+
+ /* If this symbol was ever small undefined, it needs to wind
+ up in a GP relative section. We can't control the
+ section of a defined symbol, but we can control the
+ section of a common symbol. This case is actually needed
+ on Ultrix 4.2 to handle the symbol cred in -lckrb. */
+ if (h->small
+ && h->root.type == bfd_link_hash_common
+ && streq (h->root.u.c.p->section->name, SCOMMON))
+ {
+ h->root.u.c.p->section = bfd_make_section_old_way (abfd,
+ SCOMMON);
+ h->root.u.c.p->section->flags = SEC_ALLOC;
+ if (h->esym.asym.sc == scCommon)
+ h->esym.asym.sc = scSCommon;
+ }
+ }
}
return TRUE;
}
+/* Add symbols from an ECOFF object file to the global linker hash
+ table. */
+
+static bfd_boolean
+ecoff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
+{
+ HDRR *symhdr;
+ bfd_size_type external_ext_size;
+ void * external_ext = NULL;
+ bfd_size_type esize;
+ char *ssext = NULL;
+ bfd_boolean result;
+
+ if (! ecoff_slurp_symbolic_header (abfd))
+ return FALSE;
+
+ /* If there are no symbols, we don't want it. */
+ if (bfd_get_symcount (abfd) == 0)
+ return TRUE;
+
+ symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
+
+ /* Read in the external symbols and external strings. */
+ external_ext_size = ecoff_backend (abfd)->debug_swap.external_ext_size;
+ esize = symhdr->iextMax * external_ext_size;
+ external_ext = bfd_malloc (esize);
+ if (external_ext == NULL && esize != 0)
+ goto error_return;
+
+ if (bfd_seek (abfd, (file_ptr) symhdr->cbExtOffset, SEEK_SET) != 0
+ || bfd_bread (external_ext, esize, abfd) != esize)
+ goto error_return;
+
+ ssext = bfd_malloc ((bfd_size_type) symhdr->issExtMax);
+ if (ssext == NULL && symhdr->issExtMax != 0)
+ goto error_return;
+
+ if (bfd_seek (abfd, (file_ptr) symhdr->cbSsExtOffset, SEEK_SET) != 0
+ || (bfd_bread (ssext, (bfd_size_type) symhdr->issExtMax, abfd)
+ != (bfd_size_type) symhdr->issExtMax))
+ goto error_return;
+
+ result = ecoff_link_add_externals (abfd, info, external_ext, ssext);
+
+ if (ssext != NULL)
+ free (ssext);
+ if (external_ext != NULL)
+ free (external_ext);
+ return result;
+
+ error_return:
+ if (ssext != NULL)
+ free (ssext);
+ if (external_ext != NULL)
+ free (external_ext);
+ return FALSE;
+}
+
/* This is called if we used _bfd_generic_link_add_archive_symbols
because we were not dealing with an ECOFF archive. */
static bfd_boolean
-ecoff_link_check_archive_element (abfd, info, pneeded)
- bfd *abfd;
- struct bfd_link_info *info;
- bfd_boolean *pneeded;
+ecoff_link_check_archive_element (bfd *abfd,
+ struct bfd_link_info *info,
+ bfd_boolean *pneeded)
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
- void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *))
+ void (* const swap_ext_in) (bfd *, void *, EXTR *)
= backend->debug_swap.swap_ext_in;
HDRR *symhdr;
bfd_size_type external_ext_size;
- PTR external_ext = NULL;
+ void * external_ext = NULL;
bfd_size_type esize;
char *ssext = NULL;
char *ext_ptr;
/* Read in the external symbols and external strings. */
external_ext_size = backend->debug_swap.external_ext_size;
esize = symhdr->iextMax * external_ext_size;
- external_ext = (PTR) bfd_malloc (esize);
+ external_ext = bfd_malloc (esize);
if (external_ext == NULL && esize != 0)
goto error_return;
|| bfd_bread (external_ext, esize, abfd) != esize)
goto error_return;
- ssext = (char *) bfd_malloc ((bfd_size_type) symhdr->issExtMax);
+ ssext = bfd_malloc ((bfd_size_type) symhdr->issExtMax);
if (ssext == NULL && symhdr->issExtMax != 0)
goto error_return;
const char *name;
struct bfd_link_hash_entry *h;
- (*swap_ext_in) (abfd, (PTR) ext_ptr, &esym);
+ (*swap_ext_in) (abfd, (void *) ext_ptr, &esym);
/* See if this symbol defines something. */
if (esym.asym.st != stGlobal
/* Unlike the generic linker, we do not pull in elements because
of common symbols. */
- if (h == (struct bfd_link_hash_entry *) NULL
+ if (h == NULL
|| h->type != bfd_link_hash_undefined)
continue;
return FALSE;
}
-/* Add symbols from an ECOFF object file to the global linker hash
- table. */
+/* Add the symbols from an archive file to the global hash table.
+ This looks through the undefined symbols, looks each one up in the
+ archive hash table, and adds any associated object file. We do not
+ use _bfd_generic_link_add_archive_symbols because ECOFF archives
+ already have a hash table, so there is no reason to construct
+ another one. */
static bfd_boolean
-ecoff_link_add_object_symbols (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+ecoff_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
{
- HDRR *symhdr;
- bfd_size_type external_ext_size;
- PTR external_ext = NULL;
- bfd_size_type esize;
- char *ssext = NULL;
- bfd_boolean result;
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ const bfd_byte *raw_armap;
+ struct bfd_link_hash_entry **pundef;
+ unsigned int armap_count;
+ unsigned int armap_log;
+ unsigned int i;
+ const bfd_byte *hashtable;
+ const char *stringbase;
- if (! ecoff_slurp_symbolic_header (abfd))
- return FALSE;
+ if (! bfd_has_map (abfd))
+ {
+ /* An empty archive is a special case. */
+ if (bfd_openr_next_archived_file (abfd, NULL) == NULL)
+ return TRUE;
+ bfd_set_error (bfd_error_no_armap);
+ return FALSE;
+ }
- /* If there are no symbols, we don't want it. */
- if (bfd_get_symcount (abfd) == 0)
- return TRUE;
+ /* If we don't have any raw data for this archive, as can happen on
+ Irix 4.0.5F, we call the generic routine.
+ FIXME: We should be more clever about this, since someday tdata
+ may get to something for a generic archive. */
+ raw_armap = (const bfd_byte *) bfd_ardata (abfd)->tdata;
+ if (raw_armap == NULL)
+ return (_bfd_generic_link_add_archive_symbols
+ (abfd, info, ecoff_link_check_archive_element));
- symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
+ armap_count = H_GET_32 (abfd, raw_armap);
- /* Read in the external symbols and external strings. */
- external_ext_size = ecoff_backend (abfd)->debug_swap.external_ext_size;
- esize = symhdr->iextMax * external_ext_size;
- external_ext = (PTR) bfd_malloc (esize);
- if (external_ext == NULL && esize != 0)
- goto error_return;
+ armap_log = 0;
+ for (i = 1; i < armap_count; i <<= 1)
+ armap_log++;
+ BFD_ASSERT (i == armap_count);
- if (bfd_seek (abfd, (file_ptr) symhdr->cbExtOffset, SEEK_SET) != 0
- || bfd_bread (external_ext, esize, abfd) != esize)
- goto error_return;
+ hashtable = raw_armap + 4;
+ stringbase = (const char *) raw_armap + armap_count * 8 + 8;
- ssext = (char *) bfd_malloc ((bfd_size_type) symhdr->issExtMax);
- if (ssext == NULL && symhdr->issExtMax != 0)
- goto error_return;
+ /* Look through the list of undefined symbols. */
+ pundef = &info->hash->undefs;
+ while (*pundef != NULL)
+ {
+ struct bfd_link_hash_entry *h;
+ unsigned int hash, rehash;
+ unsigned int file_offset;
+ const char *name;
+ bfd *element;
- if (bfd_seek (abfd, (file_ptr) symhdr->cbSsExtOffset, SEEK_SET) != 0
- || (bfd_bread (ssext, (bfd_size_type) symhdr->issExtMax, abfd)
- != (bfd_size_type) symhdr->issExtMax))
- goto error_return;
+ h = *pundef;
- result = ecoff_link_add_externals (abfd, info, external_ext, ssext);
+ /* When a symbol is defined, it is not necessarily removed from
+ the list. */
+ if (h->type != bfd_link_hash_undefined
+ && h->type != bfd_link_hash_common)
+ {
+ /* Remove this entry from the list, for general cleanliness
+ and because we are going to look through the list again
+ if we search any more libraries. We can't remove the
+ entry if it is the tail, because that would lose any
+ entries we add to the list later on. */
+ if (*pundef != info->hash->undefs_tail)
+ *pundef = (*pundef)->u.undef.next;
+ else
+ pundef = &(*pundef)->u.undef.next;
+ continue;
+ }
- if (ssext != NULL)
- free (ssext);
- if (external_ext != NULL)
- free (external_ext);
- return result;
+ /* Native ECOFF linkers do not pull in archive elements merely
+ to satisfy common definitions, so neither do we. We leave
+ them on the list, though, in case we are linking against some
+ other object format. */
+ if (h->type != bfd_link_hash_undefined)
+ {
+ pundef = &(*pundef)->u.undef.next;
+ continue;
+ }
- error_return:
- if (ssext != NULL)
- free (ssext);
- if (external_ext != NULL)
- free (external_ext);
- return FALSE;
-}
+ /* Look for this symbol in the archive hash table. */
+ hash = ecoff_armap_hash (h->root.string, &rehash, armap_count,
+ armap_log);
-/* Add the external symbols of an object file to the global linker
- hash table. The external symbols and strings we are passed are
- just allocated on the stack, and will be discarded. We must
- explicitly save any information we may need later on in the link.
- We do not want to read the external symbol information again. */
-
-static bfd_boolean
-ecoff_link_add_externals (abfd, info, external_ext, ssext)
- bfd *abfd;
- struct bfd_link_info *info;
- PTR external_ext;
- char *ssext;
-{
- const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
- void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *))
- = backend->debug_swap.swap_ext_in;
- bfd_size_type external_ext_size = backend->debug_swap.external_ext_size;
- unsigned long ext_count;
- struct bfd_link_hash_entry **sym_hash;
- char *ext_ptr;
- char *ext_end;
- bfd_size_type amt;
-
- ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
-
- amt = ext_count;
- amt *= sizeof (struct bfd_link_hash_entry *);
- sym_hash = (struct bfd_link_hash_entry **) bfd_alloc (abfd, amt);
- if (!sym_hash)
- return FALSE;
- ecoff_data (abfd)->sym_hashes = (struct ecoff_link_hash_entry **) sym_hash;
-
- ext_ptr = (char *) external_ext;
- ext_end = ext_ptr + ext_count * external_ext_size;
- for (; ext_ptr < ext_end; ext_ptr += external_ext_size, sym_hash++)
- {
- EXTR esym;
- bfd_boolean skip;
- bfd_vma value;
- asection *section;
- const char *name;
- struct ecoff_link_hash_entry *h;
-
- *sym_hash = NULL;
-
- (*swap_ext_in) (abfd, (PTR) ext_ptr, &esym);
-
- /* Skip debugging symbols. */
- skip = FALSE;
- switch (esym.asym.st)
+ file_offset = H_GET_32 (abfd, hashtable + (hash * 8) + 4);
+ if (file_offset == 0)
{
- case stGlobal:
- case stStatic:
- case stLabel:
- case stProc:
- case stStaticProc:
- break;
- default:
- skip = TRUE;
- break;
+ /* Nothing in this slot. */
+ pundef = &(*pundef)->u.undef.next;
+ continue;
}
- if (skip)
- continue;
-
- /* Get the information for this symbol. */
- value = esym.asym.value;
- switch (esym.asym.sc)
+ name = stringbase + H_GET_32 (abfd, hashtable + (hash * 8));
+ if (name[0] != h->root.string[0]
+ || ! streq (name, h->root.string))
{
- default:
- case scNil:
- case scRegister:
- case scCdbLocal:
- case scBits:
- case scCdbSystem:
- case scRegImage:
- case scInfo:
- case scUserStruct:
- case scVar:
- case scVarRegister:
- case scVariant:
- case scBasedVar:
- case scXData:
- case scPData:
- section = NULL;
- break;
- case scText:
- section = bfd_make_section_old_way (abfd, ".text");
- value -= section->vma;
- break;
- case scData:
- section = bfd_make_section_old_way (abfd, ".data");
- value -= section->vma;
- break;
- case scBss:
- section = bfd_make_section_old_way (abfd, ".bss");
- value -= section->vma;
- break;
- case scAbs:
- section = bfd_abs_section_ptr;
- break;
- case scUndefined:
- section = bfd_und_section_ptr;
- break;
- case scSData:
- section = bfd_make_section_old_way (abfd, ".sdata");
- value -= section->vma;
- break;
- case scSBss:
- section = bfd_make_section_old_way (abfd, ".sbss");
- value -= section->vma;
- break;
- case scRData:
- section = bfd_make_section_old_way (abfd, ".rdata");
- value -= section->vma;
- break;
- case scCommon:
- if (value > ecoff_data (abfd)->gp_size)
+ unsigned int srch;
+ bfd_boolean found;
+
+ /* That was the wrong symbol. Try rehashing. */
+ found = FALSE;
+ for (srch = (hash + rehash) & (armap_count - 1);
+ srch != hash;
+ srch = (srch + rehash) & (armap_count - 1))
{
- section = bfd_com_section_ptr;
- break;
+ file_offset = H_GET_32 (abfd, hashtable + (srch * 8) + 4);
+ if (file_offset == 0)
+ break;
+ name = stringbase + H_GET_32 (abfd, hashtable + (srch * 8));
+ if (name[0] == h->root.string[0]
+ && streq (name, h->root.string))
+ {
+ found = TRUE;
+ break;
+ }
}
- /* Fall through. */
- case scSCommon:
- if (ecoff_scom_section.name == NULL)
+
+ if (! found)
{
- /* Initialize the small common section. */
- ecoff_scom_section.name = SCOMMON;
- ecoff_scom_section.flags = SEC_IS_COMMON;
- ecoff_scom_section.output_section = &ecoff_scom_section;
- ecoff_scom_section.symbol = &ecoff_scom_symbol;
- ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr;
- ecoff_scom_symbol.name = SCOMMON;
- ecoff_scom_symbol.flags = BSF_SECTION_SYM;
- ecoff_scom_symbol.section = &ecoff_scom_section;
- ecoff_scom_symbol_ptr = &ecoff_scom_symbol;
+ pundef = &(*pundef)->u.undef.next;
+ continue;
}
- section = &ecoff_scom_section;
- break;
- case scSUndefined:
- section = bfd_und_section_ptr;
- break;
- case scInit:
- section = bfd_make_section_old_way (abfd, ".init");
- value -= section->vma;
- break;
- case scFini:
- section = bfd_make_section_old_way (abfd, ".fini");
- value -= section->vma;
- break;
- case scRConst:
- section = bfd_make_section_old_way (abfd, ".rconst");
- value -= section->vma;
- break;
+
+ hash = srch;
}
- if (section == (asection *) NULL)
- continue;
+ element = (*backend->get_elt_at_filepos) (abfd, (file_ptr) file_offset);
+ if (element == NULL)
+ return FALSE;
- name = ssext + esym.asym.iss;
+ if (! bfd_check_format (element, bfd_object))
+ return FALSE;
- if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, name,
- (flagword) (esym.weakext ? BSF_WEAK : BSF_GLOBAL),
- section, value, (const char *) NULL, TRUE, TRUE, sym_hash)))
+ /* Unlike the generic linker, we know that this element provides
+ a definition for an undefined symbol and we know that we want
+ to include it. We don't need to check anything. */
+ if (! (*info->callbacks->add_archive_element) (info, element, name))
+ return FALSE;
+ if (! ecoff_link_add_object_symbols (element, info))
return FALSE;
- h = (struct ecoff_link_hash_entry *) *sym_hash;
+ pundef = &(*pundef)->u.undef.next;
+ }
- /* If we are building an ECOFF hash table, save the external
- symbol information. */
- if (info->hash->creator->flavour == bfd_get_flavour (abfd))
- {
- if (h->abfd == (bfd *) NULL
- || (! bfd_is_und_section (section)
- && (! bfd_is_com_section (section)
- || (h->root.type != bfd_link_hash_defined
- && h->root.type != bfd_link_hash_defweak))))
- {
- h->abfd = abfd;
- h->esym = esym;
- }
+ return TRUE;
+}
- /* Remember whether this symbol was small undefined. */
- if (esym.asym.sc == scSUndefined)
- h->small = 1;
+/* Given an ECOFF BFD, add symbols to the global hash table as
+ appropriate. */
- /* If this symbol was ever small undefined, it needs to wind
- up in a GP relative section. We can't control the
- section of a defined symbol, but we can control the
- section of a common symbol. This case is actually needed
- on Ultrix 4.2 to handle the symbol cred in -lckrb. */
- if (h->small
- && h->root.type == bfd_link_hash_common
- && strcmp (h->root.u.c.p->section->name, SCOMMON) != 0)
- {
- h->root.u.c.p->section = bfd_make_section_old_way (abfd,
- SCOMMON);
- h->root.u.c.p->section->flags = SEC_ALLOC;
- if (h->esym.asym.sc == scCommon)
- h->esym.asym.sc = scSCommon;
- }
- }
+bfd_boolean
+_bfd_ecoff_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
+{
+ switch (bfd_get_format (abfd))
+ {
+ case bfd_object:
+ return ecoff_link_add_object_symbols (abfd, info);
+ case bfd_archive:
+ return ecoff_link_add_archive_symbols (abfd, info);
+ default:
+ bfd_set_error (bfd_error_wrong_format);
+ return FALSE;
}
-
- return TRUE;
}
+
\f
/* ECOFF final link routines. */
-static bfd_boolean ecoff_final_link_debug_accumulate
- PARAMS ((bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *,
- PTR handle));
-static bfd_boolean ecoff_link_write_external
- PARAMS ((struct ecoff_link_hash_entry *, PTR));
-static bfd_boolean ecoff_indirect_link_order
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- struct bfd_link_order *));
-static bfd_boolean ecoff_reloc_link_order
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- struct bfd_link_order *));
-
/* Structure used to pass information to ecoff_link_write_external. */
struct extsym_info
struct bfd_link_info *info;
};
-/* ECOFF final link routine. This looks through all the input BFDs
- and gathers together all the debugging information, and then
- processes all the link order information. This may cause it to
- close and reopen some input BFDs; I'll see how bad this is. */
+/* Accumulate the debugging information for an input BFD into the
+ output BFD. This must read in the symbolic information of the
+ input BFD. */
-bfd_boolean
-_bfd_ecoff_bfd_final_link (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+static bfd_boolean
+ecoff_final_link_debug_accumulate (bfd *output_bfd,
+ bfd *input_bfd,
+ struct bfd_link_info *info,
+ void * handle)
{
- const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
- struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info;
- HDRR *symhdr;
- PTR handle;
- register bfd *input_bfd;
- asection *o;
- struct bfd_link_order *p;
- struct extsym_info einfo;
+ struct ecoff_debug_info * const debug = &ecoff_data (input_bfd)->debug_info;
+ const struct ecoff_debug_swap * const swap =
+ &ecoff_backend (input_bfd)->debug_swap;
+ HDRR *symhdr = &debug->symbolic_header;
+ bfd_boolean ret;
- /* We accumulate the debugging information counts in the symbolic
- header. */
- symhdr = &debug->symbolic_header;
- symhdr->vstamp = 0;
- symhdr->ilineMax = 0;
- symhdr->cbLine = 0;
- symhdr->idnMax = 0;
- symhdr->ipdMax = 0;
- symhdr->isymMax = 0;
- symhdr->ioptMax = 0;
- symhdr->iauxMax = 0;
- symhdr->issMax = 0;
- symhdr->issExtMax = 0;
- symhdr->ifdMax = 0;
- symhdr->crfd = 0;
- symhdr->iextMax = 0;
+#define READ(ptr, offset, count, size, type) \
+ if (symhdr->count == 0) \
+ debug->ptr = NULL; \
+ else \
+ { \
+ bfd_size_type amt = (bfd_size_type) size * symhdr->count; \
+ debug->ptr = bfd_malloc (amt); \
+ if (debug->ptr == NULL) \
+ { \
+ ret = FALSE; \
+ goto return_something; \
+ } \
+ if (bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \
+ || bfd_bread (debug->ptr, amt, input_bfd) != amt) \
+ { \
+ ret = FALSE; \
+ goto return_something; \
+ } \
+ }
- /* We accumulate the debugging information itself in the debug_info
- structure. */
- debug->line = NULL;
- debug->external_dnr = NULL;
- debug->external_pdr = NULL;
- debug->external_sym = NULL;
- debug->external_opt = NULL;
- debug->external_aux = NULL;
- debug->ss = NULL;
- debug->ssext = debug->ssext_end = NULL;
- debug->external_fdr = NULL;
- debug->external_rfd = NULL;
- debug->external_ext = debug->external_ext_end = NULL;
+ /* If raw_syments is not NULL, then the data was already by read by
+ _bfd_ecoff_slurp_symbolic_info. */
+ if (ecoff_data (input_bfd)->raw_syments == NULL)
+ {
+ READ (line, cbLineOffset, cbLine, sizeof (unsigned char),
+ unsigned char *);
+ READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
+ READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
+ READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
+ READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
+ READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
+ union aux_ext *);
+ READ (ss, cbSsOffset, issMax, sizeof (char), char *);
+ READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
+ READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
+ }
+#undef READ
- handle = bfd_ecoff_debug_init (abfd, debug, &backend->debug_swap, info);
- if (handle == (PTR) NULL)
- return FALSE;
+ /* We do not read the external strings or the external symbols. */
- /* Accumulate the debugging symbols from each input BFD. */
- for (input_bfd = info->input_bfds;
- input_bfd != (bfd *) NULL;
- input_bfd = input_bfd->link_next)
- {
- bfd_boolean ret;
+ ret = (bfd_ecoff_debug_accumulate
+ (handle, output_bfd, &ecoff_data (output_bfd)->debug_info,
+ &ecoff_backend (output_bfd)->debug_swap,
+ input_bfd, debug, swap, info));
- if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour)
- {
- /* Arbitrarily set the symbolic header vstamp to the vstamp
- of the first object file in the link. */
- if (symhdr->vstamp == 0)
- symhdr->vstamp
- = ecoff_data (input_bfd)->debug_info.symbolic_header.vstamp;
- ret = ecoff_final_link_debug_accumulate (abfd, input_bfd, info,
- handle);
- }
- else
- ret = bfd_ecoff_debug_accumulate_other (handle, abfd,
- debug, &backend->debug_swap,
- input_bfd, info);
- if (! ret)
- return FALSE;
+ return_something:
+ if (ecoff_data (input_bfd)->raw_syments == NULL)
+ {
+ if (debug->line != NULL)
+ free (debug->line);
+ if (debug->external_dnr != NULL)
+ free (debug->external_dnr);
+ if (debug->external_pdr != NULL)
+ free (debug->external_pdr);
+ if (debug->external_sym != NULL)
+ free (debug->external_sym);
+ if (debug->external_opt != NULL)
+ free (debug->external_opt);
+ if (debug->external_aux != NULL)
+ free (debug->external_aux);
+ if (debug->ss != NULL)
+ free (debug->ss);
+ if (debug->external_fdr != NULL)
+ free (debug->external_fdr);
+ if (debug->external_rfd != NULL)
+ free (debug->external_rfd);
- /* Combine the register masks. */
- ecoff_data (abfd)->gprmask |= ecoff_data (input_bfd)->gprmask;
- ecoff_data (abfd)->fprmask |= ecoff_data (input_bfd)->fprmask;
- ecoff_data (abfd)->cprmask[0] |= ecoff_data (input_bfd)->cprmask[0];
- ecoff_data (abfd)->cprmask[1] |= ecoff_data (input_bfd)->cprmask[1];
- ecoff_data (abfd)->cprmask[2] |= ecoff_data (input_bfd)->cprmask[2];
- ecoff_data (abfd)->cprmask[3] |= ecoff_data (input_bfd)->cprmask[3];
+ /* Make sure we don't accidentally follow one of these pointers
+ into freed memory. */
+ debug->line = NULL;
+ debug->external_dnr = NULL;
+ debug->external_pdr = NULL;
+ debug->external_sym = NULL;
+ debug->external_opt = NULL;
+ debug->external_aux = NULL;
+ debug->ss = NULL;
+ debug->external_fdr = NULL;
+ debug->external_rfd = NULL;
}
- /* Write out the external symbols. */
- einfo.abfd = abfd;
- einfo.info = info;
- ecoff_link_hash_traverse (ecoff_hash_table (info),
- ecoff_link_write_external,
- (PTR) &einfo);
+ return ret;
+}
+
+/* Relocate and write an ECOFF section into an ECOFF output file. */
+
+static bfd_boolean
+ecoff_indirect_link_order (bfd *output_bfd,
+ struct bfd_link_info *info,
+ asection *output_section,
+ struct bfd_link_order *link_order)
+{
+ asection *input_section;
+ bfd *input_bfd;
+ bfd_byte *contents = NULL;
+ bfd_size_type external_reloc_size;
+ bfd_size_type external_relocs_size;
+ void * external_relocs = NULL;
+
+ BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
+
+ if (link_order->size == 0)
+ return TRUE;
+
+ input_section = link_order->u.indirect.section;
+ input_bfd = input_section->owner;
+
+ BFD_ASSERT (input_section->output_section == output_section);
+ BFD_ASSERT (input_section->output_offset == link_order->offset);
+ BFD_ASSERT (input_section->size == link_order->size);
+
+ /* Get the section contents. */
+ if (!bfd_malloc_and_get_section (input_bfd, input_section, &contents))
+ goto error_return;
+
+ /* Get the relocs. If we are relaxing MIPS code, they will already
+ have been read in. Otherwise, we read them in now. */
+ external_reloc_size = ecoff_backend (input_bfd)->external_reloc_size;
+ external_relocs_size = external_reloc_size * input_section->reloc_count;
+
+ external_relocs = bfd_malloc (external_relocs_size);
+ if (external_relocs == NULL && external_relocs_size != 0)
+ goto error_return;
+
+ if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
+ || (bfd_bread (external_relocs, external_relocs_size, input_bfd)
+ != external_relocs_size))
+ goto error_return;
+
+ /* Relocate the section contents. */
+ if (! ((*ecoff_backend (input_bfd)->relocate_section)
+ (output_bfd, info, input_bfd, input_section, contents,
+ external_relocs)))
+ goto error_return;
+
+ /* Write out the relocated section. */
+ if (! bfd_set_section_contents (output_bfd,
+ output_section,
+ contents,
+ input_section->output_offset,
+ input_section->size))
+ goto error_return;
+ /* If we are producing relocatable output, the relocs were
+ modified, and we write them out now. We use the reloc_count
+ field of output_section to keep track of the number of relocs we
+ have output so far. */
if (info->relocatable)
{
- /* We need to make a pass over the link_orders to count up the
- number of relocations we will need to output, so that we know
- how much space they will take up. */
- for (o = abfd->sections; o != (asection *) NULL; o = o->next)
- {
- o->reloc_count = 0;
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
- if (p->type == bfd_indirect_link_order)
- o->reloc_count += p->u.indirect.section->reloc_count;
- else if (p->type == bfd_section_reloc_link_order
- || p->type == bfd_symbol_reloc_link_order)
- ++o->reloc_count;
- }
+ file_ptr pos = (output_section->rel_filepos
+ + output_section->reloc_count * external_reloc_size);
+ if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
+ || (bfd_bwrite (external_relocs, external_relocs_size, output_bfd)
+ != external_relocs_size))
+ goto error_return;
+ output_section->reloc_count += input_section->reloc_count;
}
- /* Compute the reloc and symbol file positions. */
- ecoff_compute_reloc_file_positions (abfd);
+ if (contents != NULL)
+ free (contents);
+ if (external_relocs != NULL)
+ free (external_relocs);
+ return TRUE;
- /* Write out the debugging information. */
- if (! bfd_ecoff_write_accumulated_debug (handle, abfd, debug,
- &backend->debug_swap, info,
- ecoff_data (abfd)->sym_filepos))
- return FALSE;
+ error_return:
+ if (contents != NULL)
+ free (contents);
+ if (external_relocs != NULL)
+ free (external_relocs);
+ return FALSE;
+}
- bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info);
+/* Generate a reloc when linking an ECOFF file. This is a reloc
+ requested by the linker, and does come from any input file. This
+ is used to build constructor and destructor tables when linking
+ with -Ur. */
- if (info->relocatable)
+static bfd_boolean
+ecoff_reloc_link_order (bfd *output_bfd,
+ struct bfd_link_info *info,
+ asection *output_section,
+ struct bfd_link_order *link_order)
+{
+ enum bfd_link_order_type type;
+ asection *section;
+ bfd_vma addend;
+ arelent rel;
+ struct internal_reloc in;
+ bfd_size_type external_reloc_size;
+ bfd_byte *rbuf;
+ bfd_boolean ok;
+ file_ptr pos;
+
+ type = link_order->type;
+ section = NULL;
+ addend = link_order->u.reloc.p->addend;
+
+ /* We set up an arelent to pass to the backend adjust_reloc_out
+ routine. */
+ rel.address = link_order->offset;
+
+ rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
+ if (rel.howto == 0)
{
- /* Now reset the reloc_count field of the sections in the output
- BFD to 0, so that we can use them to keep track of how many
- relocs we have output thus far. */
- for (o = abfd->sections; o != (asection *) NULL; o = o->next)
- o->reloc_count = 0;
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
- /* Get a value for the GP register. */
- if (ecoff_data (abfd)->gp == 0)
+ if (type == bfd_section_reloc_link_order)
+ {
+ section = link_order->u.reloc.p->u.section;
+ rel.sym_ptr_ptr = section->symbol_ptr_ptr;
+ }
+ else
{
struct bfd_link_hash_entry *h;
- h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
- if (h != (struct bfd_link_hash_entry *) NULL
- && h->type == bfd_link_hash_defined)
- ecoff_data (abfd)->gp = (h->u.def.value
- + h->u.def.section->output_section->vma
- + h->u.def.section->output_offset);
- else if (info->relocatable)
+ /* Treat a reloc against a defined symbol as though it were
+ actually against the section. */
+ h = bfd_wrapped_link_hash_lookup (output_bfd, info,
+ link_order->u.reloc.p->u.name,
+ FALSE, FALSE, FALSE);
+ if (h != NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak))
{
- bfd_vma lo;
-
- /* Make up a value. */
- lo = (bfd_vma) -1;
- for (o = abfd->sections; o != (asection *) NULL; o = o->next)
- {
- if (o->vma < lo
- && (strcmp (o->name, _SBSS) == 0
- || strcmp (o->name, _SDATA) == 0
- || strcmp (o->name, _LIT4) == 0
- || strcmp (o->name, _LIT8) == 0
- || strcmp (o->name, _LITA) == 0))
- lo = o->vma;
- }
- ecoff_data (abfd)->gp = lo + 0x8000;
+ type = bfd_section_reloc_link_order;
+ section = h->u.def.section->output_section;
+ /* It seems that we ought to add the symbol value to the
+ addend here, but in practice it has already been added
+ because it was passed to constructor_callback. */
+ addend += section->vma + h->u.def.section->output_offset;
}
else
{
- /* If the relocate_section function needs to do a reloc
- involving the GP value, it should make a reloc_dangerous
- callback to warn that GP is not defined. */
+ /* We can't set up a reloc against a symbol correctly,
+ because we have no asymbol structure. Currently no
+ adjust_reloc_out routine cares. */
+ rel.sym_ptr_ptr = NULL;
+ }
+ }
+
+ /* All ECOFF relocs are in-place. Put the addend into the object
+ file. */
+
+ BFD_ASSERT (rel.howto->partial_inplace);
+ if (addend != 0)
+ {
+ bfd_size_type size;
+ bfd_reloc_status_type rstat;
+ bfd_byte *buf;
+
+ size = bfd_get_reloc_size (rel.howto);
+ buf = bfd_zmalloc (size);
+ if (buf == NULL)
+ return FALSE;
+ rstat = _bfd_relocate_contents (rel.howto, output_bfd,
+ (bfd_vma) addend, buf);
+ switch (rstat)
+ {
+ case bfd_reloc_ok:
+ break;
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+ case bfd_reloc_overflow:
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, NULL,
+ (link_order->type == bfd_section_reloc_link_order
+ ? bfd_section_name (output_bfd, section)
+ : link_order->u.reloc.p->u.name),
+ rel.howto->name, addend, NULL,
+ NULL, (bfd_vma) 0)))
+ {
+ free (buf);
+ return FALSE;
+ }
+ break;
}
+ ok = bfd_set_section_contents (output_bfd, output_section, (void *) buf,
+ (file_ptr) link_order->offset, size);
+ free (buf);
+ if (! ok)
+ return FALSE;
}
- for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ rel.addend = 0;
+
+ /* Move the information into an internal_reloc structure. */
+ in.r_vaddr = (rel.address
+ + bfd_get_section_vma (output_bfd, output_section));
+ in.r_type = rel.howto->type;
+
+ if (type == bfd_symbol_reloc_link_order)
{
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
+ struct ecoff_link_hash_entry *h;
+
+ h = ((struct ecoff_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (output_bfd, info,
+ link_order->u.reloc.p->u.name,
+ FALSE, FALSE, TRUE));
+ if (h != NULL
+ && h->indx != -1)
+ in.r_symndx = h->indx;
+ else
{
- if (p->type == bfd_indirect_link_order
- && (bfd_get_flavour (p->u.indirect.section->owner)
- == bfd_target_ecoff_flavour))
- {
- if (! ecoff_indirect_link_order (abfd, info, o, p))
- return FALSE;
- }
- else if (p->type == bfd_section_reloc_link_order
- || p->type == bfd_symbol_reloc_link_order)
- {
- if (! ecoff_reloc_link_order (abfd, info, o, p))
- return FALSE;
- }
- else
- {
- if (! _bfd_default_link_order (abfd, info, o, p))
- return FALSE;
- }
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, link_order->u.reloc.p->u.name, NULL,
+ NULL, (bfd_vma) 0)))
+ return FALSE;
+ in.r_symndx = 0;
}
+ in.r_extern = 1;
}
+ else
+ {
+ const char *name;
+ unsigned int i;
+ static struct
+ {
+ const char * name;
+ long r_symndx;
+ }
+ section_symndx [] =
+ {
+ { _TEXT, RELOC_SECTION_TEXT },
+ { _RDATA, RELOC_SECTION_RDATA },
+ { _DATA, RELOC_SECTION_DATA },
+ { _SDATA, RELOC_SECTION_SDATA },
+ { _SBSS, RELOC_SECTION_SBSS },
+ { _BSS, RELOC_SECTION_BSS },
+ { _INIT, RELOC_SECTION_INIT },
+ { _LIT8, RELOC_SECTION_LIT8 },
+ { _LIT4, RELOC_SECTION_LIT4 },
+ { _XDATA, RELOC_SECTION_XDATA },
+ { _PDATA, RELOC_SECTION_PDATA },
+ { _FINI, RELOC_SECTION_FINI },
+ { _LITA, RELOC_SECTION_LITA },
+ { "*ABS*", RELOC_SECTION_ABS },
+ { _RCONST, RELOC_SECTION_RCONST }
+ };
- bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax;
-
- ecoff_data (abfd)->linker = TRUE;
-
- return TRUE;
-}
+ name = bfd_get_section_name (output_bfd, section);
-/* Accumulate the debugging information for an input BFD into the
- output BFD. This must read in the symbolic information of the
- input BFD. */
+ for (i = 0; i < ARRAY_SIZE (section_symndx); i++)
+ if (streq (name, section_symndx[i].name))
+ {
+ in.r_symndx = section_symndx[i].r_symndx;
+ break;
+ }
-static bfd_boolean
-ecoff_final_link_debug_accumulate (output_bfd, input_bfd, info, handle)
- bfd *output_bfd;
- bfd *input_bfd;
- struct bfd_link_info *info;
- PTR handle;
-{
- struct ecoff_debug_info * const debug = &ecoff_data (input_bfd)->debug_info;
- const struct ecoff_debug_swap * const swap =
- &ecoff_backend (input_bfd)->debug_swap;
- HDRR *symhdr = &debug->symbolic_header;
- bfd_boolean ret;
+ if (i == ARRAY_SIZE (section_symndx))
+ abort ();
-#define READ(ptr, offset, count, size, type) \
- if (symhdr->count == 0) \
- debug->ptr = NULL; \
- else \
- { \
- bfd_size_type amt = (bfd_size_type) size * symhdr->count; \
- debug->ptr = (type) bfd_malloc (amt); \
- if (debug->ptr == NULL) \
- { \
- ret = FALSE; \
- goto return_something; \
- } \
- if (bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \
- || bfd_bread (debug->ptr, amt, input_bfd) != amt) \
- { \
- ret = FALSE; \
- goto return_something; \
- } \
+ in.r_extern = 0;
}
- /* If raw_syments is not NULL, then the data was already by read by
- _bfd_ecoff_slurp_symbolic_info. */
- if (ecoff_data (input_bfd)->raw_syments == NULL)
- {
- READ (line, cbLineOffset, cbLine, sizeof (unsigned char),
- unsigned char *);
- READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
- READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
- READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
- READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
- READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
- union aux_ext *);
- READ (ss, cbSsOffset, issMax, sizeof (char), char *);
- READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
- READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
- }
-#undef READ
+ /* Let the BFD backend adjust the reloc. */
+ (*ecoff_backend (output_bfd)->adjust_reloc_out) (output_bfd, &rel, &in);
- /* We do not read the external strings or the external symbols. */
+ /* Get some memory and swap out the reloc. */
+ external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size;
+ rbuf = bfd_malloc (external_reloc_size);
+ if (rbuf == NULL)
+ return FALSE;
- ret = (bfd_ecoff_debug_accumulate
- (handle, output_bfd, &ecoff_data (output_bfd)->debug_info,
- &ecoff_backend (output_bfd)->debug_swap,
- input_bfd, debug, swap, info));
+ (*ecoff_backend (output_bfd)->swap_reloc_out) (output_bfd, &in, (void *) rbuf);
- return_something:
- if (ecoff_data (input_bfd)->raw_syments == NULL)
- {
- if (debug->line != NULL)
- free (debug->line);
- if (debug->external_dnr != NULL)
- free (debug->external_dnr);
- if (debug->external_pdr != NULL)
- free (debug->external_pdr);
- if (debug->external_sym != NULL)
- free (debug->external_sym);
- if (debug->external_opt != NULL)
- free (debug->external_opt);
- if (debug->external_aux != NULL)
- free (debug->external_aux);
- if (debug->ss != NULL)
- free (debug->ss);
- if (debug->external_fdr != NULL)
- free (debug->external_fdr);
- if (debug->external_rfd != NULL)
- free (debug->external_rfd);
+ pos = (output_section->rel_filepos
+ + output_section->reloc_count * external_reloc_size);
+ ok = (bfd_seek (output_bfd, pos, SEEK_SET) == 0
+ && (bfd_bwrite ((void *) rbuf, external_reloc_size, output_bfd)
+ == external_reloc_size));
- /* Make sure we don't accidentally follow one of these pointers
- into freed memory. */
- debug->line = NULL;
- debug->external_dnr = NULL;
- debug->external_pdr = NULL;
- debug->external_sym = NULL;
- debug->external_opt = NULL;
- debug->external_aux = NULL;
- debug->ss = NULL;
- debug->external_fdr = NULL;
- debug->external_rfd = NULL;
- }
+ if (ok)
+ ++output_section->reloc_count;
- return ret;
+ free (rbuf);
+
+ return ok;
}
/* Put out information for an external symbol. These come only from
the hash table. */
static bfd_boolean
-ecoff_link_write_external (h, data)
- struct ecoff_link_hash_entry *h;
- PTR data;
+ecoff_link_write_external (struct ecoff_link_hash_entry *h, void * data)
{
struct extsym_info *einfo = (struct extsym_info *) data;
bfd *output_bfd = einfo->abfd;
if (strip || h->written)
return TRUE;
- if (h->abfd == (bfd *) NULL)
+ if (h->abfd == NULL)
{
h->esym.jmptbl = 0;
h->esym.cobol_main = 0;
{
asection *output_section;
const char *name;
+ unsigned int i;
+ static struct
+ {
+ const char * name;
+ int sc;
+ }
+ section_storage_classes [] =
+ {
+ { _TEXT, scText },
+ { _DATA, scData },
+ { _SDATA, scSData },
+ { _RDATA, scRData },
+ { _BSS, scBss },
+ { _SBSS, scSBss },
+ { _INIT, scInit },
+ { _FINI, scFini },
+ { _PDATA, scPData },
+ { _XDATA, scXData },
+ { _RCONST, scRConst }
+ };
output_section = h->root.u.def.section->output_section;
name = bfd_section_name (output_section->owner, output_section);
- if (strcmp (name, _TEXT) == 0)
- h->esym.asym.sc = scText;
- else if (strcmp (name, _DATA) == 0)
- h->esym.asym.sc = scData;
- else if (strcmp (name, _SDATA) == 0)
- h->esym.asym.sc = scSData;
- else if (strcmp (name, _RDATA) == 0)
- h->esym.asym.sc = scRData;
- else if (strcmp (name, _BSS) == 0)
- h->esym.asym.sc = scBss;
- else if (strcmp (name, _SBSS) == 0)
- h->esym.asym.sc = scSBss;
- else if (strcmp (name, _INIT) == 0)
- h->esym.asym.sc = scInit;
- else if (strcmp (name, _FINI) == 0)
- h->esym.asym.sc = scFini;
- else if (strcmp (name, _PDATA) == 0)
- h->esym.asym.sc = scPData;
- else if (strcmp (name, _XDATA) == 0)
- h->esym.asym.sc = scXData;
- else if (strcmp (name, _RCONST) == 0)
- h->esym.asym.sc = scRConst;
- else
+ for (i = 0; i < ARRAY_SIZE (section_storage_classes); i++)
+ if (streq (name, section_storage_classes[i].name))
+ {
+ h->esym.asym.sc = section_storage_classes[i].sc;
+ break;
+ }
+
+ if (i == ARRAY_SIZE (section_storage_classes))
h->esym.asym.sc = scAbs;
}
&h->esym));
}
-/* Relocate and write an ECOFF section into an ECOFF output file. */
+/* ECOFF final link routine. This looks through all the input BFDs
+ and gathers together all the debugging information, and then
+ processes all the link order information. This may cause it to
+ close and reopen some input BFDs; I'll see how bad this is. */
-static bfd_boolean
-ecoff_indirect_link_order (output_bfd, info, output_section, link_order)
- bfd *output_bfd;
- struct bfd_link_info *info;
- asection *output_section;
- struct bfd_link_order *link_order;
+bfd_boolean
+_bfd_ecoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
{
- asection *input_section;
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info;
+ HDRR *symhdr;
+ void * handle;
bfd *input_bfd;
- bfd_byte *contents = NULL;
- bfd_size_type external_reloc_size;
- bfd_size_type external_relocs_size;
- PTR external_relocs = NULL;
-
- BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
-
- if (link_order->size == 0)
- return TRUE;
-
- input_section = link_order->u.indirect.section;
- input_bfd = input_section->owner;
+ asection *o;
+ struct bfd_link_order *p;
+ struct extsym_info einfo;
- BFD_ASSERT (input_section->output_section == output_section);
- BFD_ASSERT (input_section->output_offset == link_order->offset);
- BFD_ASSERT (input_section->size == link_order->size);
+ /* We accumulate the debugging information counts in the symbolic
+ header. */
+ symhdr = &debug->symbolic_header;
+ symhdr->vstamp = 0;
+ symhdr->ilineMax = 0;
+ symhdr->cbLine = 0;
+ symhdr->idnMax = 0;
+ symhdr->ipdMax = 0;
+ symhdr->isymMax = 0;
+ symhdr->ioptMax = 0;
+ symhdr->iauxMax = 0;
+ symhdr->issMax = 0;
+ symhdr->issExtMax = 0;
+ symhdr->ifdMax = 0;
+ symhdr->crfd = 0;
+ symhdr->iextMax = 0;
- /* Get the section contents. */
- if (!bfd_malloc_and_get_section (input_bfd, input_section, &contents))
- goto error_return;
+ /* We accumulate the debugging information itself in the debug_info
+ structure. */
+ debug->line = NULL;
+ debug->external_dnr = NULL;
+ debug->external_pdr = NULL;
+ debug->external_sym = NULL;
+ debug->external_opt = NULL;
+ debug->external_aux = NULL;
+ debug->ss = NULL;
+ debug->ssext = debug->ssext_end = NULL;
+ debug->external_fdr = NULL;
+ debug->external_rfd = NULL;
+ debug->external_ext = debug->external_ext_end = NULL;
- /* Get the relocs. If we are relaxing MIPS code, they will already
- have been read in. Otherwise, we read them in now. */
- external_reloc_size = ecoff_backend (input_bfd)->external_reloc_size;
- external_relocs_size = external_reloc_size * input_section->reloc_count;
+ handle = bfd_ecoff_debug_init (abfd, debug, &backend->debug_swap, info);
+ if (handle == NULL)
+ return FALSE;
- external_relocs = (PTR) bfd_malloc (external_relocs_size);
- if (external_relocs == NULL && external_relocs_size != 0)
- goto error_return;
+ /* Accumulate the debugging symbols from each input BFD. */
+ for (input_bfd = info->input_bfds;
+ input_bfd != NULL;
+ input_bfd = input_bfd->link_next)
+ {
+ bfd_boolean ret;
- if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
- || (bfd_bread (external_relocs, external_relocs_size, input_bfd)
- != external_relocs_size))
- goto error_return;
+ if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour)
+ {
+ /* Arbitrarily set the symbolic header vstamp to the vstamp
+ of the first object file in the link. */
+ if (symhdr->vstamp == 0)
+ symhdr->vstamp
+ = ecoff_data (input_bfd)->debug_info.symbolic_header.vstamp;
+ ret = ecoff_final_link_debug_accumulate (abfd, input_bfd, info,
+ handle);
+ }
+ else
+ ret = bfd_ecoff_debug_accumulate_other (handle, abfd,
+ debug, &backend->debug_swap,
+ input_bfd, info);
+ if (! ret)
+ return FALSE;
- /* Relocate the section contents. */
- if (! ((*ecoff_backend (input_bfd)->relocate_section)
- (output_bfd, info, input_bfd, input_section, contents,
- external_relocs)))
- goto error_return;
+ /* Combine the register masks. */
+ ecoff_data (abfd)->gprmask |= ecoff_data (input_bfd)->gprmask;
+ ecoff_data (abfd)->fprmask |= ecoff_data (input_bfd)->fprmask;
+ ecoff_data (abfd)->cprmask[0] |= ecoff_data (input_bfd)->cprmask[0];
+ ecoff_data (abfd)->cprmask[1] |= ecoff_data (input_bfd)->cprmask[1];
+ ecoff_data (abfd)->cprmask[2] |= ecoff_data (input_bfd)->cprmask[2];
+ ecoff_data (abfd)->cprmask[3] |= ecoff_data (input_bfd)->cprmask[3];
+ }
- /* Write out the relocated section. */
- if (! bfd_set_section_contents (output_bfd,
- output_section,
- contents,
- input_section->output_offset,
- input_section->size))
- goto error_return;
+ /* Write out the external symbols. */
+ einfo.abfd = abfd;
+ einfo.info = info;
+ ecoff_link_hash_traverse (ecoff_hash_table (info),
+ ecoff_link_write_external,
+ (void *) &einfo);
- /* If we are producing relocatable output, the relocs were
- modified, and we write them out now. We use the reloc_count
- field of output_section to keep track of the number of relocs we
- have output so far. */
if (info->relocatable)
{
- file_ptr pos = (output_section->rel_filepos
- + output_section->reloc_count * external_reloc_size);
- if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
- || (bfd_bwrite (external_relocs, external_relocs_size, output_bfd)
- != external_relocs_size))
- goto error_return;
- output_section->reloc_count += input_section->reloc_count;
+ /* We need to make a pass over the link_orders to count up the
+ number of relocations we will need to output, so that we know
+ how much space they will take up. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ o->reloc_count = 0;
+ for (p = o->link_order_head;
+ p != NULL;
+ p = p->next)
+ if (p->type == bfd_indirect_link_order)
+ o->reloc_count += p->u.indirect.section->reloc_count;
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ ++o->reloc_count;
+ }
}
- if (contents != NULL)
- free (contents);
- if (external_relocs != NULL)
- free (external_relocs);
- return TRUE;
-
- error_return:
- if (contents != NULL)
- free (contents);
- if (external_relocs != NULL)
- free (external_relocs);
- return FALSE;
-}
-
-/* Generate a reloc when linking an ECOFF file. This is a reloc
- requested by the linker, and does come from any input file. This
- is used to build constructor and destructor tables when linking
- with -Ur. */
-
-static bfd_boolean
-ecoff_reloc_link_order (output_bfd, info, output_section, link_order)
- bfd *output_bfd;
- struct bfd_link_info *info;
- asection *output_section;
- struct bfd_link_order *link_order;
-{
- enum bfd_link_order_type type;
- asection *section;
- bfd_vma addend;
- arelent rel;
- struct internal_reloc in;
- bfd_size_type external_reloc_size;
- bfd_byte *rbuf;
- bfd_boolean ok;
- file_ptr pos;
+ /* Compute the reloc and symbol file positions. */
+ ecoff_compute_reloc_file_positions (abfd);
- type = link_order->type;
- section = NULL;
- addend = link_order->u.reloc.p->addend;
+ /* Write out the debugging information. */
+ if (! bfd_ecoff_write_accumulated_debug (handle, abfd, debug,
+ &backend->debug_swap, info,
+ ecoff_data (abfd)->sym_filepos))
+ return FALSE;
- /* We set up an arelent to pass to the backend adjust_reloc_out
- routine. */
- rel.address = link_order->offset;
+ bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info);
- rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
- if (rel.howto == 0)
+ if (info->relocatable)
{
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ /* Now reset the reloc_count field of the sections in the output
+ BFD to 0, so that we can use them to keep track of how many
+ relocs we have output thus far. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ o->reloc_count = 0;
}
- if (type == bfd_section_reloc_link_order)
- {
- section = link_order->u.reloc.p->u.section;
- rel.sym_ptr_ptr = section->symbol_ptr_ptr;
- }
- else
+ /* Get a value for the GP register. */
+ if (ecoff_data (abfd)->gp == 0)
{
struct bfd_link_hash_entry *h;
- /* Treat a reloc against a defined symbol as though it were
- actually against the section. */
- h = bfd_wrapped_link_hash_lookup (output_bfd, info,
- link_order->u.reloc.p->u.name,
- FALSE, FALSE, FALSE);
+ h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
if (h != NULL
- && (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_defweak))
+ && h->type == bfd_link_hash_defined)
+ ecoff_data (abfd)->gp = (h->u.def.value
+ + h->u.def.section->output_section->vma
+ + h->u.def.section->output_offset);
+ else if (info->relocatable)
{
- type = bfd_section_reloc_link_order;
- section = h->u.def.section->output_section;
- /* It seems that we ought to add the symbol value to the
- addend here, but in practice it has already been added
- because it was passed to constructor_callback. */
- addend += section->vma + h->u.def.section->output_offset;
+ bfd_vma lo;
+
+ /* Make up a value. */
+ lo = (bfd_vma) -1;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if (o->vma < lo
+ && (streq (o->name, _SBSS)
+ || streq (o->name, _SDATA)
+ || streq (o->name, _LIT4)
+ || streq (o->name, _LIT8)
+ || streq (o->name, _LITA)))
+ lo = o->vma;
+ }
+ ecoff_data (abfd)->gp = lo + 0x8000;
}
else
{
- /* We can't set up a reloc against a symbol correctly,
- because we have no asymbol structure. Currently no
- adjust_reloc_out routine cares. */
- rel.sym_ptr_ptr = (asymbol **) NULL;
+ /* If the relocate_section function needs to do a reloc
+ involving the GP value, it should make a reloc_dangerous
+ callback to warn that GP is not defined. */
}
}
- /* All ECOFF relocs are in-place. Put the addend into the object
- file. */
-
- BFD_ASSERT (rel.howto->partial_inplace);
- if (addend != 0)
+ for (o = abfd->sections; o != NULL; o = o->next)
{
- bfd_size_type size;
- bfd_reloc_status_type rstat;
- bfd_byte *buf;
-
- size = bfd_get_reloc_size (rel.howto);
- buf = (bfd_byte *) bfd_zmalloc (size);
- if (buf == (bfd_byte *) NULL)
- return FALSE;
- rstat = _bfd_relocate_contents (rel.howto, output_bfd,
- (bfd_vma) addend, buf);
- switch (rstat)
+ for (p = o->link_order_head;
+ p != NULL;
+ p = p->next)
{
- case bfd_reloc_ok:
- break;
- default:
- case bfd_reloc_outofrange:
- abort ();
- case bfd_reloc_overflow:
- if (! ((*info->callbacks->reloc_overflow)
- (info, NULL,
- (link_order->type == bfd_section_reloc_link_order
- ? bfd_section_name (output_bfd, section)
- : link_order->u.reloc.p->u.name),
- rel.howto->name, addend, (bfd *) NULL,
- (asection *) NULL, (bfd_vma) 0)))
+ if (p->type == bfd_indirect_link_order
+ && (bfd_get_flavour (p->u.indirect.section->owner)
+ == bfd_target_ecoff_flavour))
{
- free (buf);
- return FALSE;
+ if (! ecoff_indirect_link_order (abfd, info, o, p))
+ return FALSE;
+ }
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ {
+ if (! ecoff_reloc_link_order (abfd, info, o, p))
+ return FALSE;
+ }
+ else
+ {
+ if (! _bfd_default_link_order (abfd, info, o, p))
+ return FALSE;
}
- break;
- }
- ok = bfd_set_section_contents (output_bfd, output_section, (PTR) buf,
- (file_ptr) link_order->offset, size);
- free (buf);
- if (! ok)
- return FALSE;
- }
-
- rel.addend = 0;
-
- /* Move the information into an internal_reloc structure. */
- in.r_vaddr = (rel.address
- + bfd_get_section_vma (output_bfd, output_section));
- in.r_type = rel.howto->type;
-
- if (type == bfd_symbol_reloc_link_order)
- {
- struct ecoff_link_hash_entry *h;
-
- h = ((struct ecoff_link_hash_entry *)
- bfd_wrapped_link_hash_lookup (output_bfd, info,
- link_order->u.reloc.p->u.name,
- FALSE, FALSE, TRUE));
- if (h != (struct ecoff_link_hash_entry *) NULL
- && h->indx != -1)
- in.r_symndx = h->indx;
- else
- {
- if (! ((*info->callbacks->unattached_reloc)
- (info, link_order->u.reloc.p->u.name, (bfd *) NULL,
- (asection *) NULL, (bfd_vma) 0)))
- return FALSE;
- in.r_symndx = 0;
}
- in.r_extern = 1;
- }
- else
- {
- const char *name;
-
- name = bfd_get_section_name (output_bfd, section);
- if (strcmp (name, ".text") == 0)
- in.r_symndx = RELOC_SECTION_TEXT;
- else if (strcmp (name, ".rdata") == 0)
- in.r_symndx = RELOC_SECTION_RDATA;
- else if (strcmp (name, ".data") == 0)
- in.r_symndx = RELOC_SECTION_DATA;
- else if (strcmp (name, ".sdata") == 0)
- in.r_symndx = RELOC_SECTION_SDATA;
- else if (strcmp (name, ".sbss") == 0)
- in.r_symndx = RELOC_SECTION_SBSS;
- else if (strcmp (name, ".bss") == 0)
- in.r_symndx = RELOC_SECTION_BSS;
- else if (strcmp (name, ".init") == 0)
- in.r_symndx = RELOC_SECTION_INIT;
- else if (strcmp (name, ".lit8") == 0)
- in.r_symndx = RELOC_SECTION_LIT8;
- else if (strcmp (name, ".lit4") == 0)
- in.r_symndx = RELOC_SECTION_LIT4;
- else if (strcmp (name, ".xdata") == 0)
- in.r_symndx = RELOC_SECTION_XDATA;
- else if (strcmp (name, ".pdata") == 0)
- in.r_symndx = RELOC_SECTION_PDATA;
- else if (strcmp (name, ".fini") == 0)
- in.r_symndx = RELOC_SECTION_FINI;
- else if (strcmp (name, ".lita") == 0)
- in.r_symndx = RELOC_SECTION_LITA;
- else if (strcmp (name, "*ABS*") == 0)
- in.r_symndx = RELOC_SECTION_ABS;
- else if (strcmp (name, ".rconst") == 0)
- in.r_symndx = RELOC_SECTION_RCONST;
- else
- abort ();
- in.r_extern = 0;
}
- /* Let the BFD backend adjust the reloc. */
- (*ecoff_backend (output_bfd)->adjust_reloc_out) (output_bfd, &rel, &in);
-
- /* Get some memory and swap out the reloc. */
- external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size;
- rbuf = (bfd_byte *) bfd_malloc (external_reloc_size);
- if (rbuf == (bfd_byte *) NULL)
- return FALSE;
-
- (*ecoff_backend (output_bfd)->swap_reloc_out) (output_bfd, &in, (PTR) rbuf);
-
- pos = (output_section->rel_filepos
- + output_section->reloc_count * external_reloc_size);
- ok = (bfd_seek (output_bfd, pos, SEEK_SET) == 0
- && (bfd_bwrite ((PTR) rbuf, external_reloc_size, output_bfd)
- == external_reloc_size));
-
- if (ok)
- ++output_section->reloc_count;
+ bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax;
- free (rbuf);
+ ecoff_data (abfd)->linker = TRUE;
- return ok;
+ return TRUE;
}