/* ECOFF object file format.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+ Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
Contributed by Cygnus Support.
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. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+#define OBJ_HEADER "obj-ecoff.h"
#include "as.h"
#include "coff/internal.h"
#include "bfd/libcoff.h"
gas directory. This file mostly just arranges to call that one at
the right times. */
+static int ecoff_sec_sym_ok_for_reloc PARAMS ((asection *));
+static void obj_ecoff_frob_symbol PARAMS ((symbolS *, int *));
+static void ecoff_pop_insert PARAMS ((void));
+static int ecoff_separate_stab_sections PARAMS ((void));
+
/* These are the pseudo-ops we support in this file. Only those
relating to debugging information are supported here.
{ "file", ecoff_directive_file, 0 },
{ "scl", ecoff_directive_scl, 0 },
{ "size", ecoff_directive_size, 0 },
+ { "esize", ecoff_directive_size, 0 },
{ "tag", ecoff_directive_tag, 0 },
{ "type", ecoff_directive_type, 0 },
+ { "etype", ecoff_directive_type, 0 },
{ "val", ecoff_directive_val, 0 },
/* ECOFF specific debugging information. */
{ "loc", ecoff_directive_loc, 0 },
{ "mask", ecoff_directive_mask, 0 },
+ /* Other ECOFF directives. */
+ { "extern", ecoff_directive_extern, 0 },
+
+#ifndef TC_MIPS
+ /* For TC_MIPS, tc-mips.c adds this. */
+ { "weakext", ecoff_directive_weakext, 0 },
+#endif
+
/* 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 }
+ { NULL, s_ignore, 0 }
};
+/* Set section VMAs and GP values before reloc processing. */
+
+void
+ecoff_frob_file_before_fix ()
+{
+ bfd_vma addr;
+ asection **sec;
+
+ /* Set the section VMA values. We force the .sdata and .sbss
+ sections to the end to ensure that their VMA addresses are close
+ together so that the GP register can address both of them. We
+ put the .bss section after the .sbss section.
+
+ Also, for the Alpha, we must sort the sections, to make sure they
+ appear in the output file in the correct order. (Actually, maybe
+ this is a job for BFD. But the VMAs computed would be out of
+ whack if we computed them given our initial, random ordering.
+ It's possible that that wouldn't break things; I could do some
+ experimenting sometime and find out.
+
+ This output ordering of sections is magic, on the Alpha, at
+ least. The .lita section must come before .lit8 and .lit4,
+ otherwise the OSF/1 linker may silently trash the .lit{4,8}
+ section contents. Also, .text must preceed .rdata. These differ
+ from the order described in some parts of the DEC OSF/1 Assembly
+ Language Programmer's Guide, but that order doesn't seem to work
+ with their linker.
+
+ I don't know if section ordering on the MIPS is important. */
+
+ static const char *const names[] = {
+ /* text segment */
+ ".text", ".rdata", ".init", ".fini",
+ /* data segment */
+ ".data", ".lita", ".lit8", ".lit4", ".sdata", ".got",
+ /* bss segment */
+ ".sbss", ".bss",
+ };
+#define n_names ((int) (sizeof (names) / sizeof (names[0])))
+
+ /* Sections that match names, order to be straightened out later. */
+ asection *secs[n_names];
+ int i;
+
+ addr = 0;
+ for (i = 0; i < n_names; i++)
+ secs[i] = 0;
+
+ for (sec = &stdoutput->sections; *sec != (asection *) NULL; )
+ {
+ for (i = 0; i < n_names; i++)
+ if (!strcmp ((*sec)->name, names[i]))
+ {
+ secs[i] = *sec;
+ bfd_section_list_remove (stdoutput, sec);
+ break;
+ }
+ if (i == n_names)
+ {
+ bfd_set_section_vma (stdoutput, *sec, addr);
+ addr += bfd_section_size (stdoutput, *sec);
+ sec = &(*sec)->next;
+ }
+ }
+ for (i = 0; i < n_names; i++)
+ if (secs[i])
+ {
+ bfd_set_section_vma (stdoutput, secs[i], addr);
+ addr += bfd_section_size (stdoutput, secs[i]);
+ }
+ for (i = n_names - 1; i >= 0; i--)
+ if (secs[i])
+ bfd_section_list_insert (stdoutput, &stdoutput->sections, secs[i]);
+
+ /* Fill in the register masks. */
+ {
+ unsigned long gprmask = 0;
+ unsigned long fprmask = 0;
+ unsigned long *cprmask = NULL;
+
+#ifdef TC_MIPS
+ /* Fill in the MIPS register masks. It's probably not worth
+ setting up a generic interface for this. */
+ gprmask = mips_gprmask;
+ cprmask = mips_cprmask;
+#endif
+
+#ifdef TC_ALPHA
+ alpha_frob_ecoff_data ();
+
+ if (! bfd_ecoff_set_gp_value (stdoutput, alpha_gp_value))
+ as_fatal (_("Can't set GP value"));
+
+ gprmask = alpha_gprmask;
+ fprmask = alpha_fprmask;
+#endif
+
+ if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask))
+ as_fatal (_("Can't set register masks"));
+ }
+}
+
/* Swap out the symbols and debugging information for BFD. */
void
{
const struct ecoff_debug_swap * const debug_swap
= &ecoff_backend (stdoutput)->debug_swap;
- bfd_vma addr;
- asection *sec;
+ bfd_vma addr ATTRIBUTE_UNUSED;
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. */
+ assert (ecoff_data (stdoutput) != 0);
hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header;
ecoff_build_debug (hdr, &buf, debug_swap);
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
= &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;
+ know (bfd_asymbol_flavour (symbol_get_bfdsym (sym))
+ == bfd_target_ecoff_flavour);
+ esym = ecoffsymbol (symbol_get_bfdsym (sym));
+ esym->local = FALSE;
esym->native = xmalloc (debug_swap->external_ext_size);
(*debug_swap->swap_ext_out) (stdoutput, ext, esym->native);
}
+
+static int
+ecoff_sec_sym_ok_for_reloc (sec)
+ asection *sec ATTRIBUTE_UNUSED;
+{
+ return 1;
+}
+
+static void
+obj_ecoff_frob_symbol (sym, puntp)
+ symbolS *sym;
+ int *puntp ATTRIBUTE_UNUSED;
+{
+ ecoff_frob_symbol (sym);
+}
+
+static void
+ecoff_pop_insert ()
+{
+ pop_insert (obj_pseudo_table);
+}
+
+static int
+ecoff_separate_stab_sections ()
+{
+ return 0;
+}
+
+const struct format_ops ecoff_format_ops =
+{
+ bfd_target_ecoff_flavour,
+ 0, /* dfl_leading_underscore */
+
+ /* FIXME: A comment why emit_section_symbols is different here (1) from
+ the single-format definition (0) would be in order. */
+ 1, /* emit_section_symbols */
+ 0, /* begin */
+ ecoff_new_file,
+ obj_ecoff_frob_symbol,
+ ecoff_frob_file,
+ 0, /* frob_file_before_adjust */
+ ecoff_frob_file_before_fix,
+ 0, /* frob_file_after_relocs */
+ 0, /* s_get_size */
+ 0, /* s_set_size */
+ 0, /* s_get_align */
+ 0, /* s_set_align */
+ 0, /* s_get_other */
+ 0, /* s_set_other */
+ 0, /* s_get_desc */
+ 0, /* s_set_desc */
+ 0, /* s_get_type */
+ 0, /* s_set_type */
+ 0, /* copy_symbol_attributes */
+ ecoff_generate_asm_lineno,
+ ecoff_stab,
+ ecoff_separate_stab_sections,
+ 0, /* init_stab_section */
+ ecoff_sec_sym_ok_for_reloc,
+ ecoff_pop_insert,
+ ecoff_set_ext,
+ ecoff_read_begin_hook,
+ ecoff_symbol_new_hook
+};