/* BFD back-end for MIPS Extended-Coff files.
- Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
- Written by Per Bothner.
- Symbol and line number support added by Ian Lance Taylor.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+ Original version by Per Bothner.
+ Full support added by Ian Lance Taylor, ian@cygnus.com.
This file is part of BFD, the Binary File Descriptor library.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
+#include "bfdlink.h"
#include "libbfd.h"
-#include "coff/mips.h"
#include "coff/internal.h"
#include "coff/sym.h"
#include "coff/symconst.h"
-#include "coff/ecoff-ext.h"
+#include "coff/ecoff.h"
+#include "coff/mips.h"
#include "libcoff.h"
-
-/* `Tdata' information kept for ECOFF files. */
-
-#define ecoff_data(abfd) ((abfd)->tdata.ecoff_obj_data)
-
-typedef struct ecoff_tdata
-{
- /* The symbol table file position. */
- file_ptr sym_filepos;
-
- /* The unswapped ECOFF symbolic information. */
- PTR raw_syments;
-
- /* The swapped ECOFF symbolic header. */
- HDRR symbolic_header;
-
- /* Pointers to the unswapped symbolic information. */
- unsigned char *line;
- struct dnr_ext *external_dnr;
- struct pdr_ext *external_pdr;
- struct sym_ext *external_sym;
- struct opt_ext *external_opt;
- union aux_ext *external_aux;
- char *ss;
- char *ssext;
- struct fdr_ext *external_fdr;
- struct rfd_ext *external_rfd;
- struct ext_ext *external_ext;
-
- /* The swapped fdr information. */
- FDR *fdr;
-
- /* The canonical BFD symbols. */
- struct ecoff_symbol_struct *canonical_symbols;
-
-} ecoff_data_type;
-
-/* Each canonical asymbol really looks like this. */
-
-typedef struct ecoff_symbol_struct
-{
- /* The actual symbol which the rest of BFD works with */
- asymbol symbol;
-
- /* The fdr for this symbol. */
- FDR *fdr;
-
- /* true if this is a local symbol rather than an external one. */
- boolean local;
-
- /* A pointer to the unswapped hidden information for this symbol */
- union
- {
- struct sym_ext *lnative;
- struct ext_ext *enative;
- }
- native;
-} ecoff_symbol_type;
-
-/* We take the address of the first element of a asymbol to ensure that the
- macro is only ever applied to an asymbol. */
-#define ecoffsymbol(asymbol) ((ecoff_symbol_type *) (&((asymbol)->the_bfd)))
-
-/* MIPS ECOFF has COFF sections, but the debugging information is
- stored in a completely different format. This files uses the some
- of the swapping routines from coffswap.h, and some of the generic
- COFF routines in coffgen.c, but, unlike the real COFF targets, does
- not use coffcode.h itself. */
-
-/* Get the generic COFF swapping routines, except for the symbol and
- lineno ones. Give them ecoff names. */
+#include "libecoff.h"
+\f
+/* Prototypes for static functions. */
+
+static bfd_boolean mips_ecoff_bad_format_hook
+ PARAMS ((bfd *abfd, PTR filehdr));
+static void mips_ecoff_swap_reloc_in
+ PARAMS ((bfd *, PTR, struct internal_reloc *));
+static void mips_ecoff_swap_reloc_out
+ PARAMS ((bfd *, const struct internal_reloc *, PTR));
+static void mips_adjust_reloc_in
+ PARAMS ((bfd *, const struct internal_reloc *, arelent *));
+static void mips_adjust_reloc_out
+ PARAMS ((bfd *, const arelent *, struct internal_reloc *));
+static bfd_reloc_status_type mips_generic_reloc
+ PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
+ asection *section, bfd *output_bfd, char **error));
+static bfd_reloc_status_type mips_refhi_reloc
+ PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
+ asection *section, bfd *output_bfd, char **error));
+static bfd_reloc_status_type mips_reflo_reloc
+ PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
+ asection *section, bfd *output_bfd, char **error));
+static bfd_reloc_status_type mips_gprel_reloc
+ PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
+ asection *section, bfd *output_bfd, char **error));
+static void mips_relocate_hi
+ PARAMS ((struct internal_reloc *refhi, struct internal_reloc *reflo,
+ bfd *input_bfd, asection *input_section, bfd_byte *contents,
+ bfd_vma relocation));
+static bfd_boolean mips_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR));
+static reloc_howto_type *mips_bfd_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+\f
+/* ECOFF has COFF sections, but the debugging information is stored in
+ a completely different format. ECOFF targets use some of the
+ swapping routines from coffswap.h, and some of the generic COFF
+ routines in coffgen.c, but, unlike the real COFF targets, do not
+ use coffcode.h itself.
+
+ Get the generic COFF swapping routines, except for the reloc,
+ symbol, and lineno ones. Give them ECOFF names. */
+#define MIPSECOFF
+#define NO_COFF_RELOCS
#define NO_COFF_SYMBOLS
#define NO_COFF_LINENOS
-#define coff_swap_reloc_in ecoff_swap_reloc_in
-#define coff_swap_reloc_out ecoff_swap_reloc_out
-#define coff_swap_filehdr_in ecoff_swap_filehdr_in
-#define coff_swap_filehdr_out ecoff_swap_filehdr_out
-#define coff_swap_aouthdr_in ecoff_swap_aouthdr_in
-#define coff_swap_aouthdr_out ecoff_swap_aouthdr_out
-#define coff_swap_scnhdr_in ecoff_swap_scnhdr_in
-#define coff_swap_scnhdr_out ecoff_swap_scnhdr_out
+#define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
+#define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
+#define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
+#define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
+#define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
+#define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
#include "coffswap.h"
+
+/* Get the ECOFF swapping routines. */
+#define ECOFF_32
+#include "ecoffswap.h"
\f
-/* This stuff is somewhat copied from coffcode.h. */
+/* How to process the various relocs types. */
-static asection bfd_debug_section = { "*DEBUG*" };
+static reloc_howto_type mips_howto_table[] =
+{
+ /* Reloc type 0 is ignored. The reloc reading code ensures that
+ this is a reference to the .abs section, which will cause
+ bfd_perform_relocation to do nothing. */
+ HOWTO (MIPS_R_IGNORE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "IGNORE", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 16 bit reference to a symbol, normally from a data section. */
+ HOWTO (MIPS_R_REFHALF, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ mips_generic_reloc, /* special_function */
+ "REFHALF", /* name */
+ TRUE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 32 bit reference to a symbol, normally from a data section. */
+ HOWTO (MIPS_R_REFWORD, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ mips_generic_reloc, /* special_function */
+ "REFWORD", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 26 bit absolute jump address. */
+ HOWTO (MIPS_R_JMPADDR, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ /* This needs complex overflow
+ detection, because the upper four
+ bits must match the PC. */
+ mips_generic_reloc, /* special_function */
+ "JMPADDR", /* name */
+ TRUE, /* partial_inplace */
+ 0x3ffffff, /* src_mask */
+ 0x3ffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The high 16 bits of a symbol value. Handled by the function
+ mips_refhi_reloc. */
+ HOWTO (MIPS_R_REFHI, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ mips_refhi_reloc, /* special_function */
+ "REFHI", /* name */
+ TRUE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The low 16 bits of a symbol value. */
+ HOWTO (MIPS_R_REFLO, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ mips_reflo_reloc, /* special_function */
+ "REFLO", /* name */
+ TRUE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A reference to an offset from the gp register. Handled by the
+ function mips_gprel_reloc. */
+ HOWTO (MIPS_R_GPREL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips_gprel_reloc, /* special_function */
+ "GPREL", /* name */
+ TRUE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A reference to a literal using an offset from the gp register.
+ Handled by the function mips_gprel_reloc. */
+ HOWTO (MIPS_R_LITERAL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips_gprel_reloc, /* special_function */
+ "LITERAL", /* name */
+ TRUE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ EMPTY_HOWTO (8),
+ EMPTY_HOWTO (9),
+ EMPTY_HOWTO (10),
+ EMPTY_HOWTO (11),
+
+ /* FIXME: This relocation is used (internally only) to represent branches
+ when assembling. It should never appear in output files, and
+ be removed. (It used to be used for embedded-PIC support.) */
+ HOWTO (MIPS_R_PCREL16, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips_generic_reloc, /* special_function */
+ "PCREL16", /* name */
+ TRUE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+};
+#define MIPS_HOWTO_COUNT \
+ (sizeof mips_howto_table / sizeof mips_howto_table[0])
+\f
/* See whether the magic number matches. */
-static boolean
-DEFUN(ecoff_bad_format_hook, (abfd, filehdr),
- bfd *abfd AND
- PTR filehdr)
+static bfd_boolean
+mips_ecoff_bad_format_hook (abfd, filehdr)
+ bfd *abfd;
+ PTR filehdr;
{
struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
- if (ECOFFBADMAG (*internal_f))
- return false;
+ switch (internal_f->f_magic)
+ {
+ case MIPS_MAGIC_1:
+ /* I don't know what endianness this implies. */
+ return TRUE;
- return true;
-}
+ case MIPS_MAGIC_BIG:
+ case MIPS_MAGIC_BIG2:
+ case MIPS_MAGIC_BIG3:
+ return bfd_big_endian (abfd);
-/* This is a hook needed by SCO COFF, but we have nothing to do. */
+ case MIPS_MAGIC_LITTLE:
+ case MIPS_MAGIC_LITTLE2:
+ case MIPS_MAGIC_LITTLE3:
+ return bfd_little_endian (abfd);
-static asection *
-DEFUN (ecoff_make_section_hook, (abfd, name),
- bfd *abfd AND
- char *name)
-{
- return (asection *) NULL;
+ default:
+ return FALSE;
+ }
}
+\f
+/* Reloc handling. MIPS ECOFF relocs are packed into 8 bytes in
+ external form. They use a bit which indicates whether the symbol
+ is external. */
-/* Initialize a new section. */
+/* Swap a reloc in. */
-static boolean
-DEFUN (ecoff_new_section_hook, (abfd, section),
- bfd *abfd AND
- asection *section)
+static void
+mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
+ bfd *abfd;
+ PTR ext_ptr;
+ struct internal_reloc *intern;
{
- section->alignment_power = abfd->xvec->align_power_min;
- return true;
-}
-
-#define ecoff_set_alignment_hook \
- ((void (*) PARAMS ((bfd *, asection *, PTR))) bfd_void)
+ const RELOC *ext = (RELOC *) ext_ptr;
-static boolean
-DEFUN (ecoff_mkobject, (abfd),
- bfd *abfd)
-{
- abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *)
- bfd_zalloc (abfd, sizeof(ecoff_data_type)));
- if (abfd->tdata.ecoff_obj_data == NULL)
+ intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr);
+ if (bfd_header_big_endian (abfd))
{
- bfd_error = no_memory;
- return false;
+ intern->r_symndx = (((int) ext->r_bits[0]
+ << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
+ | ((int) ext->r_bits[1]
+ << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
+ | ((int) ext->r_bits[2]
+ << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
+ intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
+ >> RELOC_BITS3_TYPE_SH_BIG);
+ intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
+ }
+ else
+ {
+ intern->r_symndx = (((int) ext->r_bits[0]
+ << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
+ | ((int) ext->r_bits[1]
+ << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
+ | ((int) ext->r_bits[2]
+ << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
+ intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
+ >> RELOC_BITS3_TYPE_SH_LITTLE)
+ | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
+ << RELOC_BITS3_TYPEHI_SH_LITTLE));
+ intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
}
-
- return true;
}
-/* Create the COFF backend specific information. */
+/* Swap a reloc out. */
-static PTR
-DEFUN(ecoff_mkobject_hook,(abfd, filehdr),
- bfd *abfd AND
- PTR filehdr)
-{
- struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
- ecoff_data_type *ecoff;
-
- if (ecoff_mkobject (abfd) == false)
- return NULL;
-
- ecoff = ecoff_data (abfd);
- ecoff->sym_filepos = internal_f->f_symptr;
- return (PTR) ecoff;
-}
-
-/* Determine the machine architecture and type. */
-static boolean
-DEFUN (ecoff_set_arch_mach_hook, (abfd, filehdr),
- bfd *abfd AND
- PTR filehdr)
+static void
+mips_ecoff_swap_reloc_out (abfd, intern, dst)
+ bfd *abfd;
+ const struct internal_reloc *intern;
+ PTR dst;
{
- long machine;
- enum bfd_architecture arch;
- struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+ RELOC *ext = (RELOC *) dst;
+ long r_symndx;
- machine = 0;
- switch (internal_f->f_magic) {
- case MIPS_MAGIC_1:
- case MIPS_MAGIC_2:
- case MIPS_MAGIC_3:
- arch = bfd_arch_mips;
- machine = 0;
- break;
-
- default: /* Unreadable input file type */
- arch = bfd_arch_obscure;
- break;
- }
-
- bfd_default_set_arch_mach(abfd, arch, machine);
- return true;
-}
+ BFD_ASSERT (intern->r_extern
+ || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
-/* Get the BFD flags to use for a section. */
+ r_symndx = intern->r_symndx;
-static flagword
-DEFUN(styp_to_sec_flags, (abfd, hdr),
- bfd *abfd AND
- PTR hdr)
-{
- struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
- long styp_flags = internal_s->s_flags;
- flagword sec_flags=0;
-
- if (styp_flags & STYP_NOLOAD)
- sec_flags |= SEC_NEVER_LOAD;
-
- /* For 386 COFF, at least, an unloadable text or data section is
- actually a shared library section. */
- if (styp_flags & STYP_TEXT)
+ H_PUT_32 (abfd, intern->r_vaddr, ext->r_vaddr);
+ if (bfd_header_big_endian (abfd))
{
- if (sec_flags & SEC_NEVER_LOAD)
- sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY;
- else
- sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
- }
- else if ((styp_flags & STYP_DATA)
- || (styp_flags & STYP_RDATA)
- || (styp_flags & STYP_SDATA))
- {
- if (sec_flags & SEC_NEVER_LOAD)
- sec_flags |= SEC_DATA | SEC_SHARED_LIBRARY;
- else
- sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
- if (styp_flags & STYP_RDATA)
- sec_flags |= SEC_READONLY;
- }
- else if ((styp_flags & STYP_BSS)
- || (styp_flags & STYP_SBSS))
- {
- sec_flags |= SEC_ALLOC;
- }
- else if (styp_flags & STYP_INFO)
- {
- sec_flags |= SEC_NEVER_LOAD;
- }
- else if ((styp_flags & STYP_LIT8)
- || (styp_flags & STYP_LIT4))
- {
- sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
+ ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
+ ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
+ ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
+ ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
+ & RELOC_BITS3_TYPE_BIG)
+ | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
}
else
{
- sec_flags |= SEC_ALLOC | SEC_LOAD;
+ ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
+ ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
+ ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
+ ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
+ & RELOC_BITS3_TYPE_LITTLE)
+ | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
+ & RELOC_BITS3_TYPEHI_LITTLE))
+ | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
}
-
- return sec_flags;
}
-\f
-/* ECOFF symbol table routines. The ECOFF symbol table is described
- in gcc/mips-tfile.c. */
-/* Create an empty symbol. */
+/* Finish canonicalizing a reloc. Part of this is generic to all
+ ECOFF targets, and that part is in ecoff.c. The rest is done in
+ this backend routine. It must fill in the howto field. */
-static asymbol *
-DEFUN (ecoff_make_empty_symbol, (abfd),
- bfd *abfd)
+static void
+mips_adjust_reloc_in (abfd, intern, rptr)
+ bfd *abfd;
+ const struct internal_reloc *intern;
+ arelent *rptr;
{
- ecoff_symbol_type *new;
+ if (intern->r_type > MIPS_R_PCREL16)
+ abort ();
- new = (ecoff_symbol_type *) bfd_alloc (abfd, sizeof (ecoff_symbol_type));
- if (new == (ecoff_symbol_type *) NULL)
- {
- bfd_error = no_memory;
- return (asymbol *) NULL;
- }
- new->symbol.section = (asection *) NULL;
- new->fdr = (FDR *) NULL;
- new->local = false;
- new->native.lnative = (struct sym_ext *) NULL;
- new->symbol.the_bfd = abfd;
- return &new->symbol;
+ if (! intern->r_extern
+ && (intern->r_type == MIPS_R_GPREL
+ || intern->r_type == MIPS_R_LITERAL))
+ rptr->addend += ecoff_data (abfd)->gp;
+
+ /* If the type is MIPS_R_IGNORE, make sure this is a reference to
+ the absolute section so that the reloc is ignored. */
+ if (intern->r_type == MIPS_R_IGNORE)
+ rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+
+ rptr->howto = &mips_howto_table[intern->r_type];
}
-/* Set the BFD flags and section for an ECOFF symbol. */
+/* Make any adjustments needed to a reloc before writing it out. None
+ are needed for MIPS. */
static void
-DEFUN (ecoff_set_symbol_info, (abfd, ecoff_sym, asym, ext),
- bfd *abfd AND
- SYMR *ecoff_sym AND
- asymbol *asym AND
- int ext)
+mips_adjust_reloc_out (abfd, rel, intern)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ const arelent *rel ATTRIBUTE_UNUSED;
+ struct internal_reloc *intern ATTRIBUTE_UNUSED;
{
- asym->the_bfd = abfd;
- asym->value = ecoff_sym->value;
- asym->section = &bfd_debug_section;
- asym->udata = NULL;
- if (ext)
- asym->flags = BSF_EXPORT | BSF_GLOBAL;
- else
- asym->flags = BSF_LOCAL;
- switch (ecoff_sym->sc)
- {
- case scNil:
- asym->flags = 0;
- break;
- case scText:
- 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->value -= asym->section->vma;
- break;
- case scBss:
- asym->section = &bfd_com_section;
- asym->flags = 0;
- break;
- case scRegister:
- asym->flags = BSF_DEBUGGING;
- break;
- case scAbs:
- asym->section = &bfd_abs_section;
- asym->flags = 0;
- break;
- case scUndefined:
- asym->section = &bfd_und_section;
- asym->flags = 0;
- break;
- case scCdbLocal:
- case scBits:
- case scCdbSystem:
- case scRegImage:
- case scInfo:
- case scUserStruct:
- asym->flags = BSF_DEBUGGING;
- break;
- case scSData:
- asym->section = bfd_make_section_old_way (abfd, ".sdata");
- asym->value -= asym->section->vma;
- break;
- case scSBss:
- asym->section = &bfd_com_section;
- asym->flags = 0;
- break;
- case scRData:
- asym->section = bfd_make_section_old_way (abfd, ".rdata");
- asym->value -= asym->section->vma;
- break;
- case scVar:
- asym->flags = BSF_DEBUGGING;
- break;
- case scCommon:
- case scSCommon:
- asym->section = &bfd_com_section;
- asym->flags = 0;
- break;
- case scVarRegister:
- case scVariant:
- asym->flags = BSF_DEBUGGING;
- break;
- case scSUndefined:
- asym->section = &bfd_und_section;
- asym->flags = 0;
- break;
- case scInit:
- asym->section = bfd_make_section_old_way (abfd, ".init");
- asym->value -= asym->section->vma;
- break;
- case scBasedVar:
- case scXData:
- case scPData:
- asym->flags = BSF_DEBUGGING;
- break;
- case scFini:
- asym->section = bfd_make_section_old_way (abfd, ".fini");
- asym->value -= asym->section->vma;
- break;
- default:
- asym->flags = 0;
- break;
- }
}
-/* Read an ECOFF symbol table. */
-
-static boolean
-DEFUN (ecoff_slurp_symbol_table, (abfd),
- bfd *abfd)
+/* ECOFF relocs are either against external symbols, or against
+ sections. If we are producing relocatable output, and the reloc
+ is against an external symbol, and nothing has given us any
+ additional addend, the resulting reloc will also be against the
+ same symbol. In such a case, we don't want to change anything
+ about the way the reloc is handled, since it will all be done at
+ final link time. Rather than put special case code into
+ bfd_perform_relocation, all the reloc types use this howto
+ function. It just short circuits the reloc if producing
+ relocatable output against an external symbol. */
+
+static bfd_reloc_status_type
+mips_generic_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data ATTRIBUTE_UNUSED;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message ATTRIBUTE_UNUSED;
{
- struct hdr_ext external_symhdr;
- HDRR *internal_symhdr;
- bfd_size_type raw_base;
- bfd_size_type raw_size;
- PTR raw;
- bfd_size_type internal_size;
- struct fdr_ext *fraw_src;
- struct fdr_ext *fraw_end;
- struct fdr *fdr_ptr;
- struct fdr *fdr_end;
- ecoff_symbol_type *internal;
- ecoff_symbol_type *internal_ptr;
- struct ext_ext *eraw_src;
- struct ext_ext *eraw_end;
-
- /* If we've already read in the symbol table, do nothing. */
- if (ecoff_data (abfd)->canonical_symbols != NULL)
- return true;
-
- /* At this point bfd_get_symcount (abfd) holds the number of symbols
- as read from the file header, but on ECOFF this is always the
- size of the symbolic information header. It would be cleaner to
- handle this when we first read the file in coffgen.c. */
- if (bfd_get_symcount (abfd) != sizeof (external_symhdr))
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
{
- bfd_error = bad_value;
- return false;
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
}
- /* Read the symbolic information header. */
- if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1
- || (bfd_read ((PTR) &external_symhdr, sizeof (external_symhdr), 1, abfd)
- != sizeof (external_symhdr)))
- {
- bfd_error = system_call_error;
- return false;
- }
- internal_symhdr = &ecoff_data (abfd)->symbolic_header;
- ecoff_swap_hdr_in (abfd, &external_symhdr, internal_symhdr);
+ return bfd_reloc_continue;
+}
- if (internal_symhdr->magic != magicSym)
- {
- bfd_error = bad_value;
- return false;
- }
+/* Do a REFHI relocation. This has to be done in combination with a
+ REFLO reloc, because there is a carry from the REFLO to the REFHI.
+ Here we just save the information we need; we do the actual
+ relocation when we see the REFLO. MIPS ECOFF requires that the
+ REFLO immediately follow the REFHI. As a GNU extension, we permit
+ an arbitrary number of HI relocs to be associated with a single LO
+ reloc. This extension permits gcc to output the HI and LO relocs
+ itself. */
- /* Now we can get the correct number of symbols. */
- bfd_get_symcount (abfd) = (internal_symhdr->isymMax
- + internal_symhdr->iextMax);
-
- /* Read the entire symbol table at once. This expression assumes
- that the external symbols are always the last item. */
- raw_base = ecoff_data (abfd)->sym_filepos + sizeof (external_symhdr);
- raw_size = (internal_symhdr->cbExtOffset - raw_base
- + internal_symhdr->iextMax * sizeof (struct ext_ext));
- raw = (PTR) bfd_alloc (abfd, raw_size);
- if (raw == NULL)
- {
- bfd_error = no_memory;
- return false;
- }
- if (bfd_read (raw, raw_size, 1, abfd) != raw_size)
- {
- bfd_error = system_call_error;
- bfd_release (abfd, raw);
- return false;
- }
+struct mips_hi
+{
+ struct mips_hi *next;
+ bfd_byte *addr;
+ bfd_vma addend;
+};
- 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) \
- ecoff_data (abfd)->off2 = (type *) NULL; \
- else \
- ecoff_data (abfd)->off2 = (type *) ((char *) raw \
- + internal_symhdr->off1 \
- - raw_base)
- FIX (cbLineOffset, line, unsigned char);
- FIX (cbDnOffset, external_dnr, struct dnr_ext);
- FIX (cbPdOffset, external_pdr, struct pdr_ext);
- FIX (cbSymOffset, external_sym, struct sym_ext);
- FIX (cbOptOffset, external_opt, struct opt_ext);
- FIX (cbAuxOffset, external_aux, union aux_ext);
- FIX (cbSsOffset, ss, char);
- FIX (cbSsExtOffset, ssext, char);
- FIX (cbFdOffset, external_fdr, struct fdr_ext);
- FIX (cbRfdOffset, external_rfd, struct rfd_ext);
- FIX (cbExtOffset, external_ext, struct ext_ext);
-#undef FIX
-
- /* I don't want to always swap all the data, because it will just
- waste time and most programs will never look at this data. The
- only time the linker needs most of the debugging information
- swapped is when linking big-endian and little-endian MIPS object
- files together, which is not a common occurrence.
-
- We need to look at the fdr to deal with a lot of information in
- the symbols, so we swap them here. We also canonicalize the
- symbols. */
- ecoff_data (abfd)->fdr = (struct fdr *) bfd_alloc (abfd,
- (internal_symhdr->ifdMax *
- sizeof (struct fdr)));
- if (ecoff_data (abfd)->fdr == NULL)
- {
- bfd_error = no_memory;
- return false;
- }
- fdr_ptr = ecoff_data (abfd)->fdr;
- fraw_src = ecoff_data (abfd)->external_fdr;
- fraw_end = fraw_src + internal_symhdr->ifdMax;
- for (; fraw_src < fraw_end; fraw_src++, fdr_ptr++)
- ecoff_swap_fdr_in (abfd, fraw_src, fdr_ptr);
-
- internal_size = bfd_get_symcount (abfd) * sizeof (ecoff_symbol_type);
- internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size);
- if (internal == NULL)
+/* FIXME: This should not be a static variable. */
+
+static struct mips_hi *mips_refhi_list;
+
+static bfd_reloc_status_type
+mips_refhi_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message ATTRIBUTE_UNUSED;
+{
+ bfd_reloc_status_type ret;
+ bfd_vma relocation;
+ struct mips_hi *n;
+
+ /* If we're relocating, and this an external symbol, we don't want
+ to change anything. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
{
- bfd_error = no_memory;
- return false;
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
}
- internal_ptr = internal;
- eraw_src = ecoff_data (abfd)->external_ext;
- eraw_end = eraw_src + internal_symhdr->iextMax;
- for (; eraw_src < eraw_end; eraw_src++, internal_ptr++)
- {
- EXTR internal_esym;
-
- ecoff_swap_ext_in (abfd, eraw_src, &internal_esym);
- internal_ptr->symbol.name = (ecoff_data (abfd)->ssext
- + internal_esym.asym.iss);
- ecoff_set_symbol_info (abfd, &internal_esym.asym,
- &internal_ptr->symbol, 1);
- internal_ptr->fdr = ecoff_data (abfd)->fdr + internal_esym.ifd;
- internal_ptr->local = false;
- internal_ptr->native.enative = eraw_src;
- }
+ ret = bfd_reloc_ok;
+ if (bfd_is_und_section (symbol->section)
+ && output_bfd == (bfd *) NULL)
+ ret = bfd_reloc_undefined;
- /* The local symbols must be accessed via the fdr's, because the
- string and aux indices are relative to the fdr information. */
- fdr_ptr = ecoff_data (abfd)->fdr;
- fdr_end = fdr_ptr + internal_symhdr->ifdMax;
- for (; fdr_ptr < fdr_end; fdr_ptr++)
- {
- struct sym_ext *lraw_src;
- struct sym_ext *lraw_end;
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
- lraw_src = ecoff_data (abfd)->external_sym + fdr_ptr->isymBase;
- lraw_end = lraw_src + fdr_ptr->csym;
- for (; lraw_src < lraw_end; lraw_src++, internal_ptr++)
- {
- SYMR internal_sym;
-
- ecoff_swap_sym_in (abfd, lraw_src, &internal_sym);
- internal_ptr->symbol.name = (ecoff_data (abfd)->ss
- + fdr_ptr->issBase
- + internal_sym.iss);
- ecoff_set_symbol_info (abfd, &internal_sym,
- &internal_ptr->symbol, 0);
- internal_ptr->fdr = fdr_ptr;
- internal_ptr->local = true;
- internal_ptr->native.lnative = lraw_src;
- }
- }
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
- ecoff_data (abfd)->canonical_symbols = internal;
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ return bfd_reloc_outofrange;
- return true;
-}
+ /* Save the information, and let REFLO do the actual relocation. */
+ n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
+ if (n == NULL)
+ return bfd_reloc_outofrange;
+ n->addr = (bfd_byte *) data + reloc_entry->address;
+ n->addend = relocation;
+ n->next = mips_refhi_list;
+ mips_refhi_list = n;
-static unsigned int
-DEFUN (ecoff_get_symtab_upper_bound, (abfd),
- bfd *abfd)
-{
- if (! ecoff_slurp_symbol_table (abfd))
- return 0;
+ if (output_bfd != (bfd *) NULL)
+ reloc_entry->address += input_section->output_offset;
- return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *));
+ return ret;
}
-static unsigned int
-DEFUN (ecoff_get_symtab, (abfd, alocation),
- bfd *abfd AND
- asymbol **alocation)
+/* Do a REFLO relocation. This is a straightforward 16 bit inplace
+ relocation; this function exists in order to do the REFHI
+ relocation described above. */
+
+static bfd_reloc_status_type
+mips_reflo_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
{
- unsigned int counter = 0;
- ecoff_symbol_type *symbase;
- ecoff_symbol_type **location = (ecoff_symbol_type **) alocation;
-
- if (! ecoff_slurp_symbol_table (abfd))
- return 0;
-
- symbase = ecoff_data (abfd)->canonical_symbols;
- while (counter < bfd_get_symcount (abfd))
+ if (mips_refhi_list != NULL)
{
- *(location++) = symbase++;
- counter++;
- }
- *location++ = (ecoff_symbol_type *) NULL;
- return bfd_get_symcount (abfd);
-}
-
-/* Turn ECOFF type information into a printable string.
- emit_aggregate and type_to_string are from gcc/mips-tdump.c, with
- swapping added and used_ptr removed. */
-
-/* Write aggregate information to a string. */
+ struct mips_hi *l;
-static void
-DEFUN (emit_aggregate, (abfd, string, rndx, isym, which),
- bfd *abfd AND
- char *string AND
- RNDXR *rndx AND
- long isym AND
- CONST char *which)
-{
- int ifd = rndx->rfd;
- int indx = rndx->index;
- int sym_base, ss_base;
- CONST char *name;
-
- if (ifd == 0xfff)
- ifd = isym;
-
- sym_base = ecoff_data (abfd)->fdr[ifd].isymBase;
- ss_base = ecoff_data (abfd)->fdr[ifd].issBase;
-
- if (indx == indexNil)
- name = "/* no name */";
- else
- {
- SYMR sym;
+ l = mips_refhi_list;
+ while (l != NULL)
+ {
+ unsigned long insn;
+ unsigned long val;
+ unsigned long vallo;
+ struct mips_hi *next;
+
+ /* Do the REFHI relocation. Note that we actually don't
+ need to know anything about the REFLO itself, except
+ where to find the low 16 bits of the addend needed by the
+ REFHI. */
+ insn = bfd_get_32 (abfd, l->addr);
+ vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
+ & 0xffff);
+ val = ((insn & 0xffff) << 16) + vallo;
+ val += l->addend;
+
+ /* The low order 16 bits are always treated as a signed
+ value. Therefore, a negative value in the low order bits
+ requires an adjustment in the high order bits. We need
+ to make this adjustment in two ways: once for the bits we
+ took from the data, and once for the bits we are putting
+ back in to the data. */
+ if ((vallo & 0x8000) != 0)
+ val -= 0x10000;
+ if ((val & 0x8000) != 0)
+ val += 0x10000;
+
+ insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
+ bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
+
+ next = l->next;
+ free (l);
+ l = next;
+ }
- indx += sym_base;
- ecoff_swap_sym_in (abfd,
- ecoff_data (abfd)->external_sym + indx,
- &sym);
- name = ecoff_data (abfd)->ss + ss_base + sym.iss;
+ mips_refhi_list = NULL;
}
- sprintf (string,
- "%s %s { ifd = %d, index = %d }",
- which, name, ifd,
- indx + ecoff_data (abfd)->symbolic_header.iextMax);
+ /* Now do the REFLO reloc in the usual way. */
+ return mips_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message);
}
-/* Convert the type information to string format. */
-
-static char *
-DEFUN (type_to_string, (abfd, aux_ptr, indx, bigendian),
- bfd *abfd AND
- union aux_ext *aux_ptr AND
- int indx AND
- int bigendian)
+/* Do a GPREL relocation. This is a 16 bit value which must become
+ the offset from the gp register. */
+
+static bfd_reloc_status_type
+mips_gprel_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
{
- AUXU u;
- struct qual {
- unsigned int type;
- int low_bound;
- int high_bound;
- int stride;
- } qualifiers[7];
-
- unsigned int basic_type;
- int i;
- static char buffer1[1024];
- static char buffer2[1024];
- char *p1 = buffer1;
- char *p2 = buffer2;
- RNDXR rndx;
-
- for (i = 0; i < 7; i++)
+ bfd_boolean relocatable;
+ bfd_vma gp;
+ bfd_vma relocation;
+ unsigned long val;
+ unsigned long insn;
+
+ /* If we're relocating, and this is an external symbol with no
+ addend, we don't want to change anything. We will only have an
+ addend if this is a newly created reloc, not read from an ECOFF
+ file. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
{
- qualifiers[i].low_bound = 0;
- qualifiers[i].high_bound = 0;
- qualifiers[i].stride = 0;
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
}
- 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);
-
- basic_type = u.ti.bt;
- qualifiers[0].type = u.ti.tq0;
- qualifiers[1].type = u.ti.tq1;
- qualifiers[2].type = u.ti.tq2;
- qualifiers[3].type = u.ti.tq3;
- qualifiers[4].type = u.ti.tq4;
- qualifiers[5].type = u.ti.tq5;
- qualifiers[6].type = tqNil;
-
- /*
- * Go get the basic type.
- */
- switch (basic_type)
+ if (output_bfd != (bfd *) NULL)
+ relocatable = TRUE;
+ else
{
- case btNil: /* undefined */
- strcpy (p1, "nil");
- break;
-
- case btAdr: /* address - integer same size as pointer */
- strcpy (p1, "address");
- break;
+ relocatable = FALSE;
+ output_bfd = symbol->section->output_section->owner;
+ }
- case btChar: /* character */
- strcpy (p1, "char");
- break;
+ if (bfd_is_und_section (symbol->section) && ! relocatable)
+ return bfd_reloc_undefined;
+
+ /* We have to figure out the gp value, so that we can adjust the
+ symbol value correctly. We look up the symbol _gp in the output
+ BFD. If we can't find it, we're stuck. We cache it in the ECOFF
+ target data. We don't need to adjust the symbol value for an
+ external symbol if we are producing relocatable output. */
+ gp = _bfd_get_gp_value (output_bfd);
+ if (gp == 0
+ && (! relocatable
+ || (symbol->flags & BSF_SECTION_SYM) != 0))
+ {
+ if (relocatable)
+ {
+ /* Make up a value. */
+ gp = symbol->section->output_section->vma + 0x4000;
+ _bfd_set_gp_value (output_bfd, gp);
+ }
+ else
+ {
+ unsigned int count;
+ asymbol **sym;
+ unsigned int i;
- case btUChar: /* unsigned character */
- strcpy (p1, "unsigned char");
- break;
+ count = bfd_get_symcount (output_bfd);
+ sym = bfd_get_outsymbols (output_bfd);
- case btShort: /* short */
- strcpy (p1, "short");
- break;
+ if (sym == (asymbol **) NULL)
+ i = count;
+ else
+ {
+ for (i = 0; i < count; i++, sym++)
+ {
+ register const char *name;
+
+ name = bfd_asymbol_name (*sym);
+ if (*name == '_' && strcmp (name, "_gp") == 0)
+ {
+ gp = bfd_asymbol_value (*sym);
+ _bfd_set_gp_value (output_bfd, gp);
+ break;
+ }
+ }
+ }
- case btUShort: /* unsigned short */
- strcpy (p1, "unsigned short");
- break;
+ if (i >= count)
+ {
+ /* Only get the error once. */
+ gp = 4;
+ _bfd_set_gp_value (output_bfd, gp);
+ *error_message =
+ (char *) _("GP relative relocation when _gp not defined");
+ return bfd_reloc_dangerous;
+ }
+ }
+ }
- case btInt: /* int */
- strcpy (p1, "int");
- break;
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
- case btUInt: /* unsigned int */
- strcpy (p1, "unsigned int");
- break;
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
- case btLong: /* long */
- strcpy (p1, "long");
- break;
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ return bfd_reloc_outofrange;
- case btULong: /* unsigned long */
- strcpy (p1, "unsigned long");
- break;
+ insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
- case btFloat: /* float (real) */
- strcpy (p1, "float");
- break;
+ /* Set val to the offset into the section or symbol. */
+ val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
+ if (val & 0x8000)
+ val -= 0x10000;
- case btDouble: /* Double (real) */
- strcpy (p1, "double");
- break;
+ /* Adjust val for the final section location and GP value. If we
+ are producing relocatable output, we don't want to do this for
+ an external symbol. */
+ if (! relocatable
+ || (symbol->flags & BSF_SECTION_SYM) != 0)
+ val += relocation - gp;
- /* Structures add 1-2 aux words:
- 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
- 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
+ insn = (insn &~ (unsigned) 0xffff) | (val & 0xffff);
+ bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + reloc_entry->address);
- case btStruct: /* Structure (Record) */
- ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- emit_aggregate (abfd, p1, &rndx,
- AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
- "struct");
- indx++; /* skip aux words */
- break;
+ if (relocatable)
+ reloc_entry->address += input_section->output_offset;
- /* Unions add 1-2 aux words:
- 1st word is [ST_RFDESCAPE, offset] pointer to union def;
- 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
+ /* Make sure it fit in 16 bits. */
+ if ((long) val >= 0x8000 || (long) val < -0x8000)
+ return bfd_reloc_overflow;
- case btUnion: /* Union */
- ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- emit_aggregate (abfd, p1, &rndx,
- AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
- "union");
- indx++; /* skip aux words */
- break;
+ return bfd_reloc_ok;
+}
- /* Enumerations add 1-2 aux words:
- 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
- 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
+/* Get the howto structure for a generic reloc type. */
- case btEnum: /* Enumeration */
- ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
- emit_aggregate (abfd, p1, &rndx,
- AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
- "enum");
- indx++; /* skip aux words */
- break;
+static reloc_howto_type *
+mips_bfd_reloc_type_lookup (abfd, code)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ bfd_reloc_code_real_type code;
+{
+ int mips_type;
- case btTypedef: /* defined via a typedef, isymRef points */
- strcpy (p1, "typedef");
+ switch (code)
+ {
+ case BFD_RELOC_16:
+ mips_type = MIPS_R_REFHALF;
break;
-
- case btRange: /* subrange of int */
- strcpy (p1, "subrange");
+ case BFD_RELOC_32:
+ case BFD_RELOC_CTOR:
+ mips_type = MIPS_R_REFWORD;
break;
-
- case btSet: /* pascal sets */
- strcpy (p1, "set");
+ case BFD_RELOC_MIPS_JMP:
+ mips_type = MIPS_R_JMPADDR;
break;
-
- case btComplex: /* fortran complex */
- strcpy (p1, "complex");
+ case BFD_RELOC_HI16_S:
+ mips_type = MIPS_R_REFHI;
break;
-
- case btDComplex: /* fortran double complex */
- strcpy (p1, "double complex");
+ case BFD_RELOC_LO16:
+ mips_type = MIPS_R_REFLO;
break;
-
- case btIndirect: /* forward or unnamed typedef */
- strcpy (p1, "forward/unamed typedef");
+ case BFD_RELOC_GPREL16:
+ mips_type = MIPS_R_GPREL;
break;
-
- case btFixedDec: /* Fixed Decimal */
- strcpy (p1, "fixed decimal");
+ case BFD_RELOC_MIPS_LITERAL:
+ mips_type = MIPS_R_LITERAL;
break;
-
- case btFloatDec: /* Float Decimal */
- strcpy (p1, "float decimal");
+ case BFD_RELOC_16_PCREL_S2:
+ mips_type = MIPS_R_PCREL16;
break;
+ default:
+ return (reloc_howto_type *) NULL;
+ }
- case btString: /* Varying Length Character String */
- strcpy (p1, "string");
- break;
+ return &mips_howto_table[mips_type];
+}
+\f
+/* A helper routine for mips_relocate_section which handles the REFHI
+ relocations. The REFHI relocation must be followed by a REFLO
+ relocation, and the addend used is formed from the addends of both
+ instructions. */
- case btBit: /* Aligned Bit String */
- strcpy (p1, "bit");
- break;
+static void
+mips_relocate_hi (refhi, reflo, input_bfd, input_section, contents,
+ relocation)
+ struct internal_reloc *refhi;
+ struct internal_reloc *reflo;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ bfd_vma relocation;
+{
+ unsigned long insn;
+ unsigned long val;
+ unsigned long vallo;
- case btPicture: /* Picture */
- strcpy (p1, "picture");
- break;
+ if (refhi == NULL)
+ return;
- case btVoid: /* Void */
- strcpy (p1, "void");
- break;
+ insn = bfd_get_32 (input_bfd,
+ contents + refhi->r_vaddr - input_section->vma);
+ if (reflo == NULL)
+ vallo = 0;
+ else
+ vallo = (bfd_get_32 (input_bfd,
+ contents + reflo->r_vaddr - input_section->vma)
+ & 0xffff);
+
+ val = ((insn & 0xffff) << 16) + vallo;
+ val += relocation;
+
+ /* The low order 16 bits are always treated as a signed value.
+ Therefore, a negative value in the low order bits requires an
+ adjustment in the high order bits. We need to make this
+ adjustment in two ways: once for the bits we took from the data,
+ and once for the bits we are putting back in to the data. */
+ if ((vallo & 0x8000) != 0)
+ val -= 0x10000;
+
+ if ((val & 0x8000) != 0)
+ val += 0x10000;
+
+ insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
+ bfd_put_32 (input_bfd, (bfd_vma) insn,
+ contents + refhi->r_vaddr - input_section->vma);
+}
- default:
- sprintf (p1, "Unknown basic type %d", (int) basic_type);
- break;
+/* Relocate a section while linking a MIPS ECOFF file. */
+
+static bfd_boolean
+mips_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, external_relocs)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ PTR external_relocs;
+{
+ asection **symndx_to_section;
+ struct ecoff_link_hash_entry **sym_hashes;
+ bfd_vma gp;
+ bfd_boolean gp_undefined;
+ struct external_reloc *ext_rel;
+ struct external_reloc *ext_rel_end;
+ unsigned int i;
+ bfd_boolean got_lo;
+ struct internal_reloc lo_int_rel;
+ bfd_size_type amt;
+
+ BFD_ASSERT (input_bfd->xvec->byteorder
+ == output_bfd->xvec->byteorder);
+
+ /* We keep a table mapping the symndx found in an internal reloc to
+ the appropriate section. This is faster than looking up the
+ section by name each time. */
+ symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
+ if (symndx_to_section == (asection **) NULL)
+ {
+ amt = NUM_RELOC_SECTIONS * sizeof (asection *);
+ symndx_to_section = (asection **) bfd_alloc (input_bfd, amt);
+ if (!symndx_to_section)
+ return FALSE;
+
+ symndx_to_section[RELOC_SECTION_NONE] = NULL;
+ symndx_to_section[RELOC_SECTION_TEXT] =
+ bfd_get_section_by_name (input_bfd, ".text");
+ symndx_to_section[RELOC_SECTION_RDATA] =
+ bfd_get_section_by_name (input_bfd, ".rdata");
+ symndx_to_section[RELOC_SECTION_DATA] =
+ bfd_get_section_by_name (input_bfd, ".data");
+ symndx_to_section[RELOC_SECTION_SDATA] =
+ bfd_get_section_by_name (input_bfd, ".sdata");
+ symndx_to_section[RELOC_SECTION_SBSS] =
+ bfd_get_section_by_name (input_bfd, ".sbss");
+ symndx_to_section[RELOC_SECTION_BSS] =
+ bfd_get_section_by_name (input_bfd, ".bss");
+ symndx_to_section[RELOC_SECTION_INIT] =
+ bfd_get_section_by_name (input_bfd, ".init");
+ symndx_to_section[RELOC_SECTION_LIT8] =
+ bfd_get_section_by_name (input_bfd, ".lit8");
+ symndx_to_section[RELOC_SECTION_LIT4] =
+ bfd_get_section_by_name (input_bfd, ".lit4");
+ symndx_to_section[RELOC_SECTION_XDATA] = NULL;
+ symndx_to_section[RELOC_SECTION_PDATA] = NULL;
+ symndx_to_section[RELOC_SECTION_FINI] =
+ bfd_get_section_by_name (input_bfd, ".fini");
+ symndx_to_section[RELOC_SECTION_LITA] = NULL;
+ symndx_to_section[RELOC_SECTION_ABS] = NULL;
+
+ ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
}
- p1 += strlen (buffer1);
+ sym_hashes = ecoff_data (input_bfd)->sym_hashes;
+
+ gp = _bfd_get_gp_value (output_bfd);
+ if (gp == 0)
+ gp_undefined = TRUE;
+ else
+ gp_undefined = FALSE;
+
+ got_lo = FALSE;
- /*
- * If this is a bitfield, get the bitsize.
- */
- if (u.ti.fBitfield)
+ ext_rel = (struct external_reloc *) external_relocs;
+ ext_rel_end = ext_rel + input_section->reloc_count;
+ for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
{
- int bitsize;
+ struct internal_reloc int_rel;
+ bfd_boolean use_lo = FALSE;
+ bfd_vma addend;
+ reloc_howto_type *howto;
+ struct ecoff_link_hash_entry *h = NULL;
+ asection *s = NULL;
+ bfd_vma relocation;
+ bfd_reloc_status_type r;
+
+ if (! got_lo)
+ mips_ecoff_swap_reloc_in (input_bfd, (PTR) ext_rel, &int_rel);
+ else
+ {
+ int_rel = lo_int_rel;
+ got_lo = FALSE;
+ }
- bitsize = AUX_GET_WIDTH (bigendian, &aux_ptr[indx++]);
- sprintf (p1, " : %d", bitsize);
- p1 += strlen (buffer1);
- }
+ BFD_ASSERT (int_rel.r_type
+ < sizeof mips_howto_table / sizeof mips_howto_table[0]);
+ /* The REFHI reloc requires special handling. It must be followed
+ by a REFLO reloc, and the addend is formed from both relocs. */
+ if (int_rel.r_type == MIPS_R_REFHI)
+ {
+ struct external_reloc *lo_ext_rel;
+
+ /* As a GNU extension, permit an arbitrary number of REFHI
+ relocs before the REFLO reloc. This permits gcc to emit
+ the HI and LO relocs itself. */
+ for (lo_ext_rel = ext_rel + 1;
+ lo_ext_rel < ext_rel_end;
+ lo_ext_rel++)
+ {
+ mips_ecoff_swap_reloc_in (input_bfd, (PTR) lo_ext_rel,
+ &lo_int_rel);
+ if (lo_int_rel.r_type != int_rel.r_type)
+ break;
+ }
- /*
- * Deal with any qualifiers.
- */
- if (qualifiers[0].type != tqNil)
- {
- /*
- * Snarf up any array bounds in the correct order. Arrays
- * store 5 successive words in the aux. table:
- * word 0 RNDXR to type of the bounds (ie, int)
- * word 1 Current file descriptor index
- * word 2 low bound
- * word 3 high bound (or -1 if [])
- * word 4 stride size in bits
- */
- for (i = 0; i < 7; i++)
+ if (lo_ext_rel < ext_rel_end
+ && lo_int_rel.r_type == MIPS_R_REFLO
+ && int_rel.r_extern == lo_int_rel.r_extern
+ && int_rel.r_symndx == lo_int_rel.r_symndx)
+ {
+ use_lo = TRUE;
+ if (lo_ext_rel == ext_rel + 1)
+ got_lo = TRUE;
+ }
+ }
+
+ howto = &mips_howto_table[int_rel.r_type];
+
+ if (int_rel.r_extern)
{
- if (qualifiers[i].type == tqArray)
+ h = sym_hashes[int_rel.r_symndx];
+ /* If h is NULL, that means that there is a reloc against an
+ external symbol which we thought was just a debugging
+ symbol. This should not happen. */
+ if (h == (struct ecoff_link_hash_entry *) NULL)
+ abort ();
+ }
+ else
+ {
+ if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
+ s = NULL;
+ else
+ s = symndx_to_section[int_rel.r_symndx];
+
+ if (s == (asection *) NULL)
+ abort ();
+ }
+
+ /* The GPREL reloc uses an addend: the difference in the GP
+ values. */
+ if (int_rel.r_type != MIPS_R_GPREL
+ && int_rel.r_type != MIPS_R_LITERAL)
+ addend = 0;
+ else
+ {
+ if (gp_undefined)
+ {
+ if (! ((*info->callbacks->reloc_dangerous)
+ (info, _("GP relative relocation used when GP not defined"),
+ input_bfd, input_section,
+ int_rel.r_vaddr - input_section->vma)))
+ return FALSE;
+ /* Only give the error once per link. */
+ gp = 4;
+ _bfd_set_gp_value (output_bfd, gp);
+ gp_undefined = FALSE;
+ }
+ if (! int_rel.r_extern)
+ {
+ /* This is a relocation against a section. The current
+ addend in the instruction is the difference between
+ INPUT_SECTION->vma and the GP value of INPUT_BFD. We
+ must change this to be the difference between the
+ final definition (which will end up in RELOCATION)
+ and the GP value of OUTPUT_BFD (which is in GP). */
+ addend = ecoff_data (input_bfd)->gp - gp;
+ }
+ else if (! info->relocatable
+ || h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ /* This is a relocation against a defined symbol. The
+ current addend in the instruction is simply the
+ desired offset into the symbol (normally zero). We
+ are going to change this into a relocation against a
+ defined symbol, so we want the instruction to hold
+ the difference between the final definition of the
+ symbol (which will end up in RELOCATION) and the GP
+ value of OUTPUT_BFD (which is in GP). */
+ addend = - gp;
+ }
+ else
{
- qualifiers[i].low_bound =
- AUX_GET_DNLOW (bigendian, &aux_ptr[indx+2]);
- qualifiers[i].high_bound =
- AUX_GET_DNHIGH (bigendian, &aux_ptr[indx+3]);
- qualifiers[i].stride =
- AUX_GET_WIDTH (bigendian, &aux_ptr[indx+4]);
- indx += 5;
+ /* This is a relocation against an undefined or common
+ symbol. The current addend in the instruction is
+ simply the desired offset into the symbol (normally
+ zero). We are generating relocatable output, and we
+ aren't going to define this symbol, so we just leave
+ the instruction alone. */
+ addend = 0;
}
}
- /*
- * Now print out the qualifiers.
- */
- for (i = 0; i < 6; i++)
+ if (info->relocatable)
{
- switch (qualifiers[i].type)
+ /* We are generating relocatable output, and must convert
+ the existing reloc. */
+ if (int_rel.r_extern)
{
- case tqNil:
- case tqMax:
- break;
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && ! bfd_is_abs_section (h->root.u.def.section))
+ {
+ const char *name;
+
+ /* This symbol is defined in the output. Convert
+ the reloc from being against the symbol to being
+ against the section. */
+
+ /* Clear the r_extern bit. */
+ int_rel.r_extern = 0;
+
+ /* Compute a new r_symndx value. */
+ s = h->root.u.def.section;
+ name = bfd_get_section_name (output_bfd,
+ s->output_section);
+
+ int_rel.r_symndx = -1;
+ switch (name[1])
+ {
+ case 'b':
+ if (strcmp (name, ".bss") == 0)
+ int_rel.r_symndx = RELOC_SECTION_BSS;
+ break;
+ case 'd':
+ if (strcmp (name, ".data") == 0)
+ int_rel.r_symndx = RELOC_SECTION_DATA;
+ break;
+ case 'f':
+ if (strcmp (name, ".fini") == 0)
+ int_rel.r_symndx = RELOC_SECTION_FINI;
+ break;
+ case 'i':
+ if (strcmp (name, ".init") == 0)
+ int_rel.r_symndx = RELOC_SECTION_INIT;
+ break;
+ case 'l':
+ if (strcmp (name, ".lit8") == 0)
+ int_rel.r_symndx = RELOC_SECTION_LIT8;
+ else if (strcmp (name, ".lit4") == 0)
+ int_rel.r_symndx = RELOC_SECTION_LIT4;
+ break;
+ case 'r':
+ if (strcmp (name, ".rdata") == 0)
+ int_rel.r_symndx = RELOC_SECTION_RDATA;
+ break;
+ case 's':
+ if (strcmp (name, ".sdata") == 0)
+ int_rel.r_symndx = RELOC_SECTION_SDATA;
+ else if (strcmp (name, ".sbss") == 0)
+ int_rel.r_symndx = RELOC_SECTION_SBSS;
+ break;
+ case 't':
+ if (strcmp (name, ".text") == 0)
+ int_rel.r_symndx = RELOC_SECTION_TEXT;
+ break;
+ }
+
+ if (int_rel.r_symndx == -1)
+ abort ();
+
+ /* Add the section VMA and the symbol value. */
+ relocation = (h->root.u.def.value
+ + s->output_section->vma
+ + s->output_offset);
+
+ /* For a PC relative relocation, the object file
+ currently holds just the addend. We must adjust
+ by the address to get the right value. */
+ if (howto->pc_relative)
+ relocation -= int_rel.r_vaddr - input_section->vma;
+
+ h = NULL;
+ }
+ else
+ {
+ /* Change the symndx value to the right one for the
+ output BFD. */
+ int_rel.r_symndx = h->indx;
+ if (int_rel.r_symndx == -1)
+ {
+ /* This symbol is not being written out. */
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, h->root.root.string, input_bfd,
+ input_section,
+ int_rel.r_vaddr - input_section->vma)))
+ return FALSE;
+ int_rel.r_symndx = 0;
+ }
+ relocation = 0;
+ }
+ }
+ else
+ {
+ /* This is a relocation against a section. Adjust the
+ value by the amount the section moved. */
+ relocation = (s->output_section->vma
+ + s->output_offset
+ - s->vma);
+ }
- case tqPtr:
- strcpy (p2, "ptr to ");
- p2 += sizeof ("ptr to ")-1;
- break;
+ relocation += addend;
+ addend = 0;
+
+ /* Adjust a PC relative relocation by removing the reference
+ to the original address in the section and including the
+ reference to the new address. */
+ if (howto->pc_relative)
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset
+ - input_section->vma);
+
+ /* Adjust the contents. */
+ if (relocation == 0)
+ r = bfd_reloc_ok;
+ else
+ {
+ if (int_rel.r_type != MIPS_R_REFHI)
+ r = _bfd_relocate_contents (howto, input_bfd, relocation,
+ (contents
+ + int_rel.r_vaddr
+ - input_section->vma));
+ else
+ {
+ mips_relocate_hi (&int_rel,
+ use_lo ? &lo_int_rel : NULL,
+ input_bfd, input_section, contents,
+ relocation);
+ r = bfd_reloc_ok;
+ }
+ }
- case tqVol:
- strcpy (p2, "volatile ");
- p2 += sizeof ("volatile ")-1;
- break;
+ /* Adjust the reloc address. */
+ int_rel.r_vaddr += (input_section->output_section->vma
+ + input_section->output_offset
+ - input_section->vma);
- case tqFar:
- strcpy (p2, "far ");
- p2 += sizeof ("far ")-1;
- break;
+ /* Save the changed reloc information. */
+ mips_ecoff_swap_reloc_out (input_bfd, &int_rel, (PTR) ext_rel);
+ }
+ else
+ {
+ /* We are producing a final executable. */
+ if (int_rel.r_extern)
+ {
+ /* This is a reloc against a symbol. */
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *hsec;
+
+ hsec = h->root.u.def.section;
+ relocation = (h->root.u.def.value
+ + hsec->output_section->vma
+ + hsec->output_offset);
+ }
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section,
+ int_rel.r_vaddr - input_section->vma, TRUE)))
+ return FALSE;
+ relocation = 0;
+ }
+ }
+ else
+ {
+ /* This is a reloc against a section. */
+ relocation = (s->output_section->vma
+ + s->output_offset
+ - s->vma);
+
+ /* A PC relative reloc is already correct in the object
+ file. Make it look like a pcrel_offset relocation by
+ adding in the start address. */
+ if (howto->pc_relative)
+ relocation += int_rel.r_vaddr;
+ }
- case tqProc:
- strcpy (p2, "func. ret. ");
- p2 += sizeof ("func. ret. ");
- break;
+ if (int_rel.r_type != MIPS_R_REFHI)
+ r = _bfd_final_link_relocate (howto,
+ input_bfd,
+ input_section,
+ contents,
+ (int_rel.r_vaddr
+ - input_section->vma),
+ relocation,
+ addend);
+ else
+ {
+ mips_relocate_hi (&int_rel,
+ use_lo ? &lo_int_rel : NULL,
+ input_bfd, input_section, contents,
+ relocation);
+ r = bfd_reloc_ok;
+ }
+ }
- case tqArray:
+ /* MIPS_R_JMPADDR requires peculiar overflow detection. The
+ instruction provides a 28 bit address (the two lower bits are
+ implicit zeroes) which is combined with the upper four bits
+ of the instruction address. */
+ if (r == bfd_reloc_ok
+ && int_rel.r_type == MIPS_R_JMPADDR
+ && (((relocation
+ + addend
+ + (int_rel.r_extern ? 0 : s->vma))
+ & 0xf0000000)
+ != ((input_section->output_section->vma
+ + input_section->output_offset
+ + (int_rel.r_vaddr - input_section->vma))
+ & 0xf0000000)))
+ r = bfd_reloc_overflow;
+
+ if (r != bfd_reloc_ok)
+ {
+ switch (r)
+ {
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+ case bfd_reloc_overflow:
{
- int first_array = i;
- int j;
-
- /* Print array bounds reversed (ie, in the order the C
- programmer writes them). C is such a fun language.... */
-
- while (i < 5 && qualifiers[i+1].type == tqArray)
- i++;
-
- for (j = i; j >= first_array; j--)
- {
- strcpy (p2, "array [");
- p2 += sizeof ("array [")-1;
- if (qualifiers[j].low_bound != 0)
- sprintf (p2,
- "%ld:%ld {%ld bits}",
- (long) qualifiers[j].low_bound,
- (long) qualifiers[j].high_bound,
- (long) qualifiers[j].stride);
-
- else if (qualifiers[j].high_bound != -1)
- sprintf (p2,
- "%ld {%ld bits}",
- (long) (qualifiers[j].high_bound + 1),
- (long) (qualifiers[j].stride));
-
- else
- sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
-
- p2 += strlen (p2);
- strcpy (p2, "] of ");
- p2 += sizeof ("] of ")-1;
- }
+ const char *name;
+
+ if (int_rel.r_extern)
+ name = NULL;
+ else
+ name = bfd_section_name (input_bfd, s);
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section,
+ int_rel.r_vaddr - input_section->vma)))
+ return FALSE;
}
break;
}
}
}
- strcpy (p2, buffer1);
- return buffer2;
+ return TRUE;
}
+\f
+/* This is the ECOFF backend structure. The backend field of the
+ target vector points to this. */
-/* Print information about an ECOFF symbol. */
-
-static void
-DEFUN (ecoff_print_symbol, (abfd, filep, symbol, how),
- bfd *abfd AND
- PTR filep AND
- asymbol *symbol AND
- bfd_print_symbol_type how)
+static const struct ecoff_backend_data mips_ecoff_backend_data =
{
- FILE *file = (FILE *)filep;
+ /* COFF backend structure. */
+ {
+ (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */
+ (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
+ (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
+ (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/
+ (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
+ (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
+ (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
+ mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
+ mips_ecoff_swap_scnhdr_out,
+ FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, FALSE, 4, FALSE, 2,
+ mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
+ mips_ecoff_swap_scnhdr_in, NULL,
+ mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
+ _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
+ _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL
+ },
+ /* Supported architecture. */
+ bfd_arch_mips,
+ /* Initial portion of armap string. */
+ "__________",
+ /* The page boundary used to align sections in a demand-paged
+ executable file. E.g., 0x1000. */
+ 0x1000,
+ /* TRUE if the .rdata section is part of the text segment, as on the
+ Alpha. FALSE if .rdata is part of the data segment, as on the
+ MIPS. */
+ FALSE,
+ /* Bitsize of constructor entries. */
+ 32,
+ /* Reloc to use for constructor entries. */
+ &mips_howto_table[MIPS_R_REFWORD],
+ {
+ /* Symbol table magic number. */
+ magicSym,
+ /* Alignment of debugging information. E.g., 4. */
+ 4,
+ /* Sizes of external symbolic information. */
+ sizeof (struct hdr_ext),
+ sizeof (struct dnr_ext),
+ sizeof (struct pdr_ext),
+ sizeof (struct sym_ext),
+ sizeof (struct opt_ext),
+ sizeof (struct fdr_ext),
+ sizeof (struct rfd_ext),
+ sizeof (struct ext_ext),
+ /* Functions to swap in external symbolic data. */
+ ecoff_swap_hdr_in,
+ ecoff_swap_dnr_in,
+ ecoff_swap_pdr_in,
+ ecoff_swap_sym_in,
+ ecoff_swap_opt_in,
+ ecoff_swap_fdr_in,
+ ecoff_swap_rfd_in,
+ ecoff_swap_ext_in,
+ _bfd_ecoff_swap_tir_in,
+ _bfd_ecoff_swap_rndx_in,
+ /* Functions to swap out external symbolic data. */
+ ecoff_swap_hdr_out,
+ ecoff_swap_dnr_out,
+ ecoff_swap_pdr_out,
+ ecoff_swap_sym_out,
+ ecoff_swap_opt_out,
+ ecoff_swap_fdr_out,
+ ecoff_swap_rfd_out,
+ ecoff_swap_ext_out,
+ _bfd_ecoff_swap_tir_out,
+ _bfd_ecoff_swap_rndx_out,
+ /* Function to read in symbolic data. */
+ _bfd_ecoff_slurp_symbolic_info
+ },
+ /* External reloc size. */
+ RELSZ,
+ /* Reloc swapping functions. */
+ mips_ecoff_swap_reloc_in,
+ mips_ecoff_swap_reloc_out,
+ /* Backend reloc tweaking. */
+ mips_adjust_reloc_in,
+ mips_adjust_reloc_out,
+ /* Relocate section contents while linking. */
+ mips_relocate_section,
+ /* Do final adjustments to filehdr and aouthdr. */
+ NULL,
+ /* Read an element from an archive at a given file position. */
+ _bfd_get_elt_at_filepos
+};
- switch (how)
- {
- case bfd_print_symbol_name:
- fprintf (file, "%s", symbol->name);
- break;
- case bfd_print_symbol_more:
- if (ecoffsymbol (symbol)->local)
- {
- SYMR ecoff_sym;
-
- ecoff_swap_sym_in (abfd, ecoffsymbol (symbol)->native.lnative,
- &ecoff_sym);
- fprintf (file, "ecoff local %lx %x %x",
- (unsigned long) ecoff_sym.value,
- (unsigned) ecoff_sym.st, (unsigned) ecoff_sym.sc);
- }
- else
- {
- EXTR ecoff_ext;
-
- ecoff_swap_ext_in (abfd, ecoffsymbol (symbol)->native.enative,
- &ecoff_ext);
- fprintf (file, "ecoff extern %lx %x %x",
- (unsigned long) ecoff_ext.asym.value,
- (unsigned) ecoff_ext.asym.st,
- (unsigned) ecoff_ext.asym.sc);
- }
- break;
- case bfd_print_symbol_nm:
- {
- CONST char *section_name = symbol->section->name;
-
- bfd_print_symbol_vandf ((PTR) file, symbol);
- fprintf (file, " %-5s %s %s",
- section_name,
- ecoffsymbol (symbol)->local ? "l" : "e",
- symbol->name);
- }
- break;
- case bfd_print_symbol_all:
- /* Print out the symbols in a reasonable way */
- {
- CONST char *section_name = symbol->section->name;
- char type;
- int pos;
- EXTR ecoff_ext;
- char jmptbl;
- char cobol_main;
- char weakext;
-
- if (ecoffsymbol (symbol)->local)
- {
- ecoff_swap_sym_in (abfd, ecoffsymbol (symbol)->native.lnative,
- &ecoff_ext.asym);
- type = 'l';
- pos = (ecoffsymbol (symbol)->native.lnative
- - ecoff_data (abfd)->external_sym
- + ecoff_data (abfd)->symbolic_header.iextMax);
- jmptbl = ' ';
- cobol_main = ' ';
- weakext = ' ';
- }
- else
- {
- ecoff_swap_ext_in (abfd, ecoffsymbol (symbol)->native.enative,
- &ecoff_ext);
- type = 'e';
- pos = (ecoffsymbol (symbol)->native.enative
- - ecoff_data (abfd)->external_ext);
- jmptbl = ecoff_ext.jmptbl ? 'j' : ' ';
- cobol_main = ecoff_ext.cobol_main ? 'c' : ' ';
- weakext = ecoff_ext.weakext ? 'w' : ' ';
- }
-
- fprintf (file, "[%3d] %c %lx st %x sc %x indx %x %c%c%c %s",
- pos, type, (unsigned long) ecoff_ext.asym.value,
- (unsigned) ecoff_ext.asym.st,
- (unsigned) ecoff_ext.asym.sc,
- (unsigned) ecoff_ext.asym.index,
- jmptbl, cobol_main, weakext,
- symbol->name);
-
- if (ecoffsymbol (symbol)->fdr != NULL
- && ecoff_ext.asym.index != indexNil)
- {
- unsigned indx;
- int bigendian;
- long sym_base;
- union aux_ext *aux_base;
-
- 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;
- if (ecoffsymbol (symbol)->local)
- sym_base += ecoff_data (abfd)->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)->external_aux
- + ecoffsymbol (symbol)->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;
-
- /* This switch is basically from gcc/mips-tdump.c */
- switch (ecoff_ext.asym.st)
- {
- case stNil:
- case stLabel:
- break;
+/* Looking up a reloc type is MIPS specific. */
+#define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
- case stFile:
- case stBlock:
- printf ("\n End+1 symbol: %ld", indx + sym_base);
- break;
+/* Getting relocated section contents is generic. */
+#define _bfd_ecoff_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
- case stEnd:
- if (ecoff_ext.asym.sc == scText
- || ecoff_ext.asym.sc == scInfo)
- printf ("\n First symbol: %ld", indx + sym_base);
- else
- printf ("\n First symbol: %ld",
- (AUX_GET_ISYM (bigendian,
- &aux_base[ecoff_ext.asym.index])
- + sym_base));
- break;
+/* Handling file windows is generic. */
+#define _bfd_ecoff_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
- case stProc:
- case stStaticProc:
- if (MIPS_IS_STAB (&ecoff_ext.asym))
- ;
- else if (ecoffsymbol (symbol)->local)
- printf ("\n End+1 symbol: %-7ld Type: %s",
- (AUX_GET_ISYM (bigendian,
- &aux_base[ecoff_ext.asym.index])
- + sym_base),
- type_to_string (abfd, aux_base, indx + 1,
- bigendian));
- else
- printf ("\n Type: %s",
- type_to_string (abfd, aux_base, indx, bigendian));
+/* Relaxing sections is MIPS specific. */
+#define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
- break;
+/* GC of sections is not done. */
+#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
- default:
- if (!MIPS_IS_STAB (&ecoff_ext.asym))
- printf ("\n Type: %s",
- type_to_string (abfd, aux_base, indx, bigendian));
- break;
- }
- }
- }
- break;
- }
-}
-\f
-/* Provided a BFD, a section and an offset into the section, calculate
- and return the name of the source file and the line nearest to the
- wanted location. */
-
-static boolean
-DEFUN (ecoff_find_nearest_line, (abfd,
- section,
- ignore_symbols,
- offset,
- filename_ptr,
- functionname_ptr,
- retline_ptr),
- bfd *abfd AND
- asection *section AND
- asymbol **ignore_symbols AND
- bfd_vma offset AND
- CONST char **filename_ptr AND
- CONST char **functionname_ptr AND
- unsigned int *retline_ptr)
-{
- FDR *fdr_ptr;
- FDR *fdr_start;
- FDR *fdr_end;
- FDR *fdr_hold;
- struct pdr_ext *pdr_ptr;
- struct pdr_ext *pdr_end;
- PDR pdr;
- unsigned char *line_ptr;
- unsigned char *line_end;
- int lineno;
- SYMR proc_sym;
-
- /* If we're not in the .text section, we don't have any line
- numbers. */
- if (strcmp (section->name, _TEXT) != 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)->fdr;
- fdr_end = fdr_start + ecoff_data (abfd)->symbolic_header.ifdMax;
- fdr_hold = (FDR *) NULL;
- for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
- {
- if (offset < fdr_ptr->adr)
- break;
- if (fdr_ptr->cpd > 0)
- 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;
- pdr_ptr = ecoff_data (abfd)->external_pdr + fdr_ptr->ipdFirst;
- pdr_end = pdr_ptr + fdr_ptr->cpd;
- ecoff_swap_pdr_in (abfd, pdr_ptr, &pdr);
- if (offset < pdr.adr)
- return false;
- for (pdr_ptr++; pdr_ptr < pdr_end; pdr_ptr++)
- {
- ecoff_swap_pdr_in (abfd, pdr_ptr, &pdr);
- if (offset < pdr.adr)
- break;
- }
+/* Merging of sections is not done. */
+#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
- /* 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)->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--;
- ecoff_swap_pdr_in (abfd, pdr_ptr, &pdr);
-
- offset -= pdr.adr;
- lineno = pdr.lnLow;
- line_ptr = (ecoff_data (abfd)->line
- + fdr_ptr->cbLineOffset
- + pdr.cbLineOffset);
- while (line_ptr < line_end)
- {
- int delta;
- int count;
-
- delta = *line_ptr >> 4;
- if (delta >= 0x8)
- delta -= 0x10;
- count = (*line_ptr & 0xf) + 1;
- ++line_ptr;
- if (delta == -8)
- {
- delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
- if (delta >= 0x8000)
- delta -= 0x10000;
- line_ptr += 2;
- }
- lineno += delta;
- if (offset < count * 4)
- break;
- offset -= count * 4;
- }
+#define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
+#define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
+#define _bfd_ecoff_section_already_linked \
+ _bfd_generic_section_already_linked
- /* If offset is too large, this line is not interesting. */
- if (offset > 100)
- return false;
-
- *filename_ptr = ecoff_data (abfd)->ss + fdr_ptr->issBase + fdr_ptr->rss;
- ecoff_swap_sym_in (abfd,
- (ecoff_data (abfd)->external_sym
- + fdr_ptr->isymBase
- + pdr.isym),
- &proc_sym);
- *functionname_ptr = ecoff_data (abfd)->ss + proc_sym.iss;
- *retline_ptr = lineno;
- return true;
-}
-\f
-static CONST bfd_coff_backend_data bfd_ecoff_std_swap_table = {
- (void (*) PARAMS ((bfd *,PTR,int,int,PTR))) bfd_void, /* aux_in */
- (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
- (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
- (unsigned (*) PARAMS ((bfd *,PTR,int,int,PTR))) bfd_void, /* aux_out */
- (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
- (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
- ecoff_swap_reloc_out, ecoff_swap_filehdr_out, ecoff_swap_aouthdr_out,
- ecoff_swap_scnhdr_out,
- FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, true,
- ecoff_swap_filehdr_in, ecoff_swap_aouthdr_in, ecoff_swap_scnhdr_in,
- ecoff_bad_format_hook, ecoff_set_arch_mach_hook, ecoff_mkobject_hook,
- styp_to_sec_flags, ecoff_make_section_hook, ecoff_set_alignment_hook,
- ecoff_slurp_symbol_table
-};
+extern const bfd_target ecoff_big_vec;
-/* Routines that need to be written. */
-#define ecoff_write_object_contents (boolean (*) PARAMS ((bfd *))) bfd_false
-#define ecoff_set_section_contents (boolean (*) PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type))) bfd_false
-#define ecoff_get_reloc_upper_bound (unsigned int (*) PARAMS ((bfd *, sec_ptr))) bfd_0
-#define ecoff_canonicalize_reloc (unsigned int (*) PARAMS ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry **))) bfd_0
-#define ecoff_set_arch_mach (boolean (*) PARAMS ((bfd *, enum bfd_architecture, unsigned long))) bfd_false
-#define ecoff_sizeof_headers (int (*) PARAMS ((bfd *, boolean))) bfd_0
-
-/* get_lineno could be written for ECOFF, but it would currently only
- be useful for linking ECOFF and COFF files together, which doesn't
- seem too likely. */
-#define ecoff_get_lineno (struct lineno_cache_entry *(*)()) bfd_nullvoidptr
-
-#define ecoff_core_file_failing_command _bfd_dummy_core_file_failing_command
-#define ecoff_core_file_failing_signal _bfd_dummy_core_file_failing_signal
-#define ecoff_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
-#define ecoff_slurp_armap bfd_slurp_coff_armap
-#define ecoff_slurp_extended_name_table _bfd_slurp_extended_name_table
-#define ecoff_write_armap coff_write_armap
-#define ecoff_truncate_arname bfd_dont_truncate_arname
-#define ecoff_openr_next_archived_file bfd_generic_openr_next_archived_file
-#define ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt
-#define ecoff_get_section_contents bfd_generic_get_section_contents
-#define ecoff_close_and_cleanup bfd_generic_close_and_cleanup
-
-#define ecoff_bfd_debug_info_start bfd_void
-#define ecoff_bfd_debug_info_end bfd_void
-#define ecoff_bfd_debug_info_accumulate \
- (void (*) PARAMS ((bfd *, struct sec *))) bfd_void
-#define ecoff_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
-#define ecoff_bfd_relax_section bfd_generic_relax_section
-
-bfd_target ecoff_little_vec =
+const bfd_target ecoff_little_vec =
{
"ecoff-littlemips", /* name */
bfd_target_ecoff_flavour,
- false, /* data byte order is little */
- false, /* header byte order is little */
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
(HAS_RELOC | EXEC_P | /* object flags */
HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* sect
- flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
0, /* leading underscore */
- '/', /* ar_pad_char */
+ ' ', /* ar_pad_char */
15, /* ar_max_namelen */
- 3, /* minimum alignment power */
- _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* data */
- _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* hdrs */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
{_bfd_dummy_target, coff_object_p, /* bfd_check_format */
- bfd_generic_archive_p, _bfd_dummy_target},
- {bfd_false, ecoff_mkobject, bfd_false, /* bfd_set_format */
- bfd_false},
- {bfd_false, ecoff_write_object_contents, bfd_false, bfd_false},
- JUMP_TABLE (ecoff),
- 0, 0,
- (PTR) &bfd_ecoff_std_swap_table
+ _bfd_ecoff_archive_p, _bfd_dummy_target},
+ {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
+ BFD_JUMP_TABLE_COPY (_bfd_ecoff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
+ BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
+ BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
+ BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
+ BFD_JUMP_TABLE_LINK (_bfd_ecoff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ & ecoff_big_vec,
+
+ (PTR) &mips_ecoff_backend_data
};
-bfd_target ecoff_big_vec =
+const bfd_target ecoff_big_vec =
{
"ecoff-bigmips", /* name */
bfd_target_ecoff_flavour,
- true, /* data byte order is big */
- true, /* header byte order is big */
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
(HAS_RELOC | EXEC_P | /* object flags */
HAS_LINENO | HAS_DEBUG |
- HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
- (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* sect flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
0, /* leading underscore */
' ', /* ar_pad_char */
- 16, /* ar_max_namelen */
- 3, /* minimum alignment power */
- _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16,
- _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16,
+ 15, /* ar_max_namelen */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16,
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16,
{_bfd_dummy_target, coff_object_p, /* bfd_check_format */
- bfd_generic_archive_p, _bfd_dummy_target},
- {bfd_false, ecoff_mkobject, bfd_false, /* bfd_set_format */
- bfd_false},
- {bfd_false, ecoff_write_object_contents, /* bfd_write_contents */
- bfd_false, bfd_false},
- JUMP_TABLE(ecoff),
- 0, 0,
- (PTR) &bfd_ecoff_std_swap_table
- /* Note that there is another bfd_target just above this one. If
- you are adding initializers here, you should be adding them there
- as well. */
+ _bfd_ecoff_archive_p, _bfd_dummy_target},
+ {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
+ BFD_JUMP_TABLE_COPY (_bfd_ecoff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
+ BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
+ BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
+ BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
+ BFD_JUMP_TABLE_LINK (_bfd_ecoff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ & ecoff_little_vec,
+
+ (PTR) &mips_ecoff_backend_data
+};
+
+const bfd_target ecoff_biglittle_vec =
+{
+ "ecoff-biglittlemips", /* name */
+ bfd_target_ecoff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
+ 0, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
+
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ _bfd_ecoff_archive_p, _bfd_dummy_target},
+ {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
+ BFD_JUMP_TABLE_COPY (_bfd_ecoff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
+ BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
+ BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
+ BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
+ BFD_JUMP_TABLE_LINK (_bfd_ecoff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ NULL,
+
+ (PTR) &mips_ecoff_backend_data
};