/* Generic ECOFF (Extended-COFF) routines.
- Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
Original version by Per Bothner.
Full support added by Ian Lance Taylor, ian@cygnus.com.
#include "libbfd.h"
#include "aout/ar.h"
#include "aout/ranlib.h"
+#include "aout/stab_gnu.h"
/* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines
some other stuff which we don't want and which conflicts with stuff
/* Prototypes for static functions. */
static int ecoff_get_magic PARAMS ((bfd *abfd));
+static long ecoff_sec_to_styp_flags PARAMS ((const char *name,
+ flagword flags));
static boolean ecoff_slurp_symbolic_header PARAMS ((bfd *abfd));
static boolean ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym,
asymbol *asym, int ext,
asymbol **indirect_ptr_ptr));
-static void ecoff_emit_aggregate PARAMS ((bfd *abfd, char *string,
+static void ecoff_emit_aggregate PARAMS ((bfd *abfd, FDR *fdr,
+ char *string,
RNDXR *rndx, long isym,
- CONST char *which));
-static char *ecoff_type_to_string PARAMS ((bfd *abfd, union aux_ext *aux_ptr,
- unsigned int indx, int bigendian));
+ const char *which));
+static char *ecoff_type_to_string PARAMS ((bfd *abfd, FDR *fdr,
+ unsigned int indx));
static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section,
asymbol **symbols));
static void ecoff_compute_section_file_positions PARAMS ((bfd *abfd));
/* Create an ECOFF object. */
boolean
-ecoff_mkobject (abfd)
+_bfd_ecoff_mkobject (abfd)
bfd *abfd;
{
abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *)
specific information. */
PTR
-ecoff_mkobject_hook (abfd, filehdr, aouthdr)
+_bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
bfd *abfd;
PTR filehdr;
PTR aouthdr;
struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
ecoff_data_type *ecoff;
- asection *regsec;
- if (ecoff_mkobject (abfd) == false)
+ if (_bfd_ecoff_mkobject (abfd) == false)
return NULL;
ecoff = ecoff_data (abfd);
ecoff->gp_size = 8;
ecoff->sym_filepos = internal_f->f_symptr;
- /* Create the .reginfo section to give programs outside BFD a way to
- see the information stored in the a.out header. See the comment
- in coff/ecoff.h. */
- regsec = bfd_make_section (abfd, REGINFO);
- if (regsec == NULL)
- return NULL;
-
if (internal_a != (struct internal_aouthdr *) NULL)
{
int i;
ecoff->fprmask = internal_a->fprmask;
if (internal_a->magic == ECOFF_AOUT_ZMAGIC)
abfd->flags |= D_PAGED;
+ else
+ abfd->flags &=~ D_PAGED;
}
/* It turns out that no special action is required by the MIPS or
/*ARGSUSED*/
asection *
-ecoff_make_section_hook (abfd, name)
+_bfd_ecoff_make_section_hook (abfd, name)
bfd *abfd;
char *name;
{
/* Initialize a new section. */
boolean
-ecoff_new_section_hook (abfd, section)
+_bfd_ecoff_new_section_hook (abfd, section)
bfd *abfd;
asection *section;
{
/* For the .pdata section, which has a special meaning on the Alpha,
- we set the alignment to 8. We correct this later in
+ we set the alignment power to 3. We correct this later in
ecoff_compute_section_file_positions. We do this hackery because
we need to know the exact unaligned size of the .pdata section in
- order to set the lnnoptr field correctly. */
+ order to set the lnnoptr field correctly. For every other
+ section we use an alignment power of 4; this could be made target
+ dependent by adding a field to ecoff_backend_data, but 4 appears
+ to be correct for both the MIPS and the Alpha. */
if (strcmp (section->name, _PDATA) == 0)
section->alignment_power = 3;
else
- section->alignment_power = abfd->xvec->align_power_min;
+ section->alignment_power = 4;
if (strcmp (section->name, _TEXT) == 0)
section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
else if (strcmp (section->name, _BSS) == 0
|| strcmp (section->name, _SBSS) == 0)
section->flags |= SEC_ALLOC;
- else if (strcmp (section->name, REGINFO) == 0)
+ else if (strcmp (section->name, _LIB) == 0)
{
- /* Setting SEC_SHARED_LIBRARY should make the linker leave the
- section completely alone. */
- section->flags |= (SEC_SHARED_LIBRARY
- | SEC_HAS_CONTENTS
- | SEC_NEVER_LOAD);
- section->_raw_size = sizeof (struct ecoff_reginfo);
+ /* An Irix 4 shared libary. */
+ section->flags |= SEC_COFF_SHARED_LIBRARY;
}
/* Probably any other section name is SEC_NEVER_LOAD, but I'm
for each target, but there aren't all that many ECOFF targets. */
boolean
-ecoff_set_arch_mach_hook (abfd, filehdr)
+_bfd_ecoff_set_arch_mach_hook (abfd, filehdr)
bfd *abfd;
PTR filehdr;
{
}
/* Get the magic number to use based on the architecture and machine.
- This is the inverse of ecoff_set_arch_mach_hook, above. */
+ This is the inverse of _bfd_ecoff_set_arch_mach_hook, above. */
static int
ecoff_get_magic (abfd)
/* Get the section s_flags to use for a section. */
-long
+static long
ecoff_sec_to_styp_flags (name, flags)
- CONST char *name;
+ const char *name;
flagword flags;
{
long styp;
styp = STYP_PDATA;
else if (strcmp (name, _XDATA) == 0)
styp = STYP_XDATA;
+ else if (strcmp (name, _LIB) == 0)
+ styp = STYP_ECOFF_LIB;
else if (flags & SEC_CODE)
styp = STYP_TEXT;
else if (flags & SEC_DATA)
/*ARGSUSED*/
flagword
-ecoff_styp_to_sec_flags (abfd, hdr)
+_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
bfd *abfd;
PTR hdr;
+ const char *name;
{
struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
long styp_flags = internal_s->s_flags;
|| (styp_flags & STYP_ECOFF_FINI))
{
if (sec_flags & SEC_NEVER_LOAD)
- sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY;
+ sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY;
else
sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
}
|| styp_flags == STYP_XDATA)
{
if (sec_flags & SEC_NEVER_LOAD)
- sec_flags |= SEC_DATA | SEC_SHARED_LIBRARY;
+ sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY;
else
sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
if ((styp_flags & STYP_RDATA)
{
sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
}
+ else if (styp_flags & STYP_ECOFF_LIB)
+ {
+ sec_flags |= SEC_COFF_SHARED_LIBRARY;
+ }
else
{
sec_flags |= SEC_ALLOC | SEC_LOAD;
return sec_flags;
}
\f
-/* Routines to swap auxiliary information in and out. I am assuming
- that the auxiliary information format is always going to be target
- independent. */
-
-/* Swap in a type information record.
- BIGEND says whether AUX symbols are big-endian or little-endian; this
- info comes from the file header record (fh-fBigendian). */
-
-void
-ecoff_swap_tir_in (bigend, ext_copy, intern)
- int bigend;
- struct tir_ext *ext_copy;
- TIR *intern;
-{
- struct tir_ext ext[1];
-
- *ext = *ext_copy; /* Make it reasonable to do in-place. */
-
- /* now the fun stuff... */
- if (bigend) {
- intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_BIG);
- intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_BIG);
- intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_BIG)
- >> TIR_BITS1_BT_SH_BIG;
- intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_BIG)
- >> TIR_BITS_TQ4_SH_BIG;
- intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_BIG)
- >> TIR_BITS_TQ5_SH_BIG;
- intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_BIG)
- >> TIR_BITS_TQ0_SH_BIG;
- intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_BIG)
- >> TIR_BITS_TQ1_SH_BIG;
- intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_BIG)
- >> TIR_BITS_TQ2_SH_BIG;
- intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_BIG)
- >> TIR_BITS_TQ3_SH_BIG;
- } else {
- intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_LITTLE);
- intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_LITTLE);
- intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_LITTLE)
- >> TIR_BITS1_BT_SH_LITTLE;
- intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_LITTLE)
- >> TIR_BITS_TQ4_SH_LITTLE;
- intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_LITTLE)
- >> TIR_BITS_TQ5_SH_LITTLE;
- intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_LITTLE)
- >> TIR_BITS_TQ0_SH_LITTLE;
- intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_LITTLE)
- >> TIR_BITS_TQ1_SH_LITTLE;
- intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_LITTLE)
- >> TIR_BITS_TQ2_SH_LITTLE;
- intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_LITTLE)
- >> TIR_BITS_TQ3_SH_LITTLE;
- }
-
-#ifdef TEST
- if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
- abort();
-#endif
-}
-
-/* Swap out a type information record.
- BIGEND says whether AUX symbols are big-endian or little-endian; this
- info comes from the file header record (fh-fBigendian). */
-
-void
-ecoff_swap_tir_out (bigend, intern_copy, ext)
- int bigend;
- TIR *intern_copy;
- struct tir_ext *ext;
-{
- TIR intern[1];
-
- *intern = *intern_copy; /* Make it reasonable to do in-place. */
-
- /* now the fun stuff... */
- if (bigend) {
- ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_BIG : 0)
- | (intern->continued ? TIR_BITS1_CONTINUED_BIG : 0)
- | ((intern->bt << TIR_BITS1_BT_SH_BIG)
- & TIR_BITS1_BT_BIG));
- ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_BIG)
- & TIR_BITS_TQ4_BIG)
- | ((intern->tq5 << TIR_BITS_TQ5_SH_BIG)
- & TIR_BITS_TQ5_BIG));
- ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_BIG)
- & TIR_BITS_TQ0_BIG)
- | ((intern->tq1 << TIR_BITS_TQ1_SH_BIG)
- & TIR_BITS_TQ1_BIG));
- ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_BIG)
- & TIR_BITS_TQ2_BIG)
- | ((intern->tq3 << TIR_BITS_TQ3_SH_BIG)
- & TIR_BITS_TQ3_BIG));
- } else {
- ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_LITTLE : 0)
- | (intern->continued ? TIR_BITS1_CONTINUED_LITTLE : 0)
- | ((intern->bt << TIR_BITS1_BT_SH_LITTLE)
- & TIR_BITS1_BT_LITTLE));
- ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_LITTLE)
- & TIR_BITS_TQ4_LITTLE)
- | ((intern->tq5 << TIR_BITS_TQ5_SH_LITTLE)
- & TIR_BITS_TQ5_LITTLE));
- ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_LITTLE)
- & TIR_BITS_TQ0_LITTLE)
- | ((intern->tq1 << TIR_BITS_TQ1_SH_LITTLE)
- & TIR_BITS_TQ1_LITTLE));
- ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_LITTLE)
- & TIR_BITS_TQ2_LITTLE)
- | ((intern->tq3 << TIR_BITS_TQ3_SH_LITTLE)
- & TIR_BITS_TQ3_LITTLE));
- }
-
-#ifdef TEST
- if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
- abort();
-#endif
-}
-
-/* Swap in a relative symbol record. BIGEND says whether it is in
- big-endian or little-endian format.*/
-
-void
-ecoff_swap_rndx_in (bigend, ext_copy, intern)
- int bigend;
- struct rndx_ext *ext_copy;
- RNDXR *intern;
-{
- struct rndx_ext ext[1];
-
- *ext = *ext_copy; /* Make it reasonable to do in-place. */
-
- /* now the fun stuff... */
- if (bigend) {
- intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_BIG)
- | ((ext->r_bits[1] & RNDX_BITS1_RFD_BIG)
- >> RNDX_BITS1_RFD_SH_BIG);
- intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_BIG)
- << RNDX_BITS1_INDEX_SH_LEFT_BIG)
- | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_BIG)
- | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_BIG);
- } else {
- intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_LITTLE)
- | ((ext->r_bits[1] & RNDX_BITS1_RFD_LITTLE)
- << RNDX_BITS1_RFD_SH_LEFT_LITTLE);
- intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE)
- >> RNDX_BITS1_INDEX_SH_LITTLE)
- | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE)
- | ((unsigned int) ext->r_bits[3]
- << RNDX_BITS3_INDEX_SH_LEFT_LITTLE);
- }
-
-#ifdef TEST
- if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
- abort();
-#endif
-}
-
-/* Swap out a relative symbol record. BIGEND says whether it is in
- big-endian or little-endian format.*/
-
-void
-ecoff_swap_rndx_out (bigend, intern_copy, ext)
- int bigend;
- RNDXR *intern_copy;
- struct rndx_ext *ext;
-{
- RNDXR intern[1];
-
- *intern = *intern_copy; /* Make it reasonable to do in-place. */
-
- /* now the fun stuff... */
- if (bigend) {
- ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_BIG;
- ext->r_bits[1] = (((intern->rfd << RNDX_BITS1_RFD_SH_BIG)
- & RNDX_BITS1_RFD_BIG)
- | ((intern->index >> RNDX_BITS1_INDEX_SH_LEFT_BIG)
- & RNDX_BITS1_INDEX_BIG));
- ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_BIG;
- ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_BIG;
- } else {
- ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_LITTLE;
- ext->r_bits[1] = (((intern->rfd >> RNDX_BITS1_RFD_SH_LEFT_LITTLE)
- & RNDX_BITS1_RFD_LITTLE)
- | ((intern->index << RNDX_BITS1_INDEX_SH_LITTLE)
- & RNDX_BITS1_INDEX_LITTLE));
- ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_LITTLE;
- ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_LITTLE;
- }
-
-#ifdef TEST
- if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
- abort();
-#endif
-}
-\f
/* Read in the symbolic header for an ECOFF object file. */
static boolean
}
/* Read in and swap the important symbolic information for an ECOFF
- object file. This is called by gdb. */
+ object file. This is called by gdb via the read_debug_info entry
+ point in the backend structure. */
+/*ARGSUSED*/
boolean
-ecoff_slurp_symbolic_info (abfd)
+_bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug)
bfd *abfd;
+ asection *ignore;
+ struct ecoff_debug_info *debug;
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
HDRR *internal_symhdr;
bfd_size_type raw_end;
bfd_size_type cb_end;
+ BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info);
+
/* Check whether we've already gotten it, and whether there's any to
get. */
if (ecoff_data (abfd)->raw_syments != (PTR) NULL)
if (! ecoff_slurp_symbolic_header (abfd))
return false;
- internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
+ internal_symhdr = &debug->symbolic_header;
/* Read all the symbolic information at once. */
raw_base = (ecoff_data (abfd)->sym_filepos
/* Get pointers for the numeric offsets in the HDRR structure. */
#define FIX(off1, off2, type) \
if (internal_symhdr->off1 == 0) \
- ecoff_data (abfd)->debug_info.off2 = (type) NULL; \
+ debug->off2 = (type) NULL; \
else \
- ecoff_data (abfd)->debug_info.off2 = (type) ((char *) raw \
- + internal_symhdr->off1 \
- - raw_base)
+ 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);
We need to look at the fdr to deal with a lot of information in
the symbols, so we swap them here. */
- ecoff_data (abfd)->debug_info.fdr =
- (struct fdr *) bfd_alloc (abfd,
- (internal_symhdr->ifdMax *
- sizeof (struct fdr)));
- if (ecoff_data (abfd)->debug_info.fdr == NULL)
+ debug->fdr = (struct fdr *) bfd_alloc (abfd,
+ (internal_symhdr->ifdMax *
+ sizeof (struct fdr)));
+ if (debug->fdr == NULL)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
external_fdr_size = backend->debug_swap.external_fdr_size;
- fdr_ptr = ecoff_data (abfd)->debug_info.fdr;
- fraw_src = (char *) ecoff_data (abfd)->debug_info.external_fdr;
+ fdr_ptr = debug->fdr;
+ 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);
/* Create an empty symbol. */
asymbol *
-ecoff_make_empty_symbol (abfd)
+_bfd_ecoff_make_empty_symbol (abfd)
bfd *abfd;
{
ecoff_symbol_type *new;
asym->the_bfd = abfd;
asym->value = ecoff_sym->value;
asym->section = &bfd_debug_section;
- asym->udata = NULL;
+ asym->udata.i = 0;
/* An indirect symbol requires two consecutive stabs symbols. */
if (*indirect_ptr_ptr != (asymbol *) NULL)
(*indirect_ptr_ptr)->value = (bfd_vma) asym;
asym->flags = BSF_DEBUGGING;
- asym->section = &bfd_und_section;
+ asym->section = bfd_und_section_ptr;
*indirect_ptr_ptr = NULL;
return true;
}
&& (ECOFF_UNMARK_STAB (ecoff_sym->index) | N_EXT) == (N_INDR | N_EXT))
{
asym->flags = BSF_DEBUGGING | BSF_INDIRECT;
- asym->section = &bfd_ind_section;
+ asym->section = bfd_ind_section_ptr;
/* Pass this symbol on to the next call to this function. */
*indirect_ptr_ptr = asym;
return true;
if (ext)
asym->flags = BSF_EXPORT | BSF_GLOBAL;
else
- asym->flags = BSF_LOCAL;
+ {
+ asym->flags = BSF_LOCAL;
+ /* Normally, a local stProc symbol will have a corresponding
+ external symbol. We mark the local symbol as a debugging
+ symbol, in order to prevent nm from printing both out.
+ Similarly, we mark stLabel and stabs symbols as debugging
+ symbols. In both cases, we do want to set the value
+ correctly based on the symbol class. */
+ if (ecoff_sym->st == stProc
+ || ecoff_sym->st == stLabel
+ || ECOFF_IS_STAB (ecoff_sym))
+ asym->flags |= BSF_DEBUGGING;
+ }
switch (ecoff_sym->sc)
{
case scNil:
asym->flags = BSF_DEBUGGING;
break;
case scAbs:
- asym->section = &bfd_abs_section;
+ asym->section = bfd_abs_section_ptr;
break;
case scUndefined:
- asym->section = &bfd_und_section;
+ asym->section = bfd_und_section_ptr;
asym->flags = 0;
asym->value = 0;
break;
case scCommon:
if (asym->value > ecoff_data (abfd)->gp_size)
{
- asym->section = &bfd_com_section;
+ asym->section = bfd_com_section_ptr;
asym->flags = 0;
break;
}
asym->flags = BSF_DEBUGGING;
break;
case scSUndefined:
- asym->section = &bfd_und_section;
+ asym->section = bfd_und_section_ptr;
asym->flags = 0;
asym->value = 0;
break;
/* Read an ECOFF symbol table. */
boolean
-ecoff_slurp_symbol_table (abfd)
+_bfd_ecoff_slurp_symbol_table (abfd)
bfd *abfd;
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
return true;
/* Get the symbolic information. */
- if (ecoff_slurp_symbolic_info (abfd) == false)
+ if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL,
+ &ecoff_data (abfd)->debug_info))
return false;
if (bfd_get_symcount (abfd) == 0)
return true;
/* Return the amount of space needed for the canonical symbols. */
-unsigned int
-ecoff_get_symtab_upper_bound (abfd)
+long
+_bfd_ecoff_get_symtab_upper_bound (abfd)
bfd *abfd;
{
- if (ecoff_slurp_symbolic_info (abfd) == false
- || bfd_get_symcount (abfd) == 0)
+ if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL,
+ &ecoff_data (abfd)->debug_info))
+ return -1;
+
+ if (bfd_get_symcount (abfd) == 0)
return 0;
return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *));
/* Get the canonical symbols. */
-unsigned int
-ecoff_get_symtab (abfd, alocation)
+long
+_bfd_ecoff_get_symtab (abfd, alocation)
bfd *abfd;
asymbol **alocation;
{
ecoff_symbol_type *symbase;
ecoff_symbol_type **location = (ecoff_symbol_type **) alocation;
- if (ecoff_slurp_symbol_table (abfd) == false
- || bfd_get_symcount (abfd) == 0)
+ if (_bfd_ecoff_slurp_symbol_table (abfd) == false)
+ return -1;
+ if (bfd_get_symcount (abfd) == 0)
return 0;
symbase = ecoff_data (abfd)->canonical_symbols;
/* Write aggregate information to a string. */
static void
-ecoff_emit_aggregate (abfd, string, rndx, isym, which)
+ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which)
bfd *abfd;
+ FDR *fdr;
char *string;
RNDXR *rndx;
long isym;
- CONST char *which;
+ const char *which;
{
- int ifd = rndx->rfd;
- int indx = rndx->index;
- int sym_base, ss_base;
- CONST char *name;
+ const struct ecoff_debug_swap * const debug_swap =
+ &ecoff_backend (abfd)->debug_swap;
+ struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
+ unsigned int ifd = rndx->rfd;
+ unsigned int indx = rndx->index;
+ const char *name;
if (ifd == 0xfff)
ifd = isym;
- sym_base = ecoff_data (abfd)->debug_info.fdr[ifd].isymBase;
- ss_base = ecoff_data (abfd)->debug_info.fdr[ifd].issBase;
-
- if (indx == indexNil)
- name = "/* no name */";
+ /* An ifd of -1 is an opaque type. An escaped index of 0 is a
+ struct return type of a procedure compiled without -g. */
+ if (ifd == 0xffffffff
+ || (rndx->rfd == 0xfff && indx == 0))
+ name = "<undefined>";
+ else if (indx == indexNil)
+ name = "<no name>";
else
{
- const struct ecoff_debug_swap * const debug_swap
- = &ecoff_backend (abfd)->debug_swap;
SYMR sym;
- indx += sym_base;
- (*debug_swap->swap_sym_in)
- (abfd,
- ((char *) ecoff_data (abfd)->debug_info.external_sym
- + indx * debug_swap->external_sym_size),
- &sym);
- name = ecoff_data (abfd)->debug_info.ss + ss_base + sym.iss;
+ if (debug_info->external_rfd == NULL)
+ fdr = debug_info->fdr + ifd;
+ else
+ {
+ RFDT rfd;
+
+ (*debug_swap->swap_rfd_in) (abfd,
+ ((char *) debug_info->external_rfd
+ + ((fdr->rfdBase + ifd)
+ * debug_swap->external_rfd_size)),
+ &rfd);
+ fdr = debug_info->fdr + rfd;
+ }
+
+ indx += fdr->isymBase;
+
+ (*debug_swap->swap_sym_in) (abfd,
+ ((char *) debug_info->external_sym
+ + indx * debug_swap->external_sym_size),
+ &sym);
+
+ name = debug_info->ss + fdr->issBase + sym.iss;
}
sprintf (string,
- "%s %s { ifd = %d, index = %ld }",
+ "%s %s { ifd = %u, index = %lu }",
which, name, ifd,
((long) indx
- + ecoff_data (abfd)->debug_info.symbolic_header.iextMax));
+ + debug_info->symbolic_header.iextMax));
}
/* Convert the type information to string format. */
static char *
-ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
+ecoff_type_to_string (abfd, fdr, indx)
bfd *abfd;
- union aux_ext *aux_ptr;
+ FDR *fdr;
unsigned int indx;
- int bigendian;
{
+ union aux_ext *aux_ptr;
+ int bigendian;
AUXU u;
struct qual {
unsigned int type;
int high_bound;
int stride;
} qualifiers[7];
-
unsigned int basic_type;
int i;
- static char buffer1[1024];
+ char buffer1[1024];
static char buffer2[1024];
char *p1 = buffer1;
char *p2 = buffer2;
RNDXR rndx;
+ aux_ptr = ecoff_data (abfd)->debug_info.external_aux + fdr->iauxBase;
+ bigendian = fdr->fBigendian;
+
for (i = 0; i < 7; i++)
{
qualifiers[i].low_bound = 0;
if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == -1)
return "-1 (no type)";
- ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti);
+ _bfd_ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti);
basic_type = u.ti.bt;
qualifiers[0].type = u.ti.tq0;
2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
case btStruct: /* Structure (Record) */
- ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- ecoff_emit_aggregate (abfd, p1, &rndx,
+ _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
+ ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
(long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
"struct");
indx++; /* skip aux words */
2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
case btUnion: /* Union */
- ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- ecoff_emit_aggregate (abfd, p1, &rndx,
+ _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
+ ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
(long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
"union");
indx++; /* skip aux words */
2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
case btEnum: /* Enumeration */
- ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- ecoff_emit_aggregate (abfd, p1, &rndx,
+ _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
+ ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
(long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
"enum");
indx++; /* skip aux words */
/*ARGSUSED*/
void
-ecoff_get_symbol_info (abfd, symbol, ret)
+_bfd_ecoff_get_symbol_info (abfd, symbol, ret)
bfd *abfd; /* Ignored. */
asymbol *symbol;
symbol_info *ret;
/* Print information about an ECOFF symbol. */
void
-ecoff_print_symbol (abfd, filep, symbol, how)
+_bfd_ecoff_print_symbol (abfd, filep, symbol, how)
bfd *abfd;
PTR filep;
asymbol *symbol;
if (ecoffsymbol (symbol)->fdr != NULL
&& ecoff_ext.asym.index != indexNil)
{
+ FDR *fdr;
unsigned int indx;
int bigendian;
bfd_size_type sym_base;
union aux_ext *aux_base;
+ fdr = ecoffsymbol (symbol)->fdr;
indx = ecoff_ext.asym.index;
/* sym_base is used to map the fdr relative indices which
appear in the file to the position number which we are
using. */
- sym_base = ecoffsymbol (symbol)->fdr->isymBase;
+ sym_base = fdr->isymBase;
if (ecoffsymbol (symbol)->local)
sym_base +=
ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
/* aux_base is the start of the aux entries for this file;
asym.index is an offset from this. */
aux_base = (ecoff_data (abfd)->debug_info.external_aux
- + ecoffsymbol (symbol)->fdr->iauxBase);
+ + fdr->iauxBase);
/* The aux entries are stored in host byte order; the
order is indicated by a bit in the fdr. */
- bigendian = ecoffsymbol (symbol)->fdr->fBigendian;
+ bigendian = fdr->fBigendian;
/* This switch is basically from gcc/mips-tdump.c */
switch (ecoff_ext.asym.st)
(long) (indx + sym_base));
else
fprintf (file, "\n First symbol: %ld",
- (long) (AUX_GET_ISYM (bigendian,
- &aux_base[ecoff_ext.asym.index])
- + sym_base));
+ ((long)
+ (AUX_GET_ISYM (bigendian,
+ &aux_base[ecoff_ext.asym.index])
+ + sym_base)));
break;
case stProc:
;
else if (ecoffsymbol (symbol)->local)
fprintf (file, "\n End+1 symbol: %-7ld Type: %s",
- (long) (AUX_GET_ISYM (bigendian,
- &aux_base[ecoff_ext.asym.index])
- + sym_base),
- ecoff_type_to_string (abfd, aux_base, indx + 1,
- bigendian));
+ ((long)
+ (AUX_GET_ISYM (bigendian,
+ &aux_base[ecoff_ext.asym.index])
+ + sym_base)),
+ ecoff_type_to_string (abfd, fdr, indx + 1));
else
fprintf (file, "\n Local symbol: %ld",
((long) indx
->debug_info.symbolic_header.iextMax)));
break;
+ case stStruct:
+ fprintf (file, "\n struct; End+1 symbol: %ld",
+ (long) (indx + sym_base));
+ break;
+
+ case stUnion:
+ fprintf (file, "\n union; End+1 symbol: %ld",
+ (long) (indx + sym_base));
+ break;
+
+ case stEnum:
+ fprintf (file, "\n enum; End+1 symbol: %ld",
+ (long) (indx + sym_base));
+ break;
+
default:
if (! ECOFF_IS_STAB (&ecoff_ext.asym))
fprintf (file, "\n Type: %s",
- ecoff_type_to_string (abfd, aux_base, indx,
- bigendian));
+ ecoff_type_to_string (abfd, fdr, indx));
break;
}
}
|| (section->flags & SEC_CONSTRUCTOR) != 0)
return true;
- if (ecoff_slurp_symbol_table (abfd) == false)
+ if (_bfd_ecoff_slurp_symbol_table (abfd) == false)
return false;
internal_relocs = (arelent *) bfd_alloc (abfd,
else if (intern.r_symndx == RELOC_SECTION_NONE
|| intern.r_symndx == RELOC_SECTION_ABS)
{
- rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+ rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
rptr->addend = 0;
}
else
/* Get a canonical list of relocs. */
-unsigned int
-ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
+long
+_bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
bfd *abfd;
asection *section;
arelent **relptr;
arelent *tblptr;
if (ecoff_slurp_reloc_table (abfd, section, symbols) == false)
- return 0;
+ return -1;
tblptr = section->relocation;
- if (tblptr == (arelent *) NULL)
- return 0;
for (count = 0; count < section->reloc_count; count++)
*relptr++ = tblptr++;
/*ARGSUSED*/
boolean
-ecoff_find_nearest_line (abfd,
- section,
- ignore_symbols,
- offset,
- filename_ptr,
- functionname_ptr,
- retline_ptr)
+_bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
+ filename_ptr, functionname_ptr, retline_ptr)
bfd *abfd;
asection *section;
asymbol **ignore_symbols;
{
const struct ecoff_debug_swap * const debug_swap
= &ecoff_backend (abfd)->debug_swap;
- FDR *fdr_ptr;
- FDR *fdr_start;
- FDR *fdr_end;
- FDR *fdr_hold;
- bfd_size_type external_pdr_size;
- char *pdr_ptr;
- char *pdr_end;
- PDR pdr;
- unsigned char *line_ptr;
- unsigned char *line_end;
- int lineno;
+ struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
+ struct ecoff_find_line *line_info;
/* If we're not in the .text section, we don't have any line
numbers. */
return false;
/* Make sure we have the FDR's. */
- if (ecoff_slurp_symbolic_info (abfd) == false
+ if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
|| bfd_get_symcount (abfd) == 0)
return false;
- /* Each file descriptor (FDR) has a memory address. Here we track
- down which FDR we want. The FDR's are stored in increasing
- memory order. If speed is ever important, this can become a
- binary search. We must ignore FDR's with no PDR entries; they
- will have the adr of the FDR before or after them. */
- fdr_start = ecoff_data (abfd)->debug_info.fdr;
- fdr_end = fdr_start + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax;
- fdr_hold = (FDR *) NULL;
- for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
+ if (ecoff_data (abfd)->find_line_info == NULL)
{
- if (fdr_ptr->cpd == 0)
- continue;
- if (offset < fdr_ptr->adr)
- break;
- fdr_hold = fdr_ptr;
- }
- if (fdr_hold == (FDR *) NULL)
- return false;
- fdr_ptr = fdr_hold;
-
- /* Each FDR has a list of procedure descriptors (PDR). PDR's also
- have an address, which is relative to the FDR address, and are
- also stored in increasing memory order. */
- offset -= fdr_ptr->adr;
- external_pdr_size = debug_swap->external_pdr_size;
- pdr_ptr = ((char *) ecoff_data (abfd)->debug_info.external_pdr
- + fdr_ptr->ipdFirst * external_pdr_size);
- pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
- (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-
- /* The address of the first PDR is an offset which applies to the
- addresses of all the PDR's. */
- offset += pdr.adr;
-
- for (pdr_ptr += external_pdr_size;
- pdr_ptr < pdr_end;
- pdr_ptr += external_pdr_size)
- {
- (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
- if (offset < pdr.adr)
- break;
+ ecoff_data (abfd)->find_line_info =
+ ((struct ecoff_find_line *)
+ bfd_alloc (abfd, sizeof (struct ecoff_find_line)));
+ if (ecoff_data (abfd)->find_line_info == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ ecoff_data (abfd)->find_line_info->find_buffer = NULL;
+ ecoff_data (abfd)->find_line_info->fdrtab_len = 0;
+ ecoff_data (abfd)->find_line_info->fdrtab = NULL;
}
+ line_info = ecoff_data (abfd)->find_line_info;
- /* Now we can look for the actual line number. The line numbers are
- stored in a very funky format, which I won't try to describe.
- Note that right here pdr_ptr and pdr hold the PDR *after* the one
- we want; we need this to compute line_end. */
- line_end = ecoff_data (abfd)->debug_info.line;
- if (pdr_ptr == pdr_end)
- line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
- else
- line_end += fdr_ptr->cbLineOffset + pdr.cbLineOffset;
-
- /* Now change pdr and pdr_ptr to the one we want. */
- pdr_ptr -= external_pdr_size;
- (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-
- offset -= pdr.adr;
- lineno = pdr.lnLow;
- line_ptr = (ecoff_data (abfd)->debug_info.line
- + fdr_ptr->cbLineOffset
- + pdr.cbLineOffset);
- while (line_ptr < line_end)
+ return _bfd_ecoff_locate_line (abfd, section, offset, debug_info,
+ debug_swap, line_info, filename_ptr,
+ functionname_ptr, retline_ptr);
+}
+\f
+/* Copy private BFD data. This is called by objcopy and strip. We
+ use it to copy the ECOFF debugging information from one BFD to the
+ other. It would be theoretically possible to represent the ECOFF
+ debugging information in the symbol table. However, it would be a
+ lot of work, and there would be little gain (gas, gdb, and ld
+ already access the ECOFF debugging information via the
+ ecoff_debug_info structure, and that structure would have to be
+ retained in order to support ECOFF debugging in MIPS ELF).
+
+ The debugging information for the ECOFF external symbols comes from
+ the symbol table, so this function only handles the other debugging
+ information. */
+
+boolean
+_bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd)
+ 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;
+ asymbol **sym_ptr_ptr;
+ size_t c;
+ boolean local;
+
+ /* This function is selected based on the input vector. We only
+ want to copy information over if the output BFD also uses ECOFF
+ format. */
+ if (bfd_get_flavour (obfd) != bfd_target_ecoff_flavour)
+ return true;
+
+ /* Copy the GP value and the register masks. */
+ ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp;
+ ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask;
+ ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask;
+ for (i = 0; i < 3; i++)
+ ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i];
+
+ /* Copy the version stamp. */
+ oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp;
+
+ /* 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)
+ return true;
+
+ /* See if there are any local symbols. */
+ local = false;
+ for (; c > 0; c--, sym_ptr_ptr++)
{
- int delta;
- int count;
-
- delta = *line_ptr >> 4;
- if (delta >= 0x8)
- delta -= 0x10;
- count = (*line_ptr & 0xf) + 1;
- ++line_ptr;
- if (delta == -8)
+ if (ecoffsymbol (*sym_ptr_ptr)->local)
{
- delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
- if (delta >= 0x8000)
- delta -= 0x10000;
- line_ptr += 2;
+ local = true;
+ break;
}
- lineno += delta;
- if (offset < count * 4)
- break;
- offset -= count * 4;
}
- /* If fdr_ptr->rss is -1, then this file does not have full symbols,
- at least according to gdb/mipsread.c. */
- if (fdr_ptr->rss == -1)
+ if (local)
{
- *filename_ptr = NULL;
- if (pdr.isym == -1)
- *functionname_ptr = NULL;
- else
- {
- EXTR proc_ext;
-
- (*debug_swap->swap_ext_in)
- (abfd,
- ((char *) ecoff_data (abfd)->debug_info.external_ext
- + pdr.isym * debug_swap->external_ext_size),
- &proc_ext);
- *functionname_ptr = (ecoff_data (abfd)->debug_info.ssext
- + proc_ext.asym.iss);
- }
+ /* There are some local symbols. We just bring over all the
+ debugging information. FIXME: This is not quite the right
+ thing to do. If the user has asked us to discard all
+ debugging information, then we are probably going to wind up
+ keeping it because there will probably be some local symbol
+ which objcopy did not discard. We should actually break
+ apart the debugging information and only keep that which
+ applies to the symbols we want to keep. */
+ oinfo->symbolic_header.ilineMax = iinfo->symbolic_header.ilineMax;
+ oinfo->symbolic_header.cbLine = iinfo->symbolic_header.cbLine;
+ oinfo->line = iinfo->line;
+
+ oinfo->symbolic_header.idnMax = iinfo->symbolic_header.idnMax;
+ oinfo->external_dnr = iinfo->external_dnr;
+
+ oinfo->symbolic_header.ipdMax = iinfo->symbolic_header.ipdMax;
+ oinfo->external_pdr = iinfo->external_pdr;
+
+ oinfo->symbolic_header.isymMax = iinfo->symbolic_header.isymMax;
+ oinfo->external_sym = iinfo->external_sym;
+
+ oinfo->symbolic_header.ioptMax = iinfo->symbolic_header.ioptMax;
+ oinfo->external_opt = iinfo->external_opt;
+
+ oinfo->symbolic_header.iauxMax = iinfo->symbolic_header.iauxMax;
+ oinfo->external_aux = iinfo->external_aux;
+
+ oinfo->symbolic_header.issMax = iinfo->symbolic_header.issMax;
+ oinfo->ss = iinfo->ss;
+
+ oinfo->symbolic_header.ifdMax = iinfo->symbolic_header.ifdMax;
+ oinfo->external_fdr = iinfo->external_fdr;
+
+ oinfo->symbolic_header.crfd = iinfo->symbolic_header.crfd;
+ oinfo->external_rfd = iinfo->external_rfd;
}
else
{
- SYMR proc_sym;
-
- *filename_ptr = (ecoff_data (abfd)->debug_info.ss
- + fdr_ptr->issBase
- + fdr_ptr->rss);
- (*debug_swap->swap_sym_in)
- (abfd,
- ((char *) ecoff_data (abfd)->debug_info.external_sym
- + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size),
- &proc_sym);
- *functionname_ptr = (ecoff_data (abfd)->debug_info.ss
- + fdr_ptr->issBase
- + proc_sym.iss);
+ /* We are discarding all the local symbol information. Look
+ through the external symbols and remove all references to FDR
+ or aux information. */
+ c = bfd_get_symcount (obfd);
+ sym_ptr_ptr = bfd_get_outsymbols (obfd);
+ for (; c > 0; c--, sym_ptr_ptr++)
+ {
+ EXTR esym;
+
+ (*(ecoff_backend (obfd)->debug_swap.swap_ext_in))
+ (obfd, ecoffsymbol (*sym_ptr_ptr)->native, &esym);
+ esym.ifd = ifdNil;
+ esym.asym.index = indexNil;
+ (*(ecoff_backend (obfd)->debug_swap.swap_ext_out))
+ (obfd, &esym, ecoffsymbol (*sym_ptr_ptr)->native);
+ }
}
- if (lineno == ilineNil)
- lineno = 0;
- *retline_ptr = lineno;
+
return true;
}
\f
callers ignore the return value. */
boolean
-ecoff_set_arch_mach (abfd, arch, machine)
+_bfd_ecoff_set_arch_mach (abfd, arch, machine)
bfd *abfd;
enum bfd_architecture arch;
unsigned long machine;
return arch == ecoff_backend (abfd)->arch;
}
-/* Get the size of the section headers. We do not output the .reginfo
- section. */
+/* Get the size of the section headers. */
/*ARGSUSED*/
int
-ecoff_sizeof_headers (abfd, reloc)
+_bfd_ecoff_sizeof_headers (abfd, reloc)
bfd *abfd;
boolean reloc;
{
for (current = abfd->sections;
current != (asection *)NULL;
current = current->next)
- if (strcmp (current->name, REGINFO) != 0)
- ++c;
+ ++c;
ret = (bfd_coff_filhsz (abfd)
+ bfd_coff_aoutsz (abfd)
return BFD_ALIGN (ret, 16);
}
-/* Get the contents of a section. This is where we handle reading the
- .reginfo section, which implicitly holds the contents of an
- ecoff_reginfo structure. */
+/* Get the contents of a section. */
boolean
-ecoff_get_section_contents (abfd, section, location, offset, count)
+_bfd_ecoff_get_section_contents (abfd, section, location, offset, count)
bfd *abfd;
asection *section;
PTR location;
file_ptr offset;
bfd_size_type count;
{
- ecoff_data_type *tdata = ecoff_data (abfd);
- struct ecoff_reginfo s;
- int i;
-
- if (strcmp (section->name, REGINFO) != 0)
- return bfd_generic_get_section_contents (abfd, section, location,
- offset, count);
-
- s.gp_value = tdata->gp;
- s.gprmask = tdata->gprmask;
- for (i = 0; i < 4; i++)
- s.cprmask[i] = tdata->cprmask[i];
- s.fprmask = tdata->fprmask;
-
- /* bfd_get_section_contents has already checked that the offset and
- size is reasonable. We don't have to worry about swapping or any
- such thing; the .reginfo section is defined such that the
- contents are an ecoff_reginfo structure as seen on the host. */
- memcpy (location, ((char *) &s) + offset, (size_t) count);
- return true;
+ return _bfd_generic_get_section_contents (abfd, section, location,
+ offset, count);
}
/* Calculate the file position for each section, and set
file_ptr old_sofar;
boolean first_data;
- sofar = ecoff_sizeof_headers (abfd, false);
+ sofar = _bfd_ecoff_sizeof_headers (abfd, false);
first_data = true;
for (current = abfd->sections;
unsigned int alignment_power;
/* Only deal with sections which have contents */
- if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0
- || strcmp (current->name, REGINFO) == 0)
+ if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0)
continue;
/* For the Alpha ECOFF .pdata section the lnnoptr field is
sofar = (sofar + round - 1) &~ (round - 1);
first_data = false;
}
+ else if (strcmp (current->name, _LIB) == 0)
+ {
+ const bfd_vma round = ecoff_backend (abfd)->round;
+ /* On Irix 4, the location of contents of the .lib section
+ from a shared library section is also rounded up to a
+ page boundary. */
+
+ sofar = (sofar + round - 1) &~ (round - 1);
+ }
/* Align the sections in the file to the same boundary on
which they are aligned in virtual memory. */
current != (asection *)NULL;
current = current->next)
{
- if (strcmp (current->name, REGINFO) == 0)
- continue;
if (current->reloc_count == 0)
current->rel_filepos = 0;
else
return reloc_size;
}
-/* Set the contents of a section. This is where we handle setting the
- contents of the .reginfo section, which implicitly holds a
- ecoff_reginfo structure. */
+/* Set the contents of a section. */
boolean
-ecoff_set_section_contents (abfd, section, location, offset, count)
+_bfd_ecoff_set_section_contents (abfd, section, location, offset, count)
bfd *abfd;
asection *section;
PTR location;
if (abfd->output_has_begun == false)
ecoff_compute_section_file_positions (abfd);
+ /* If this is a .lib section, bump the vma address so that it winds
+ up being the number of .lib sections output. This is right for
+ Irix 4. Ian Taylor <ian@cygnus.com>. */
+ if (strcmp (section->name, _LIB) == 0)
+ ++section->vma;
+
if (count == 0)
return true;
- if (strcmp (section->name, REGINFO) == 0)
+ if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
+ || bfd_write (location, 1, count, abfd) != count)
+ return false;
+
+ return true;
+}
+
+/* Get the GP value for an ECOFF file. This is a hook used by
+ nlmconv. */
+
+bfd_vma
+bfd_ecoff_get_gp_value (abfd)
+ bfd *abfd;
+{
+ if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+ || bfd_get_format (abfd) != bfd_object)
{
- ecoff_data_type *tdata = ecoff_data (abfd);
- struct ecoff_reginfo s;
- int i;
+ bfd_set_error (bfd_error_invalid_operation);
+ return 0;
+ }
+
+ return ecoff_data (abfd)->gp;
+}
- /* If the caller is only changing part of the structure, we must
- retrieve the current information before the memcpy. */
- if (offset != 0 || count != sizeof (struct ecoff_reginfo))
- {
- s.gp_value = tdata->gp;
- s.gprmask = tdata->gprmask;
- for (i = 0; i < 4; i++)
- s.cprmask[i] = tdata->cprmask[i];
- s.fprmask = tdata->fprmask;
- }
+/* Set the GP value for an ECOFF file. This is a hook used by the
+ assembler. */
+
+boolean
+bfd_ecoff_set_gp_value (abfd, gp_value)
+ bfd *abfd;
+ bfd_vma gp_value;
+{
+ if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+ || bfd_get_format (abfd) != bfd_object)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
- /* bfd_set_section_contents has already checked that the offset
- and size is reasonable. We don't have to worry about
- swapping or any such thing; the .reginfo section is defined
- such that the contents are an ecoff_reginfo structure as seen
- on the host. */
- memcpy (((char *) &s) + offset, location, (size_t) count);
+ ecoff_data (abfd)->gp = gp_value;
- tdata->gp = s.gp_value;
- tdata->gprmask = s.gprmask;
- for (i = 0; i < 4; i++)
- tdata->cprmask[i] = s.cprmask[i];
- tdata->fprmask = s.fprmask;
+ return true;
+}
- return true;
+/* Set the register masks for an ECOFF file. This is a hook used by
+ the assembler. */
+
+boolean
+bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask)
+ bfd *abfd;
+ unsigned long gprmask;
+ unsigned long fprmask;
+ unsigned long *cprmask;
+{
+ ecoff_data_type *tdata;
+
+ if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+ || bfd_get_format (abfd) != bfd_object)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
}
- if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
- || bfd_write (location, 1, count, abfd) != count)
- return false;
+ tdata = ecoff_data (abfd);
+ tdata->gprmask = gprmask;
+ tdata->fprmask = fprmask;
+ if (cprmask != (unsigned long *) NULL)
+ {
+ register int i;
+
+ for (i = 0; i < 3; i++)
+ tdata->cprmask[i] = cprmask[i];
+ }
return true;
}
ecoff_symbol_type *ecoff_sym_ptr;
bfd *input_bfd;
- /* Don't include debugging, local or section symbols. */
- if ((sym->flags & BSF_DEBUGGING) != 0
- || (sym->flags & BSF_LOCAL) != 0
- || (sym->flags & BSF_SECTION_SYM) != 0)
- return false;
-
if (bfd_asymbol_flavour (sym) != bfd_target_ecoff_flavour
|| ecoffsymbol (sym)->native == NULL)
{
+ /* Don't include debugging, local, or section symbols. */
+ if ((sym->flags & BSF_DEBUGGING) != 0
+ || (sym->flags & BSF_LOCAL) != 0
+ || (sym->flags & BSF_SECTION_SYM) != 0)
+ return false;
+
esym->jmptbl = 0;
esym->cobol_main = 0;
esym->weakext = 0;
ecoff_sym_ptr = ecoffsymbol (sym);
if (ecoff_sym_ptr->local)
- abort ();
+ return false;
input_bfd = bfd_asymbol_bfd (sym);
(*(ecoff_backend (input_bfd)->debug_swap.swap_ext_in))
symbol. */
if ((esym->asym.sc == scUndefined
|| esym->asym.sc == scSUndefined)
- && bfd_get_section (sym) != &bfd_und_section)
+ && ! bfd_is_und_section (bfd_get_section (sym)))
esym->asym.sc = scAbs;
/* Adjust the FDR index for the symbol by that used for the input
/* Write out an ECOFF file. */
boolean
-ecoff_write_object_contents (abfd)
+_bfd_ecoff_write_object_contents (abfd)
bfd *abfd;
{
const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
bfd_size_type reloc_size;
bfd_size_type text_size;
bfd_vma text_start;
+ boolean set_text_start;
bfd_size_type data_size;
bfd_vma data_start;
+ boolean set_data_start;
bfd_size_type bss_size;
PTR buff = NULL;
PTR reloc_buff = NULL;
current != (asection *)NULL;
current = current->next)
{
- if (strcmp (current->name, REGINFO) == 0)
- continue;
current->target_index = count;
++count;
}
if ((abfd->flags & D_PAGED) != 0)
- text_size = ecoff_sizeof_headers (abfd, false);
+ text_size = _bfd_ecoff_sizeof_headers (abfd, false);
else
text_size = 0;
text_start = 0;
+ set_text_start = false;
data_size = 0;
data_start = 0;
+ set_data_start = false;
bss_size = 0;
/* Write section headers to the file. */
struct internal_scnhdr section;
bfd_vma vma;
- if (strcmp (current->name, REGINFO) == 0)
- {
- BFD_ASSERT (current->reloc_count == 0);
- continue;
- }
-
++internal_f.f_nscns;
strncpy (section.s_name, current->name, sizeof section.s_name);
- /* FIXME: is this correct for shared libraries? I think it is
- but I have no platform to check. Ian Lance Taylor. */
+ /* This seems to be correct for Irix 4 shared libraries. */
vma = bfd_get_section_vma (abfd, current);
if (strcmp (current->name, _LIB) == 0)
section.s_vaddr = 0;
section.s_flags = ecoff_sec_to_styp_flags (current->name,
current->flags);
- bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff);
- if (bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
+ if (bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff) == 0
+ || bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
goto error_return;
if ((section.s_flags & STYP_TEXT) != 0
|| strcmp (current->name, _PDATA) == 0)
{
text_size += bfd_get_section_size_before_reloc (current);
- if (text_start == 0 || text_start > vma)
- text_start = vma;
+ if (! set_text_start || text_start > vma)
+ {
+ text_start = vma;
+ set_text_start = true;
+ }
}
else if ((section.s_flags & STYP_RDATA) != 0
|| (section.s_flags & STYP_DATA) != 0
|| strcmp (current->name, _XDATA) == 0)
{
data_size += bfd_get_section_size_before_reloc (current);
- if (data_start == 0 || data_start > vma)
- data_start = vma;
+ if (! set_data_start || data_start > vma)
+ {
+ data_start = vma;
+ set_data_start = true;
+ }
}
else if ((section.s_flags & STYP_BSS) != 0
|| (section.s_flags & STYP_SBSS) != 0)
bss_size += bfd_get_section_size_before_reloc (current);
+ else if ((section.s_flags & STYP_ECOFF_LIB) != 0)
+ /* Do nothing */ ;
else
abort ();
}
goto error_return;
/* Build the external symbol information. This must be done before
- writing out the relocs so that we know the symbol indices. The
- condition checks makes sure this object was not created by
- ecoff_bfd_final_link, since if it was we do not want to tamper
- with the external symbols. */
- if (bfd_get_outsymbols (abfd) != (asymbol **) NULL)
+ writing out the relocs so that we know the symbol indices. We
+ don't do this if this BFD was created by the backend linker,
+ since it will have already handled the symbols and relocs. */
+ if (! ecoff_data (abfd)->linker)
{
symhdr->iextMax = 0;
symhdr->issExtMax = 0;
/* Read in the armap. */
boolean
-ecoff_slurp_armap (abfd)
+_bfd_ecoff_slurp_armap (abfd)
bfd *abfd;
{
char nextname[17];
if (i != 16)
return false;
- bfd_seek (abfd, (file_ptr) -16, SEEK_CUR);
+ if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
+ return false;
/* Irix 4.0.5F apparently can use either an ECOFF armap or a
standard COFF armap. We could move the ECOFF armap stuff into
if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size)
{
- bfd_set_error (bfd_error_malformed_archive);
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_malformed_archive);
bfd_release (abfd, (PTR) raw_armap);
return false;
}
/* Write out an armap. */
boolean
-ecoff_write_armap (abfd, elength, map, orl_count, stridx)
+_bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
bfd *abfd;
unsigned int elength;
struct orl *map;
/* See whether this BFD is an archive. If it is, read in the armap
and the extended name table. */
-bfd_target *
-ecoff_archive_p (abfd)
+const bfd_target *
+_bfd_ecoff_archive_p (abfd)
bfd *abfd;
{
char armag[SARMAG + 1];
if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG
|| strncmp (armag, ARMAG, SARMAG) != 0)
{
- bfd_set_error (bfd_error_wrong_format);
- return (bfd_target *) NULL;
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return (const bfd_target *) NULL;
}
/* We are setting bfd_ardata(abfd) here, but since bfd_ardata
if (bfd_ardata (abfd) == (struct artdata *) NULL)
{
bfd_set_error (bfd_error_no_memory);
- return (bfd_target *) NULL;
+ return (const bfd_target *) NULL;
}
bfd_ardata (abfd)->first_file_filepos = SARMAG;
bfd_ardata (abfd)->extended_names = NULL;
bfd_ardata (abfd)->tdata = NULL;
- if (ecoff_slurp_armap (abfd) == false
- || ecoff_slurp_extended_name_table (abfd) == false)
+ if (_bfd_ecoff_slurp_armap (abfd) == false
+ || _bfd_ecoff_slurp_extended_name_table (abfd) == false)
{
bfd_release (abfd, bfd_ardata (abfd));
abfd->tdata.aout_ar_data = (struct artdata *) NULL;
- return (bfd_target *) NULL;
+ return (const bfd_target *) NULL;
}
return abfd->xvec;
/* Set local fields. */
ret->indx = -1;
ret->abfd = NULL;
+ ret->written = 0;
+ ret->small = 0;
}
memset ((PTR) &ret->esym, 0, sizeof ret->esym);
/* Create an ECOFF link hash table. */
struct bfd_link_hash_table *
-ecoff_bfd_link_hash_table_create (abfd)
+_bfd_ecoff_bfd_link_hash_table_create (abfd)
bfd *abfd;
{
struct ecoff_link_hash_table *ret;
appropriate. */
boolean
-ecoff_bfd_link_add_symbols (abfd, info)
+_bfd_ecoff_bfd_link_add_symbols (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
if (! bfd_has_map (abfd))
{
- bfd_set_error (bfd_error_no_symbols);
+ /* 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;
}
value -= section->vma;
break;
case scAbs:
- section = &bfd_abs_section;
+ section = bfd_abs_section_ptr;
break;
case scUndefined:
- section = &bfd_und_section;
+ section = bfd_und_section_ptr;
break;
case scSData:
section = bfd_make_section_old_way (abfd, ".sdata");
case scCommon:
if (value > ecoff_data (abfd)->gp_size)
{
- section = &bfd_com_section;
+ section = bfd_com_section_ptr;
break;
}
/* Fall through. */
section = &ecoff_scom_section;
break;
case scSUndefined:
- section = &bfd_und_section;
+ section = bfd_und_section_ptr;
break;
case scInit:
section = bfd_make_section_old_way (abfd, ".init");
name = ssext + esym.asym.iss;
+ h = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, name, BSF_GLOBAL, section, value,
(const char *) NULL, true, true,
if (info->hash->creator->flavour == bfd_get_flavour (abfd))
{
if (h->abfd == (bfd *) NULL
- || (section != &bfd_und_section
+ || (! bfd_is_und_section (section)
&& (! bfd_is_com_section (section)
- || h->root.type != bfd_link_hash_defined)))
+ || (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
+ && 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;
+ }
}
}
close and reopen some input BFDs; I'll see how bad this is. */
boolean
-ecoff_bfd_final_link (abfd, info)
+_bfd_ecoff_bfd_final_link (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
{
- /* Ignore any link_orders for the .reginfo section, which does
- not really exist. */
- if (strcmp (o->name, REGINFO) == 0)
- continue;
-
for (p = o->link_order_head;
p != (struct bfd_link_order *) NULL;
p = p->next)
bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax;
+ ecoff_data (abfd)->linker = true;
+
return true;
}
}
/* If raw_syments is not NULL, then the data was already by read by
- ecoff_slurp_symbolic_info. */
+ _bfd_ecoff_slurp_symbolic_info. */
if (ecoff_data (input_bfd)->raw_syments == NULL)
{
READ (line, cbLineOffset, cbLine, sizeof (unsigned char),
/* FIXME: We should check if this symbol is being stripped. */
- if (h->root.written)
+ if (h->written)
return true;
if (h->abfd == (bfd *) NULL)
h->esym.asym.value = 0;
h->esym.asym.st = stGlobal;
- if (h->root.type != bfd_link_hash_defined)
+ if (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak)
h->esym.asym.sc = scAbs;
else
{
case bfd_link_hash_new:
abort ();
case bfd_link_hash_undefined:
- case bfd_link_hash_weak:
+ case bfd_link_hash_undefweak:
if (h->esym.asym.sc != scUndefined
&& h->esym.asym.sc != scSUndefined)
h->esym.asym.sc = scUndefined;
break;
case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
if (h->esym.asym.sc == scUndefined
|| h->esym.asym.sc == scSUndefined)
h->esym.asym.sc = scAbs;
/* bfd_ecoff_debug_one_external uses iextMax to keep track of the
symbol number. */
h->indx = ecoff_data (output_bfd)->debug_info.symbolic_header.iextMax;
- h->root.written = true;
+ h->written = 1;
return (bfd_ecoff_debug_one_external
(output_bfd, &ecoff_data (output_bfd)->debug_info,
rel.address = link_order->offset;
rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
- if (rel.howto == (const reloc_howto_type *) NULL)
+ if (rel.howto == 0)
{
bfd_set_error (bfd_error_bad_value);
return false;