binutils-gdb/gas/config/obj-ecoff.c

180 lines
6.0 KiB
C

/* ECOFF object file format.
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file was put together by Ian Lance Taylor <ian@cygnus.com>.
This file is part of GAS.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "as.h"
#include "coff/internal.h"
#include "bfd/libcoff.h"
#include "bfd/libecoff.h"
/* Almost all of the ECOFF support is actually in ecoff.c in the main
gas directory. This file mostly just arranges to call that one at
the right times. */
/* These are the pseudo-ops we support in this file. Only those
relating to debugging information are supported here.
The following pseudo-ops from the Kane and Heinrich MIPS book
should be defined here, but are currently unsupported: .aent,
.bgnb, .endb, .verstamp, .vreg.
The following pseudo-ops from the Kane and Heinrich MIPS book are
MIPS CPU specific, and should be defined by tc-mips.c: .alias,
.extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option,
.rdata, .sdata, .set.
The following pseudo-ops from the Kane and Heinrich MIPS book are
not MIPS CPU specific, but are also not ECOFF specific. I have
only listed the ones which are not already in read.c. It's not
completely clear where these should be defined, but tc-mips.c is
probably the most reasonable place: .asciiz, .asm0, .endr, .err,
.half, .lab, .repeat, .struct, .weakext. */
const pseudo_typeS obj_pseudo_table[] =
{
/* COFF style debugging information. .ln is not used; .loc is used
instead. */
{ "def", ecoff_directive_def, 0 },
{ "dim", ecoff_directive_dim, 0 },
{ "endef", ecoff_directive_endef, 0 },
{ "file", ecoff_directive_file, 0 },
{ "scl", ecoff_directive_scl, 0 },
{ "size", ecoff_directive_size, 0 },
{ "tag", ecoff_directive_tag, 0 },
{ "type", ecoff_directive_type, 0 },
{ "val", ecoff_directive_val, 0 },
/* ECOFF specific debugging information. */
{ "begin", ecoff_directive_begin, 0 },
{ "bend", ecoff_directive_bend, 0 },
{ "end", ecoff_directive_end, 0 },
{ "ent", ecoff_directive_ent, 0 },
{ "fmask", ecoff_directive_fmask, 0 },
{ "frame", ecoff_directive_frame, 0 },
{ "loc", ecoff_directive_loc, 0 },
{ "mask", ecoff_directive_mask, 0 },
/* These are used on Irix. I don't know how to implement them. */
{ "bgnb", s_ignore, 0 },
{ "endb", s_ignore, 0 },
{ "verstamp", s_ignore, 0 },
/* Sentinel. */
{ NULL }
};
/* Swap out the symbols and debugging information for BFD. */
void
ecoff_frob_file ()
{
const struct ecoff_debug_swap * const debug_swap
= &ecoff_backend (stdoutput)->debug_swap;
bfd_vma addr;
asection *sec;
HDRR *hdr;
char *buf;
char *set;
/* Set the section VMA values. */
addr = 0;
for (sec = stdoutput->sections; sec != (asection *) NULL; sec = sec->next)
{
bfd_set_section_vma (stdoutput, sec, addr);
addr += bfd_section_size (stdoutput, sec);
}
/* Build the ECOFF debugging information. */
hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header;
ecoff_build_debug (hdr, &buf, debug_swap);
/* Finish up the ecoff_tdata structure. */
set = buf;
#define SET(ptr, count, type, size) \
if (hdr->count == 0) \
ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \
else \
{ \
ecoff_data (stdoutput)->debug_info.ptr = (type) set; \
set += hdr->count * size; \
}
SET (line, cbLine, unsigned char *, sizeof (unsigned char));
SET (external_dnr, idnMax, PTR, debug_swap->external_dnr_size);
SET (external_pdr, ipdMax, PTR, debug_swap->external_pdr_size);
SET (external_sym, isymMax, PTR, debug_swap->external_sym_size);
SET (external_opt, ioptMax, PTR, debug_swap->external_opt_size);
SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext));
SET (ss, issMax, char *, sizeof (char));
SET (ssext, issExtMax, char *, sizeof (char));
SET (external_rfd, crfd, PTR, debug_swap->external_rfd_size);
SET (external_fdr, ifdMax, PTR, debug_swap->external_fdr_size);
SET (external_ext, iextMax, PTR, debug_swap->external_ext_size);
#undef SET
/* Fill in the register masks. */
{
asection *regsec;
struct ecoff_reginfo s;
regsec = bfd_make_section (stdoutput, REGINFO);
know (regsec != NULL);
if (bfd_get_section_contents (stdoutput, regsec, (PTR) &s,
(file_ptr) 0, sizeof s) == false)
as_fatal ("Can't read REGINFO section");
#ifdef TC_MIPS
/* Fill in the MIPS register masks. It's probably not worth
setting up a generic interface for this. */
s.gprmask = mips_gprmask;
s.cprmask[0] = mips_cprmask[0];
s.cprmask[1] = mips_cprmask[1];
s.cprmask[2] = mips_cprmask[2];
s.cprmask[3] = mips_cprmask[3];
#endif
if (bfd_set_section_contents (stdoutput, regsec, (PTR) &s,
(file_ptr) 0, sizeof s) == false)
as_fatal ("Can't write REGINFO section");
}
}
/* This is called by the ECOFF code to set the external information
for a symbol. We just pass it on to BFD, which expects the swapped
information to be stored in the native field of the symbol. */
void
obj_ecoff_set_ext (sym, ext)
symbolS *sym;
EXTR *ext;
{
const struct ecoff_debug_swap * const debug_swap
= &ecoff_backend (stdoutput)->debug_swap;
ecoff_symbol_type *esym;
know (bfd_asymbol_flavour (sym->bsym) == bfd_target_ecoff_flavour);
esym = ecoffsymbol (sym->bsym);
esym->local = false;
esym->native = xmalloc (debug_swap->external_ext_size);
(*debug_swap->swap_ext_out) (stdoutput, ext, esym->native);
}