obj-ecoff.c revision 89857
1290001Sglebius/* ECOFF object file format.
2290001Sglebius   Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
3290001Sglebius   Free Software Foundation, Inc.
4290001Sglebius   Contributed by Cygnus Support.
5290001Sglebius   This file was put together by Ian Lance Taylor <ian@cygnus.com>.
6290001Sglebius
7290001Sglebius   This file is part of GAS.
8290001Sglebius
9290001Sglebius   GAS is free software; you can redistribute it and/or modify
10290001Sglebius   it under the terms of the GNU General Public License as published by
11290001Sglebius   the Free Software Foundation; either version 2, or (at your option)
12290001Sglebius   any later version.
13290001Sglebius
14290001Sglebius   GAS is distributed in the hope that it will be useful,
15290001Sglebius   but WITHOUT ANY WARRANTY; without even the implied warranty of
16290001Sglebius   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17290001Sglebius   GNU General Public License for more details.
18290001Sglebius
19290001Sglebius   You should have received a copy of the GNU General Public License
20290001Sglebius   along with GAS; see the file COPYING.  If not, write to the Free
21290001Sglebius   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22290001Sglebius   02111-1307, USA.  */
23290001Sglebius
24290001Sglebius#define OBJ_HEADER "obj-ecoff.h"
25290001Sglebius#include "as.h"
26290001Sglebius#include "coff/internal.h"
27290001Sglebius#include "bfd/libcoff.h"
28290001Sglebius#include "bfd/libecoff.h"
29290001Sglebius
30290001Sglebius/* Almost all of the ECOFF support is actually in ecoff.c in the main
31290001Sglebius   gas directory.  This file mostly just arranges to call that one at
32290001Sglebius   the right times.  */
33290001Sglebius
34290001Sglebiusstatic int ecoff_sec_sym_ok_for_reloc PARAMS ((asection *));
35290001Sglebiusstatic void obj_ecoff_frob_symbol PARAMS ((symbolS *, int *));
36290001Sglebiusstatic void ecoff_pop_insert PARAMS ((void));
37290001Sglebiusstatic int ecoff_separate_stab_sections PARAMS ((void));
38290001Sglebius
39290001Sglebius/* These are the pseudo-ops we support in this file.  Only those
40290001Sglebius   relating to debugging information are supported here.
41290001Sglebius
42290001Sglebius   The following pseudo-ops from the Kane and Heinrich MIPS book
43290001Sglebius   should be defined here, but are currently unsupported: .aent,
44290001Sglebius   .bgnb, .endb, .verstamp, .vreg.
45290001Sglebius
46290001Sglebius   The following pseudo-ops from the Kane and Heinrich MIPS book are
47290001Sglebius   MIPS CPU specific, and should be defined by tc-mips.c: .alias,
48290001Sglebius   .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option,
49290001Sglebius   .rdata, .sdata, .set.
50290001Sglebius
51290001Sglebius   The following pseudo-ops from the Kane and Heinrich MIPS book are
52290001Sglebius   not MIPS CPU specific, but are also not ECOFF specific.  I have
53290001Sglebius   only listed the ones which are not already in read.c.  It's not
54290001Sglebius   completely clear where these should be defined, but tc-mips.c is
55290001Sglebius   probably the most reasonable place: .asciiz, .asm0, .endr, .err,
56290001Sglebius   .half, .lab, .repeat, .struct, .weakext.  */
57290001Sglebius
58290001Sglebiusconst pseudo_typeS obj_pseudo_table[] =
59290001Sglebius{
60290001Sglebius  /* COFF style debugging information. .ln is not used; .loc is used
61290001Sglebius     instead.  */
62290001Sglebius  { "def",	ecoff_directive_def,	0 },
63290001Sglebius  { "dim",	ecoff_directive_dim,	0 },
64290001Sglebius  { "endef",	ecoff_directive_endef,	0 },
65290001Sglebius  { "file",	ecoff_directive_file,	0 },
66290001Sglebius  { "scl",	ecoff_directive_scl,	0 },
67290001Sglebius  { "size",	ecoff_directive_size,	0 },
68290001Sglebius  { "esize",	ecoff_directive_size,	0 },
69290001Sglebius  { "tag",	ecoff_directive_tag,	0 },
70290001Sglebius  { "type",	ecoff_directive_type,	0 },
71290001Sglebius  { "etype",	ecoff_directive_type,	0 },
72290001Sglebius  { "val",	ecoff_directive_val,	0 },
73290001Sglebius
74290001Sglebius  /* ECOFF specific debugging information.  */
75290001Sglebius  { "begin",	ecoff_directive_begin,	0 },
76290001Sglebius  { "bend",	ecoff_directive_bend,	0 },
77290001Sglebius  { "end",	ecoff_directive_end,	0 },
78290001Sglebius  { "ent",	ecoff_directive_ent,	0 },
79290001Sglebius  { "fmask",	ecoff_directive_fmask,	0 },
80290001Sglebius  { "frame",	ecoff_directive_frame,	0 },
81290001Sglebius  { "loc",	ecoff_directive_loc,	0 },
82290001Sglebius  { "mask",	ecoff_directive_mask,	0 },
83290001Sglebius
84290001Sglebius  /* Other ECOFF directives.  */
85290001Sglebius  { "extern",	ecoff_directive_extern,	0 },
86290001Sglebius
87290001Sglebius#ifndef TC_MIPS
88290001Sglebius  /* For TC_MIPS, tc-mips.c adds this.  */
89290001Sglebius  { "weakext",	ecoff_directive_weakext, 0 },
90290001Sglebius#endif
91290001Sglebius
92290001Sglebius  /* These are used on Irix.  I don't know how to implement them.  */
93290001Sglebius  { "bgnb",	s_ignore,		0 },
94290001Sglebius  { "endb",	s_ignore,		0 },
95290001Sglebius  { "verstamp",	s_ignore,		0 },
96290001Sglebius
97290001Sglebius  /* Sentinel.  */
98290001Sglebius  { NULL,	s_ignore,		0 }
99290001Sglebius};
100290001Sglebius
101290001Sglebius/* Swap out the symbols and debugging information for BFD.  */
102290001Sglebius
103290001Sglebiusvoid
104290001Sglebiusecoff_frob_file ()
105290001Sglebius{
106290001Sglebius  const struct ecoff_debug_swap * const debug_swap
107290001Sglebius    = &ecoff_backend (stdoutput)->debug_swap;
108290001Sglebius  bfd_vma addr;
109290001Sglebius  asection **sec;
110290001Sglebius  HDRR *hdr;
111290001Sglebius  char *buf;
112290001Sglebius  char *set;
113290001Sglebius
114290001Sglebius  /* Set the section VMA values.  We force the .sdata and .sbss
115290001Sglebius     sections to the end to ensure that their VMA addresses are close
116290001Sglebius     together so that the GP register can address both of them.  We
117290001Sglebius     put the .bss section after the .sbss section.
118290001Sglebius
119290001Sglebius     Also, for the Alpha, we must sort the sections, to make sure they
120290001Sglebius     appear in the output file in the correct order.  (Actually, maybe
121290001Sglebius     this is a job for BFD.  But the VMAs computed would be out of
122290001Sglebius     whack if we computed them given our initial, random ordering.
123290001Sglebius     It's possible that that wouldn't break things; I could do some
124290001Sglebius     experimenting sometime and find out.
125290001Sglebius
126290001Sglebius     This output ordering of sections is magic, on the Alpha, at
127290001Sglebius     least.  The .lita section must come before .lit8 and .lit4,
128290001Sglebius     otherwise the OSF/1 linker may silently trash the .lit{4,8}
129290001Sglebius     section contents.  Also, .text must preceed .rdata.  These differ
130290001Sglebius     from the order described in some parts of the DEC OSF/1 Assembly
131290001Sglebius     Language Programmer's Guide, but that order doesn't seem to work
132290001Sglebius     with their linker.
133290001Sglebius
134290001Sglebius     I don't know if section ordering on the MIPS is important.  */
135290001Sglebius
136290001Sglebius  static const char *const names[] = {
137290001Sglebius    /* text segment */
138290001Sglebius    ".text", ".rdata", ".init", ".fini",
139290001Sglebius    /* data segment */
140290001Sglebius    ".data", ".lita", ".lit8", ".lit4", ".sdata", ".got",
141290001Sglebius    /* bss segment */
142290001Sglebius    ".sbss", ".bss",
143290001Sglebius  };
144290001Sglebius#define n_names ((int) (sizeof (names) / sizeof (names[0])))
145290001Sglebius
146290001Sglebius  /* Sections that match names, order to be straightened out later.  */
147290001Sglebius  asection *secs[n_names];
148290001Sglebius  int i;
149290001Sglebius
150290001Sglebius  addr = 0;
151290001Sglebius  for (i = 0; i < n_names; i++)
152290001Sglebius    secs[i] = 0;
153290001Sglebius
154290001Sglebius  for (sec = &stdoutput->sections; *sec != (asection *) NULL; )
155290001Sglebius    {
156290001Sglebius      for (i = 0; i < n_names; i++)
157290001Sglebius	if (!strcmp ((*sec)->name, names[i]))
158290001Sglebius	  {
159290001Sglebius	    secs[i] = *sec;
160290001Sglebius	    bfd_section_list_remove (stdoutput, sec);
161290001Sglebius	    break;
162290001Sglebius	  }
163290001Sglebius      if (i == n_names)
164290001Sglebius	{
165290001Sglebius	  bfd_set_section_vma (stdoutput, *sec, addr);
166290001Sglebius	  addr += bfd_section_size (stdoutput, *sec);
167290001Sglebius	  sec = &(*sec)->next;
168290001Sglebius	}
169290001Sglebius    }
170290001Sglebius  for (i = 0; i < n_names; i++)
171290001Sglebius    if (secs[i])
172290001Sglebius      {
173290001Sglebius	bfd_set_section_vma (stdoutput, secs[i], addr);
174290001Sglebius	addr += bfd_section_size (stdoutput, secs[i]);
175290001Sglebius      }
176290001Sglebius  for (i = n_names - 1; i >= 0; i--)
177290001Sglebius    if (secs[i])
178290001Sglebius      bfd_section_list_insert (stdoutput, &stdoutput->sections, secs[i]);
179290001Sglebius
180290001Sglebius  /* Build the ECOFF debugging information.  */
181290001Sglebius  assert (ecoff_data (stdoutput) != 0);
182290001Sglebius  hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header;
183290001Sglebius  ecoff_build_debug (hdr, &buf, debug_swap);
184290001Sglebius
185290001Sglebius  /* Finish up the ecoff_tdata structure.  */
186290001Sglebius  set = buf;
187290001Sglebius#define SET(ptr, count, type, size) \
188290001Sglebius  if (hdr->count == 0) \
189290001Sglebius    ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \
190290001Sglebius  else \
191290001Sglebius    { \
192290001Sglebius      ecoff_data (stdoutput)->debug_info.ptr = (type) set; \
193290001Sglebius      set += hdr->count * size; \
194290001Sglebius    }
195290001Sglebius
196290001Sglebius  SET (line, cbLine, unsigned char *, sizeof (unsigned char));
197290001Sglebius  SET (external_dnr, idnMax, PTR, debug_swap->external_dnr_size);
198290001Sglebius  SET (external_pdr, ipdMax, PTR, debug_swap->external_pdr_size);
199290001Sglebius  SET (external_sym, isymMax, PTR, debug_swap->external_sym_size);
200290001Sglebius  SET (external_opt, ioptMax, PTR, debug_swap->external_opt_size);
201290001Sglebius  SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext));
202290001Sglebius  SET (ss, issMax, char *, sizeof (char));
203290001Sglebius  SET (ssext, issExtMax, char *, sizeof (char));
204290001Sglebius  SET (external_rfd, crfd, PTR, debug_swap->external_rfd_size);
205290001Sglebius  SET (external_fdr, ifdMax, PTR, debug_swap->external_fdr_size);
206290001Sglebius  SET (external_ext, iextMax, PTR, debug_swap->external_ext_size);
207290001Sglebius
208290001Sglebius#undef SET
209290001Sglebius
210290001Sglebius  /* Fill in the register masks.  */
211290001Sglebius  {
212290001Sglebius    unsigned long gprmask = 0;
213290001Sglebius    unsigned long fprmask = 0;
214290001Sglebius    unsigned long *cprmask = NULL;
215290001Sglebius
216290001Sglebius#ifdef TC_MIPS
217290001Sglebius    /* Fill in the MIPS register masks.  It's probably not worth
218290001Sglebius       setting up a generic interface for this.  */
219290001Sglebius    gprmask = mips_gprmask;
220290001Sglebius    cprmask = mips_cprmask;
221290001Sglebius#endif
222290001Sglebius
223290001Sglebius#ifdef TC_ALPHA
224290001Sglebius    alpha_frob_ecoff_data ();
225290001Sglebius
226290001Sglebius    if (! bfd_ecoff_set_gp_value (stdoutput, alpha_gp_value))
227290001Sglebius      as_fatal (_("Can't set GP value"));
228290001Sglebius
229290001Sglebius    gprmask = alpha_gprmask;
230290001Sglebius    fprmask = alpha_fprmask;
231290001Sglebius#endif
232290001Sglebius
233290001Sglebius    if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask))
234290001Sglebius      as_fatal (_("Can't set register masks"));
235290001Sglebius  }
236290001Sglebius}
237290001Sglebius
238290001Sglebius/* This is called by the ECOFF code to set the external information
239290001Sglebius   for a symbol.  We just pass it on to BFD, which expects the swapped
240290001Sglebius   information to be stored in the native field of the symbol.  */
241290001Sglebius
242290001Sglebiusvoid
243290001Sglebiusobj_ecoff_set_ext (sym, ext)
244290001Sglebius     symbolS *sym;
245290001Sglebius     EXTR *ext;
246290001Sglebius{
247290001Sglebius  const struct ecoff_debug_swap * const debug_swap
248290001Sglebius    = &ecoff_backend (stdoutput)->debug_swap;
249290001Sglebius  ecoff_symbol_type *esym;
250290001Sglebius
251290001Sglebius  know (bfd_asymbol_flavour (symbol_get_bfdsym (sym))
252290001Sglebius	== bfd_target_ecoff_flavour);
253290001Sglebius  esym = ecoffsymbol (symbol_get_bfdsym (sym));
254290001Sglebius  esym->local = false;
255290001Sglebius  esym->native = xmalloc (debug_swap->external_ext_size);
256290001Sglebius  (*debug_swap->swap_ext_out) (stdoutput, ext, esym->native);
257290001Sglebius}
258290001Sglebius
259290001Sglebiusstatic int
260290001Sglebiusecoff_sec_sym_ok_for_reloc (sec)
261290001Sglebius     asection *sec ATTRIBUTE_UNUSED;
262290001Sglebius{
263290001Sglebius  return 1;
264290001Sglebius}
265290001Sglebius
266290001Sglebiusstatic void
267290001Sglebiusobj_ecoff_frob_symbol (sym, puntp)
268290001Sglebius     symbolS *sym;
269290001Sglebius     int *puntp ATTRIBUTE_UNUSED;
270290001Sglebius{
271290001Sglebius  ecoff_frob_symbol (sym);
272290001Sglebius}
273290001Sglebius
274290001Sglebiusstatic void
275290001Sglebiusecoff_pop_insert ()
276290001Sglebius{
277290001Sglebius  pop_insert (obj_pseudo_table);
278290001Sglebius}
279290001Sglebius
280290001Sglebiusstatic int
281290001Sglebiusecoff_separate_stab_sections ()
282290001Sglebius{
283290001Sglebius  return 0;
284290001Sglebius}
285290001Sglebius
286290001Sglebiusconst struct format_ops ecoff_format_ops =
287290001Sglebius{
288290001Sglebius  bfd_target_ecoff_flavour,
289290001Sglebius  0,	/* dfl_leading_underscore */
290290001Sglebius
291290001Sglebius  /* FIXME: A comment why emit_section_symbols is different here (1) from
292290001Sglebius     the single-format definition (0) would be in order.  */
293290001Sglebius  1,	/* emit_section_symbols */
294290001Sglebius  0,	/* begin */
295290001Sglebius  ecoff_new_file,
296290001Sglebius  obj_ecoff_frob_symbol,
297290001Sglebius  ecoff_frob_file,
298290001Sglebius  0,	/* frob_file_before_adjust */
299290001Sglebius  0,	/* frob_file_after_relocs */
300290001Sglebius  0,	/* s_get_size */
301290001Sglebius  0,	/* s_set_size */
302290001Sglebius  0,	/* s_get_align */
303290001Sglebius  0,	/* s_set_align */
304290001Sglebius  0,	/* s_get_other */
305290001Sglebius  0,	/* s_set_other */
306290001Sglebius  0,	/* s_get_desc */
307290001Sglebius  0,	/* s_set_desc */
308290001Sglebius  0,	/* s_get_type */
309290001Sglebius  0,	/* s_set_type */
310290001Sglebius  0,	/* copy_symbol_attributes */
311290001Sglebius  ecoff_generate_asm_lineno,
312290001Sglebius  ecoff_stab,
313290001Sglebius  ecoff_separate_stab_sections,
314290001Sglebius  0,	/* init_stab_section */
315290001Sglebius  ecoff_sec_sym_ok_for_reloc,
316290001Sglebius  ecoff_pop_insert,
317290001Sglebius  ecoff_set_ext,
318290001Sglebius  ecoff_read_begin_hook,
319290001Sglebius  ecoff_symbol_new_hook
320290001Sglebius};
321290001Sglebius