133965Sjdp/* a.out object file format
2130561Sobrien   Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000,
3218822Sdim   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
433965Sjdp
5218822Sdim   This file is part of GAS, the GNU Assembler.
633965Sjdp
7218822Sdim   GAS is free software; you can redistribute it and/or modify
8218822Sdim   it under the terms of the GNU General Public License as
9218822Sdim   published by the Free Software Foundation; either version 2,
10218822Sdim   or (at your option) any later version.
1133965Sjdp
12218822Sdim   GAS is distributed in the hope that it will be useful, but
13218822Sdim   WITHOUT ANY WARRANTY; without even the implied warranty of
14218822Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15218822Sdim   the GNU General Public License for more details.
1633965Sjdp
17218822Sdim   You should have received a copy of the GNU General Public License
18218822Sdim   along with GAS; see the file COPYING.  If not, write to the Free
19218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20218822Sdim   02110-1301, USA.  */
2133965Sjdp
2260484Sobrien#define OBJ_HEADER "obj-aout.h"
2360484Sobrien
2433965Sjdp#include "as.h"
2533965Sjdp#undef NO_RELOC
2633965Sjdp#include "aout/aout64.h"
2733965Sjdp#include "obstack.h"
2833965Sjdp
2933965Sjdpvoid
30218822Sdimobj_aout_frob_symbol (symbolS *sym, int *punt ATTRIBUTE_UNUSED)
3133965Sjdp{
3233965Sjdp  flagword flags;
3333965Sjdp  asection *sec;
3433965Sjdp  int desc, type, other;
3533965Sjdp
3660484Sobrien  flags = symbol_get_bfdsym (sym)->flags;
3760484Sobrien  desc = aout_symbol (symbol_get_bfdsym (sym))->desc;
3860484Sobrien  type = aout_symbol (symbol_get_bfdsym (sym))->type;
3960484Sobrien  other = aout_symbol (symbol_get_bfdsym (sym))->other;
4060484Sobrien  sec = S_GET_SEGMENT (sym);
4133965Sjdp
4233965Sjdp  /* Only frob simple symbols this way right now.  */
4333965Sjdp  if (! (type & ~ (N_TYPE | N_EXT)))
4433965Sjdp    {
4533965Sjdp      if (type == (N_UNDF | N_EXT)
4633965Sjdp	  && sec == &bfd_abs_section)
4760484Sobrien	{
4860484Sobrien	  sec = bfd_und_section_ptr;
4960484Sobrien	  S_SET_SEGMENT (sym, sec);
5060484Sobrien	}
5133965Sjdp
5233965Sjdp      if ((type & N_TYPE) != N_INDR
5333965Sjdp	  && (type & N_TYPE) != N_SETA
5433965Sjdp	  && (type & N_TYPE) != N_SETT
5533965Sjdp	  && (type & N_TYPE) != N_SETD
5633965Sjdp	  && (type & N_TYPE) != N_SETB
5733965Sjdp	  && type != N_WARNING
5833965Sjdp	  && (sec == &bfd_abs_section
5933965Sjdp	      || sec == &bfd_und_section))
6033965Sjdp	return;
6133965Sjdp      if (flags & BSF_EXPORT)
6233965Sjdp	type |= N_EXT;
6333965Sjdp
6433965Sjdp      switch (type & N_TYPE)
6533965Sjdp	{
6633965Sjdp	case N_SETA:
6733965Sjdp	case N_SETT:
6833965Sjdp	case N_SETD:
6933965Sjdp	case N_SETB:
7033965Sjdp	  /* Set the debugging flag for constructor symbols so that
7133965Sjdp	     BFD leaves them alone.  */
7260484Sobrien	  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
7333965Sjdp
7433965Sjdp	  /* You can't put a common symbol in a set.  The way a set
7533965Sjdp	     element works is that the symbol has a definition and a
7633965Sjdp	     name, and the linker adds the definition to the set of
7733965Sjdp	     that name.  That does not work for a common symbol,
7833965Sjdp	     because the linker can't tell which common symbol the
7933965Sjdp	     user means.  FIXME: Using as_bad here may be
8033965Sjdp	     inappropriate, since the user may want to force a
8133965Sjdp	     particular type without regard to the semantics of sets;
8233965Sjdp	     on the other hand, we certainly don't want anybody to be
8333965Sjdp	     mislead into thinking that their code will work.  */
8433965Sjdp	  if (S_IS_COMMON (sym))
8560484Sobrien	    as_bad (_("Attempt to put a common symbol into set %s"),
8633965Sjdp		    S_GET_NAME (sym));
8733965Sjdp	  /* Similarly, you can't put an undefined symbol in a set.  */
8833965Sjdp	  else if (! S_IS_DEFINED (sym))
8960484Sobrien	    as_bad (_("Attempt to put an undefined symbol into set %s"),
9033965Sjdp		    S_GET_NAME (sym));
9133965Sjdp
9233965Sjdp	  break;
9333965Sjdp	case N_INDR:
9433965Sjdp	  /* Put indirect symbols in the indirect section.  */
9560484Sobrien	  S_SET_SEGMENT (sym, bfd_ind_section_ptr);
9660484Sobrien	  symbol_get_bfdsym (sym)->flags |= BSF_INDIRECT;
9733965Sjdp	  if (type & N_EXT)
9833965Sjdp	    {
9960484Sobrien	      symbol_get_bfdsym (sym)->flags |= BSF_EXPORT;
10060484Sobrien	      symbol_get_bfdsym (sym)->flags &=~ BSF_LOCAL;
10133965Sjdp	    }
10233965Sjdp	  break;
10333965Sjdp	case N_WARNING:
10433965Sjdp	  /* Mark warning symbols.  */
10560484Sobrien	  symbol_get_bfdsym (sym)->flags |= BSF_WARNING;
10633965Sjdp	  break;
10733965Sjdp	}
10833965Sjdp    }
10933965Sjdp  else
110218822Sdim    symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
11133965Sjdp
11260484Sobrien  aout_symbol (symbol_get_bfdsym (sym))->type = type;
11333965Sjdp
11433965Sjdp  /* Double check weak symbols.  */
115218822Sdim  if (S_IS_WEAK (sym) && S_IS_COMMON (sym))
116218822Sdim    as_bad (_("Symbol `%s' can not be both weak and common"),
117218822Sdim	    S_GET_NAME (sym));
11833965Sjdp}
11933965Sjdp
12033965Sjdpvoid
121218822Sdimobj_aout_frob_file_before_fix (void)
12233965Sjdp{
12333965Sjdp  /* Relocation processing may require knowing the VMAs of the sections.
12433965Sjdp     Since writing to a section will cause the BFD back end to compute the
12533965Sjdp     VMAs, fake it out here....  */
12633965Sjdp  bfd_byte b = 0;
127130561Sobrien  bfd_boolean x = TRUE;
12833965Sjdp  if (bfd_section_size (stdoutput, text_section) != 0)
129218822Sdim    x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0,
130218822Sdim				  (bfd_size_type) 1);
13133965Sjdp  else if (bfd_section_size (stdoutput, data_section) != 0)
132218822Sdim    x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0,
133218822Sdim				  (bfd_size_type) 1);
134218822Sdim
135130561Sobrien  assert (x);
13633965Sjdp}
13733965Sjdp
13833965Sjdpstatic void
139218822Sdimobj_aout_line (int ignore ATTRIBUTE_UNUSED)
14033965Sjdp{
14133965Sjdp  /* Assume delimiter is part of expression.
14233965Sjdp     BSD4.2 as fails with delightful bug, so we
14377298Sobrien     are not being incompatible here.  */
14433965Sjdp  new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
14533965Sjdp  demand_empty_rest_of_line ();
146218822Sdim}
14733965Sjdp
14833965Sjdp/* Handle .weak.  This is a GNU extension.  */
14933965Sjdp
15033965Sjdpstatic void
151218822Sdimobj_aout_weak (int ignore ATTRIBUTE_UNUSED)
15233965Sjdp{
15333965Sjdp  char *name;
15433965Sjdp  int c;
15533965Sjdp  symbolS *symbolP;
15633965Sjdp
15733965Sjdp  do
15833965Sjdp    {
15933965Sjdp      name = input_line_pointer;
16033965Sjdp      c = get_symbol_end ();
16133965Sjdp      symbolP = symbol_find_or_make (name);
16233965Sjdp      *input_line_pointer = c;
16333965Sjdp      SKIP_WHITESPACE ();
16433965Sjdp      S_SET_WEAK (symbolP);
16533965Sjdp      if (c == ',')
16633965Sjdp	{
16733965Sjdp	  input_line_pointer++;
16833965Sjdp	  SKIP_WHITESPACE ();
16933965Sjdp	  if (*input_line_pointer == '\n')
17033965Sjdp	    c = '\n';
17133965Sjdp	}
17233965Sjdp    }
17333965Sjdp  while (c == ',');
17433965Sjdp  demand_empty_rest_of_line ();
17533965Sjdp}
17633965Sjdp
17733965Sjdp/* Handle .type.  On {Net,Open}BSD, this is used to set the n_other field,
17833965Sjdp   which is then apparently used when doing dynamic linking.  Older
17977298Sobrien   versions of gas ignored the .type pseudo-op, so we also ignore it if
18033965Sjdp   we can't parse it.  */
18133965Sjdp
18233965Sjdpstatic void
183218822Sdimobj_aout_type (int ignore ATTRIBUTE_UNUSED)
18433965Sjdp{
18533965Sjdp  char *name;
18633965Sjdp  int c;
18733965Sjdp  symbolS *sym;
18833965Sjdp
18933965Sjdp  name = input_line_pointer;
19033965Sjdp  c = get_symbol_end ();
19177298Sobrien  sym = symbol_find_or_make (name);
19233965Sjdp  *input_line_pointer = c;
19377298Sobrien  SKIP_WHITESPACE ();
19477298Sobrien  if (*input_line_pointer == ',')
19533965Sjdp    {
19677298Sobrien      ++input_line_pointer;
19733965Sjdp      SKIP_WHITESPACE ();
19877298Sobrien      if (*input_line_pointer == '@')
19933965Sjdp	{
20033965Sjdp	  ++input_line_pointer;
20177298Sobrien	  if (strncmp (input_line_pointer, "object", 6) == 0)
202218822Sdim	    S_SET_OTHER (sym, 1);
20377298Sobrien	  else if (strncmp (input_line_pointer, "function", 8) == 0)
204218822Sdim	    S_SET_OTHER (sym, 2);
20533965Sjdp	}
20633965Sjdp    }
20733965Sjdp
20833965Sjdp  /* Ignore everything else on the line.  */
20933965Sjdp  s_ignore (0);
21033965Sjdp}
21133965Sjdp
21260484Sobrien/* Support for an AOUT emulation.  */
21360484Sobrien
21460484Sobrienstatic void
215218822Sdimaout_pop_insert (void)
21660484Sobrien{
21760484Sobrien  pop_insert (aout_pseudo_table);
21860484Sobrien}
21960484Sobrien
22060484Sobrienstatic int
221218822Sdimobj_aout_s_get_other (symbolS *sym)
22260484Sobrien{
22360484Sobrien  return aout_symbol (symbol_get_bfdsym (sym))->other;
22460484Sobrien}
22560484Sobrien
22677298Sobrienstatic void
227218822Sdimobj_aout_s_set_other (symbolS *sym, int o)
22877298Sobrien{
22977298Sobrien  aout_symbol (symbol_get_bfdsym (sym))->other = o;
23077298Sobrien}
23177298Sobrien
23260484Sobrienstatic int
233218822Sdimobj_aout_sec_sym_ok_for_reloc (asection *sec ATTRIBUTE_UNUSED)
23477298Sobrien{
23577298Sobrien  return obj_sec_sym_ok_for_reloc (sec);
23677298Sobrien}
23777298Sobrien
23877298Sobrienstatic void
239218822Sdimobj_aout_process_stab (segT seg ATTRIBUTE_UNUSED,
240218822Sdim		       int w,
241218822Sdim		       const char *s,
242218822Sdim		       int t,
243218822Sdim		       int o,
244218822Sdim		       int d)
24577298Sobrien{
24677298Sobrien  aout_process_stab (w, s, t, o, d);
24777298Sobrien}
24877298Sobrien
24977298Sobrienstatic int
250218822Sdimobj_aout_s_get_desc (symbolS *sym)
25160484Sobrien{
25260484Sobrien  return aout_symbol (symbol_get_bfdsym (sym))->desc;
25360484Sobrien}
25460484Sobrien
25577298Sobrienstatic void
256218822Sdimobj_aout_s_set_desc (symbolS *sym, int d)
25777298Sobrien{
25877298Sobrien  aout_symbol (symbol_get_bfdsym (sym))->desc = d;
25977298Sobrien}
26060484Sobrien
26177298Sobrienstatic int
262218822Sdimobj_aout_s_get_type (symbolS *sym)
26377298Sobrien{
26477298Sobrien  return aout_symbol (symbol_get_bfdsym (sym))->type;
26577298Sobrien}
26677298Sobrien
26777298Sobrienstatic void
268218822Sdimobj_aout_s_set_type (symbolS *sym, int t)
26977298Sobrien{
27077298Sobrien  aout_symbol (symbol_get_bfdsym (sym))->type = t;
27177298Sobrien}
27277298Sobrien
27377298Sobrienstatic int
274218822Sdimobj_aout_separate_stab_sections (void)
27577298Sobrien{
27677298Sobrien  return 0;
27777298Sobrien}
27877298Sobrien
27977298Sobrien/* When changed, make sure these table entries match the single-format
28077298Sobrien   definitions in obj-aout.h.  */
281218822Sdim
28260484Sobrienconst struct format_ops aout_format_ops =
28360484Sobrien{
28460484Sobrien  bfd_target_aout_flavour,
285218822Sdim  1,	/* dfl_leading_underscore.  */
286218822Sdim  0,	/* emit_section_symbols.  */
287218822Sdim  0,	/* begin.  */
288218822Sdim  0,	/* app_file.  */
28960484Sobrien  obj_aout_frob_symbol,
290218822Sdim  0,	/* frob_file.  */
291218822Sdim  0,	/* frob_file_before_adjust.  */
292130561Sobrien  obj_aout_frob_file_before_fix,
293218822Sdim  0,	/* frob_file_after_relocs.  */
294218822Sdim  0,	/* s_get_size.  */
295218822Sdim  0,	/* s_set_size.  */
296218822Sdim  0,	/* s_get_align.  */
297218822Sdim  0,	/* s_set_align.  */
29860484Sobrien  obj_aout_s_get_other,
29977298Sobrien  obj_aout_s_set_other,
30060484Sobrien  obj_aout_s_get_desc,
30177298Sobrien  obj_aout_s_set_desc,
30277298Sobrien  obj_aout_s_get_type,
30377298Sobrien  obj_aout_s_set_type,
304218822Sdim  0,	/* copy_symbol_attributes.  */
305218822Sdim  0,	/* generate_asm_lineno.  */
30677298Sobrien  obj_aout_process_stab,
30777298Sobrien  obj_aout_separate_stab_sections,
308218822Sdim  0,	/* init_stab_section.  */
30977298Sobrien  obj_aout_sec_sym_ok_for_reloc,
31060484Sobrien  aout_pop_insert,
311218822Sdim  0,	/* ecoff_set_ext.  */
312218822Sdim  0,	/* read_begin_hook.  */
313218822Sdim  0 	/* symbol_new_hook.  */
31460484Sobrien};
315218822Sdim
316218822Sdimconst pseudo_typeS aout_pseudo_table[] =
317218822Sdim{
318218822Sdim  {"line", obj_aout_line, 0},	/* Source code line number.  */
319218822Sdim  {"ln", obj_aout_line, 0},	/* COFF line number that we use anyway.  */
320218822Sdim
321218822Sdim  {"weak", obj_aout_weak, 0},	/* Mark symbol as weak.  */
322218822Sdim
323218822Sdim  {"type", obj_aout_type, 0},
324218822Sdim
325218822Sdim  /* coff debug pseudos (ignored) */
326218822Sdim  {"def", s_ignore, 0},
327218822Sdim  {"dim", s_ignore, 0},
328218822Sdim  {"endef", s_ignore, 0},
329218822Sdim  {"ident", s_ignore, 0},
330218822Sdim  {"line", s_ignore, 0},
331218822Sdim  {"ln", s_ignore, 0},
332218822Sdim  {"scl", s_ignore, 0},
333218822Sdim  {"size", s_ignore, 0},
334218822Sdim  {"tag", s_ignore, 0},
335218822Sdim  {"val", s_ignore, 0},
336218822Sdim  {"version", s_ignore, 0},
337218822Sdim
338218822Sdim  {"optim", s_ignore, 0},	/* For sun386i cc (?).  */
339218822Sdim
340218822Sdim  /* other stuff */
341218822Sdim  {"ABORT", s_abort, 0},
342218822Sdim
343218822Sdim  {NULL, NULL, 0}
344218822Sdim};
345