obj-aout.c revision 256281
1295011Sandrew/* a.out object file format
2295011Sandrew   Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000,
3295011Sandrew   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4295011Sandrew
5295011Sandrew   This file is part of GAS, the GNU Assembler.
6295011Sandrew
7295011Sandrew   GAS is free software; you can redistribute it and/or modify
8295011Sandrew   it under the terms of the GNU General Public License as
9295011Sandrew   published by the Free Software Foundation; either version 2,
10295011Sandrew   or (at your option) any later version.
11295011Sandrew
12295011Sandrew   GAS is distributed in the hope that it will be useful, but
13295011Sandrew   WITHOUT ANY WARRANTY; without even the implied warranty of
14295011Sandrew   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15295011Sandrew   the GNU General Public License for more details.
16295011Sandrew
17295011Sandrew   You should have received a copy of the GNU General Public License
18295011Sandrew   along with GAS; see the file COPYING.  If not, write to the Free
19295011Sandrew   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20295011Sandrew   02110-1301, USA.  */
21295011Sandrew
22295011Sandrew#define OBJ_HEADER "obj-aout.h"
23295011Sandrew
24295011Sandrew#include "as.h"
25295011Sandrew#undef NO_RELOC
26295011Sandrew#include "aout/aout64.h"
27295011Sandrew#include "obstack.h"
28295011Sandrew
29295011Sandrewvoid
30295011Sandrewobj_aout_frob_symbol (symbolS *sym, int *punt ATTRIBUTE_UNUSED)
31295011Sandrew{
32295011Sandrew  flagword flags;
33295011Sandrew  asection *sec;
34295011Sandrew  int desc, type, other;
35295011Sandrew
36295011Sandrew  flags = symbol_get_bfdsym (sym)->flags;
37295011Sandrew  desc = aout_symbol (symbol_get_bfdsym (sym))->desc;
38295011Sandrew  type = aout_symbol (symbol_get_bfdsym (sym))->type;
39295011Sandrew  other = aout_symbol (symbol_get_bfdsym (sym))->other;
40295011Sandrew  sec = S_GET_SEGMENT (sym);
41295011Sandrew
42295011Sandrew  /* Only frob simple symbols this way right now.  */
43295011Sandrew  if (! (type & ~ (N_TYPE | N_EXT)))
44295011Sandrew    {
45295011Sandrew      if (type == (N_UNDF | N_EXT)
46295011Sandrew	  && sec == &bfd_abs_section)
47295011Sandrew	{
48295011Sandrew	  sec = bfd_und_section_ptr;
49295011Sandrew	  S_SET_SEGMENT (sym, sec);
50295011Sandrew	}
51295011Sandrew
52295011Sandrew      if ((type & N_TYPE) != N_INDR
53295011Sandrew	  && (type & N_TYPE) != N_SETA
54295011Sandrew	  && (type & N_TYPE) != N_SETT
55295011Sandrew	  && (type & N_TYPE) != N_SETD
56295011Sandrew	  && (type & N_TYPE) != N_SETB
57295011Sandrew	  && type != N_WARNING
58295011Sandrew	  && (sec == &bfd_abs_section
59295011Sandrew	      || sec == &bfd_und_section))
60295011Sandrew	return;
61295011Sandrew      if (flags & BSF_EXPORT)
62295011Sandrew	type |= N_EXT;
63295011Sandrew
64295011Sandrew      switch (type & N_TYPE)
65295011Sandrew	{
66295011Sandrew	case N_SETA:
67295011Sandrew	case N_SETT:
68295011Sandrew	case N_SETD:
69295011Sandrew	case N_SETB:
70295011Sandrew	  /* Set the debugging flag for constructor symbols so that
71295011Sandrew	     BFD leaves them alone.  */
72295011Sandrew	  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
73295011Sandrew
74295011Sandrew	  /* You can't put a common symbol in a set.  The way a set
75295011Sandrew	     element works is that the symbol has a definition and a
76295011Sandrew	     name, and the linker adds the definition to the set of
77295011Sandrew	     that name.  That does not work for a common symbol,
78295011Sandrew	     because the linker can't tell which common symbol the
79295011Sandrew	     user means.  FIXME: Using as_bad here may be
80295011Sandrew	     inappropriate, since the user may want to force a
81295011Sandrew	     particular type without regard to the semantics of sets;
82295011Sandrew	     on the other hand, we certainly don't want anybody to be
83295011Sandrew	     mislead into thinking that their code will work.  */
84295011Sandrew	  if (S_IS_COMMON (sym))
85295011Sandrew	    as_bad (_("Attempt to put a common symbol into set %s"),
86295011Sandrew		    S_GET_NAME (sym));
87295011Sandrew	  /* Similarly, you can't put an undefined symbol in a set.  */
88295011Sandrew	  else if (! S_IS_DEFINED (sym))
89295011Sandrew	    as_bad (_("Attempt to put an undefined symbol into set %s"),
90295011Sandrew		    S_GET_NAME (sym));
91295011Sandrew
92295011Sandrew	  break;
93295011Sandrew	case N_INDR:
94295011Sandrew	  /* Put indirect symbols in the indirect section.  */
95295011Sandrew	  S_SET_SEGMENT (sym, bfd_ind_section_ptr);
96295011Sandrew	  symbol_get_bfdsym (sym)->flags |= BSF_INDIRECT;
97295011Sandrew	  if (type & N_EXT)
98295011Sandrew	    {
99295011Sandrew	      symbol_get_bfdsym (sym)->flags |= BSF_EXPORT;
100295011Sandrew	      symbol_get_bfdsym (sym)->flags &=~ BSF_LOCAL;
101295011Sandrew	    }
102295011Sandrew	  break;
103295011Sandrew	case N_WARNING:
104295011Sandrew	  /* Mark warning symbols.  */
105295011Sandrew	  symbol_get_bfdsym (sym)->flags |= BSF_WARNING;
106295011Sandrew	  break;
107295011Sandrew	}
108295011Sandrew    }
109295011Sandrew  else
110295011Sandrew    symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
111295011Sandrew
112295011Sandrew  aout_symbol (symbol_get_bfdsym (sym))->type = type;
113295011Sandrew
114295011Sandrew  /* Double check weak symbols.  */
115295011Sandrew  if (S_IS_WEAK (sym) && S_IS_COMMON (sym))
116295011Sandrew    as_bad (_("Symbol `%s' can not be both weak and common"),
117295011Sandrew	    S_GET_NAME (sym));
118295011Sandrew}
119295011Sandrew
120295011Sandrewvoid
121295011Sandrewobj_aout_frob_file_before_fix (void)
122295011Sandrew{
123295011Sandrew  /* Relocation processing may require knowing the VMAs of the sections.
124295011Sandrew     Since writing to a section will cause the BFD back end to compute the
125295011Sandrew     VMAs, fake it out here....  */
126295011Sandrew  bfd_byte b = 0;
127295011Sandrew  bfd_boolean x = TRUE;
128295011Sandrew  if (bfd_section_size (stdoutput, text_section) != 0)
129295011Sandrew    x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0,
130295011Sandrew				  (bfd_size_type) 1);
131295011Sandrew  else if (bfd_section_size (stdoutput, data_section) != 0)
132295011Sandrew    x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0,
133295011Sandrew				  (bfd_size_type) 1);
134295011Sandrew
135295011Sandrew  assert (x);
136295011Sandrew}
137295011Sandrew
138295011Sandrewstatic void
139295011Sandrewobj_aout_line (int ignore ATTRIBUTE_UNUSED)
140295011Sandrew{
141295011Sandrew  /* Assume delimiter is part of expression.
142295011Sandrew     BSD4.2 as fails with delightful bug, so we
143295011Sandrew     are not being incompatible here.  */
144295011Sandrew  new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
145295011Sandrew  demand_empty_rest_of_line ();
146295011Sandrew}
147295011Sandrew
148295011Sandrew/* Handle .weak.  This is a GNU extension.  */
149295011Sandrew
150295011Sandrewstatic void
151295011Sandrewobj_aout_weak (int ignore ATTRIBUTE_UNUSED)
152295011Sandrew{
153295011Sandrew  char *name;
154295011Sandrew  int c;
155295011Sandrew  symbolS *symbolP;
156295011Sandrew
157295011Sandrew  do
158295011Sandrew    {
159295011Sandrew      name = input_line_pointer;
160295011Sandrew      c = get_symbol_end ();
161295011Sandrew      symbolP = symbol_find_or_make (name);
162295011Sandrew      *input_line_pointer = c;
163295011Sandrew      SKIP_WHITESPACE ();
164295011Sandrew      S_SET_WEAK (symbolP);
165295011Sandrew      if (c == ',')
166295011Sandrew	{
167295011Sandrew	  input_line_pointer++;
168295011Sandrew	  SKIP_WHITESPACE ();
169295011Sandrew	  if (*input_line_pointer == '\n')
170295011Sandrew	    c = '\n';
171295011Sandrew	}
172295011Sandrew    }
173295011Sandrew  while (c == ',');
174295011Sandrew  demand_empty_rest_of_line ();
175295011Sandrew}
176295011Sandrew
177295011Sandrew/* Handle .type.  On {Net,Open}BSD, this is used to set the n_other field,
178295011Sandrew   which is then apparently used when doing dynamic linking.  Older
179295011Sandrew   versions of gas ignored the .type pseudo-op, so we also ignore it if
180295011Sandrew   we can't parse it.  */
181295011Sandrew
182295011Sandrewstatic void
183295011Sandrewobj_aout_type (int ignore ATTRIBUTE_UNUSED)
184295011Sandrew{
185295011Sandrew  char *name;
186295011Sandrew  int c;
187295011Sandrew  symbolS *sym;
188295011Sandrew
189295011Sandrew  name = input_line_pointer;
190295011Sandrew  c = get_symbol_end ();
191295011Sandrew  sym = symbol_find_or_make (name);
192295011Sandrew  *input_line_pointer = c;
193295011Sandrew  SKIP_WHITESPACE ();
194295011Sandrew  if (*input_line_pointer == ',')
195295011Sandrew    {
196295011Sandrew      ++input_line_pointer;
197295011Sandrew      SKIP_WHITESPACE ();
198295011Sandrew      if (*input_line_pointer == '@')
199295011Sandrew	{
200295011Sandrew	  ++input_line_pointer;
201295011Sandrew	  if (strncmp (input_line_pointer, "object", 6) == 0)
202295011Sandrew	    S_SET_OTHER (sym, 1);
203295011Sandrew	  else if (strncmp (input_line_pointer, "function", 8) == 0)
204295011Sandrew	    S_SET_OTHER (sym, 2);
205295011Sandrew	}
206295011Sandrew    }
207295011Sandrew
208295011Sandrew  /* Ignore everything else on the line.  */
209295011Sandrew  s_ignore (0);
210295011Sandrew}
211295011Sandrew
212295011Sandrew/* Support for an AOUT emulation.  */
213295011Sandrew
214295011Sandrewstatic void
215295011Sandrewaout_pop_insert (void)
216295011Sandrew{
217295011Sandrew  pop_insert (aout_pseudo_table);
218295011Sandrew}
219295011Sandrew
220295011Sandrewstatic int
221295011Sandrewobj_aout_s_get_other (symbolS *sym)
222295011Sandrew{
223295011Sandrew  return aout_symbol (symbol_get_bfdsym (sym))->other;
224295011Sandrew}
225295011Sandrew
226295011Sandrewstatic void
227295011Sandrewobj_aout_s_set_other (symbolS *sym, int o)
228295011Sandrew{
229295011Sandrew  aout_symbol (symbol_get_bfdsym (sym))->other = o;
230295011Sandrew}
231295011Sandrew
232295011Sandrewstatic int
233295011Sandrewobj_aout_sec_sym_ok_for_reloc (asection *sec ATTRIBUTE_UNUSED)
234295011Sandrew{
235295011Sandrew  return obj_sec_sym_ok_for_reloc (sec);
236295011Sandrew}
237295011Sandrew
238295011Sandrewstatic void
239295011Sandrewobj_aout_process_stab (segT seg ATTRIBUTE_UNUSED,
240295011Sandrew		       int w,
241295011Sandrew		       const char *s,
242295011Sandrew		       int t,
243295011Sandrew		       int o,
244295011Sandrew		       int d)
245295011Sandrew{
246295011Sandrew  aout_process_stab (w, s, t, o, d);
247295011Sandrew}
248295011Sandrew
249295011Sandrewstatic int
250295011Sandrewobj_aout_s_get_desc (symbolS *sym)
251295011Sandrew{
252295011Sandrew  return aout_symbol (symbol_get_bfdsym (sym))->desc;
253295011Sandrew}
254295011Sandrew
255295011Sandrewstatic void
256295011Sandrewobj_aout_s_set_desc (symbolS *sym, int d)
257295011Sandrew{
258295011Sandrew  aout_symbol (symbol_get_bfdsym (sym))->desc = d;
259295011Sandrew}
260295011Sandrew
261295011Sandrewstatic int
262295011Sandrewobj_aout_s_get_type (symbolS *sym)
263295011Sandrew{
264295011Sandrew  return aout_symbol (symbol_get_bfdsym (sym))->type;
265295011Sandrew}
266295011Sandrew
267295011Sandrewstatic void
268295011Sandrewobj_aout_s_set_type (symbolS *sym, int t)
269295011Sandrew{
270295011Sandrew  aout_symbol (symbol_get_bfdsym (sym))->type = t;
271295011Sandrew}
272295011Sandrew
273295011Sandrewstatic int
274295011Sandrewobj_aout_separate_stab_sections (void)
275295011Sandrew{
276295011Sandrew  return 0;
277295011Sandrew}
278295011Sandrew
279295011Sandrew/* When changed, make sure these table entries match the single-format
280295011Sandrew   definitions in obj-aout.h.  */
281295011Sandrew
282295011Sandrewconst struct format_ops aout_format_ops =
283295011Sandrew{
284295011Sandrew  bfd_target_aout_flavour,
285295011Sandrew  1,	/* dfl_leading_underscore.  */
286295011Sandrew  0,	/* emit_section_symbols.  */
287295011Sandrew  0,	/* begin.  */
288295011Sandrew  0,	/* app_file.  */
289295011Sandrew  obj_aout_frob_symbol,
290295011Sandrew  0,	/* frob_file.  */
291295011Sandrew  0,	/* frob_file_before_adjust.  */
292295011Sandrew  obj_aout_frob_file_before_fix,
293295011Sandrew  0,	/* frob_file_after_relocs.  */
294295011Sandrew  0,	/* s_get_size.  */
295295011Sandrew  0,	/* s_set_size.  */
296295011Sandrew  0,	/* s_get_align.  */
297295011Sandrew  0,	/* s_set_align.  */
298295011Sandrew  obj_aout_s_get_other,
299295011Sandrew  obj_aout_s_set_other,
300295011Sandrew  obj_aout_s_get_desc,
301295011Sandrew  obj_aout_s_set_desc,
302295011Sandrew  obj_aout_s_get_type,
303295011Sandrew  obj_aout_s_set_type,
304295011Sandrew  0,	/* copy_symbol_attributes.  */
305295011Sandrew  0,	/* generate_asm_lineno.  */
306295011Sandrew  obj_aout_process_stab,
307295011Sandrew  obj_aout_separate_stab_sections,
308295011Sandrew  0,	/* init_stab_section.  */
309295011Sandrew  obj_aout_sec_sym_ok_for_reloc,
310295011Sandrew  aout_pop_insert,
311295011Sandrew  0,	/* ecoff_set_ext.  */
312295011Sandrew  0,	/* read_begin_hook.  */
313295011Sandrew  0 	/* symbol_new_hook.  */
314295011Sandrew};
315295011Sandrew
316295011Sandrewconst pseudo_typeS aout_pseudo_table[] =
317295011Sandrew{
318295011Sandrew  {"line", obj_aout_line, 0},	/* Source code line number.  */
319295011Sandrew  {"ln", obj_aout_line, 0},	/* COFF line number that we use anyway.  */
320295011Sandrew
321295011Sandrew  {"weak", obj_aout_weak, 0},	/* Mark symbol as weak.  */
322295011Sandrew
323295011Sandrew  {"type", obj_aout_type, 0},
324295011Sandrew
325295011Sandrew  /* coff debug pseudos (ignored) */
326295011Sandrew  {"def", s_ignore, 0},
327295011Sandrew  {"dim", s_ignore, 0},
328295011Sandrew  {"endef", s_ignore, 0},
329295011Sandrew  {"ident", s_ignore, 0},
330295011Sandrew  {"line", s_ignore, 0},
331295011Sandrew  {"ln", s_ignore, 0},
332295011Sandrew  {"scl", s_ignore, 0},
333295011Sandrew  {"size", s_ignore, 0},
334295011Sandrew  {"tag", s_ignore, 0},
335295011Sandrew  {"val", s_ignore, 0},
336295011Sandrew  {"version", s_ignore, 0},
337295011Sandrew
338295011Sandrew  {"optim", s_ignore, 0},	/* For sun386i cc (?).  */
339295011Sandrew
340295011Sandrew  /* other stuff */
341295011Sandrew  {"ABORT", s_abort, 0},
342295011Sandrew
343295011Sandrew  {NULL, NULL, 0}
344295011Sandrew};
345295011Sandrew