1/* a.out object file format
2   Copyright (C) 1989-2022 Free Software Foundation, Inc.
3
4   This file is part of GAS, the GNU Assembler.
5
6   GAS is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as
8   published by the Free Software Foundation; either version 3,
9   or (at your option) any later version.
10
11   GAS is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14   the GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with GAS; see the file COPYING.  If not, write to the Free
18   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19   02110-1301, USA.  */
20
21#define OBJ_HEADER "obj-aout.h"
22
23#include "as.h"
24#undef NO_RELOC
25#include "aout/aout64.h"
26
27void
28obj_aout_frob_symbol (symbolS *sym, int *punt ATTRIBUTE_UNUSED)
29{
30  flagword flags;
31  asection *sec;
32  int type;
33
34  flags = symbol_get_bfdsym (sym)->flags;
35  type = aout_symbol (symbol_get_bfdsym (sym))->type;
36  sec = S_GET_SEGMENT (sym);
37
38  /* Only frob simple symbols this way right now.  */
39  if (! (type & ~ (N_TYPE | N_EXT)))
40    {
41      if (type == (N_UNDF | N_EXT)
42	  && sec == bfd_abs_section_ptr)
43	{
44	  sec = bfd_und_section_ptr;
45	  S_SET_SEGMENT (sym, sec);
46	}
47
48      if ((type & N_TYPE) != N_INDR
49	  && (type & N_TYPE) != N_SETA
50	  && (type & N_TYPE) != N_SETT
51	  && (type & N_TYPE) != N_SETD
52	  && (type & N_TYPE) != N_SETB
53	  && type != N_WARNING
54	  && (sec == bfd_abs_section_ptr
55	      || sec == bfd_und_section_ptr))
56	return;
57      if (flags & BSF_EXPORT)
58	type |= N_EXT;
59
60      switch (type & N_TYPE)
61	{
62	case N_SETA:
63	case N_SETT:
64	case N_SETD:
65	case N_SETB:
66	  /* Set the debugging flag for constructor symbols so that
67	     BFD leaves them alone.  */
68	  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
69
70	  /* You can't put a common symbol in a set.  The way a set
71	     element works is that the symbol has a definition and a
72	     name, and the linker adds the definition to the set of
73	     that name.  That does not work for a common symbol,
74	     because the linker can't tell which common symbol the
75	     user means.  FIXME: Using as_bad here may be
76	     inappropriate, since the user may want to force a
77	     particular type without regard to the semantics of sets;
78	     on the other hand, we certainly don't want anybody to be
79	     mislead into thinking that their code will work.  */
80	  if (S_IS_COMMON (sym))
81	    as_bad (_("Attempt to put a common symbol into set %s"),
82		    S_GET_NAME (sym));
83	  /* Similarly, you can't put an undefined symbol in a set.  */
84	  else if (! S_IS_DEFINED (sym))
85	    as_bad (_("Attempt to put an undefined symbol into set %s"),
86		    S_GET_NAME (sym));
87
88	  break;
89	case N_INDR:
90	  /* Put indirect symbols in the indirect section.  */
91	  S_SET_SEGMENT (sym, bfd_ind_section_ptr);
92	  symbol_get_bfdsym (sym)->flags |= BSF_INDIRECT;
93	  if (type & N_EXT)
94	    {
95	      symbol_get_bfdsym (sym)->flags |= BSF_EXPORT;
96	      symbol_get_bfdsym (sym)->flags &=~ BSF_LOCAL;
97	    }
98	  break;
99	case N_WARNING:
100	  /* Mark warning symbols.  */
101	  symbol_get_bfdsym (sym)->flags |= BSF_WARNING;
102	  break;
103	}
104    }
105  else
106    symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
107
108  aout_symbol (symbol_get_bfdsym (sym))->type = type;
109
110  /* Double check weak symbols.  */
111  if (S_IS_WEAK (sym) && S_IS_COMMON (sym))
112    as_bad (_("Symbol `%s' can not be both weak and common"),
113	    S_GET_NAME (sym));
114}
115
116/* Relocation processing may require knowing the VMAs of the sections.
117   Writing to a section will cause the BFD back end to compute the
118   VMAs.  This function also ensures that file size is large enough
119   to cover a_text and a_data should text or data be the last section
120   in the file.  */
121
122void
123obj_aout_frob_file_before_fix (void)
124{
125  asection *sec;
126  bfd_vma *sizep = NULL;
127  if ((sec = data_section)->size != 0)
128    sizep = &exec_hdr (stdoutput)->a_data;
129  else if ((sec = text_section)->size != 0)
130    sizep = &exec_hdr (stdoutput)->a_text;
131  if (sizep)
132    {
133      bfd_size_type size = sec->size;
134      bfd_byte b = 0;
135
136      gas_assert (bfd_set_section_contents (stdoutput, sec, &b, size - 1, 1));
137
138      /* We don't know the aligned size until after VMAs and sizes are
139	 set on the bfd_set_section_contents call.  If that size is
140	 larger than the section then write again to ensure the file
141	 contents extend to cover the aligned size.  */
142      if (*sizep > size)
143	{
144	  file_ptr pos = sec->filepos + *sizep;
145
146	  gas_assert (bfd_seek (stdoutput, pos - 1, SEEK_SET) == 0
147		      && bfd_bwrite (&b, 1, stdoutput) == 1);
148	}
149    }
150}
151
152static void
153obj_aout_line (int ignore ATTRIBUTE_UNUSED)
154{
155  /* Assume delimiter is part of expression.
156     BSD4.2 as fails with delightful bug, so we
157     are not being incompatible here.  */
158  new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
159  demand_empty_rest_of_line ();
160}
161
162/* Handle .weak.  This is a GNU extension.  */
163
164static void
165obj_aout_weak (int ignore ATTRIBUTE_UNUSED)
166{
167  char *name;
168  int c;
169  symbolS *symbolP;
170
171  do
172    {
173      c = get_symbol_name (&name);
174      symbolP = symbol_find_or_make (name);
175      (void) restore_line_pointer (c);
176      SKIP_WHITESPACE ();
177      S_SET_WEAK (symbolP);
178      if (c == ',')
179	{
180	  input_line_pointer++;
181	  SKIP_WHITESPACE ();
182	  if (*input_line_pointer == '\n')
183	    c = '\n';
184	}
185    }
186  while (c == ',');
187  demand_empty_rest_of_line ();
188}
189
190/* Handle .type.  On {Net,Open}BSD, this is used to set the n_other field,
191   which is then apparently used when doing dynamic linking.  Older
192   versions of gas ignored the .type pseudo-op, so we also ignore it if
193   we can't parse it.  */
194
195static void
196obj_aout_type (int ignore ATTRIBUTE_UNUSED)
197{
198  char *name;
199  int c;
200  symbolS *sym;
201
202  c = get_symbol_name (&name);
203  sym = symbol_find_or_make (name);
204  (void) restore_line_pointer (c);
205  SKIP_WHITESPACE ();
206  if (*input_line_pointer == ',')
207    {
208      ++input_line_pointer;
209      SKIP_WHITESPACE ();
210      if (*input_line_pointer == '@')
211	{
212	  ++input_line_pointer;
213	  if (startswith (input_line_pointer, "object"))
214	    S_SET_OTHER (sym, 1);
215	  else if (startswith (input_line_pointer, "function"))
216	    S_SET_OTHER (sym, 2);
217	}
218    }
219
220  /* Ignore everything else on the line.  */
221  s_ignore (0);
222}
223
224/* Support for an AOUT emulation.  */
225
226static void
227aout_pop_insert (void)
228{
229  pop_insert (aout_pseudo_table);
230}
231
232static int
233obj_aout_s_get_other (symbolS *sym)
234{
235  return aout_symbol (symbol_get_bfdsym (sym))->other;
236}
237
238static void
239obj_aout_s_set_other (symbolS *sym, int o)
240{
241  aout_symbol (symbol_get_bfdsym (sym))->other = o;
242}
243
244static int
245obj_aout_sec_sym_ok_for_reloc (asection *sec ATTRIBUTE_UNUSED)
246{
247  return obj_sec_sym_ok_for_reloc (sec);
248}
249
250static void
251obj_aout_process_stab (segT seg ATTRIBUTE_UNUSED,
252		       int w,
253		       const char *s,
254		       int t,
255		       int o,
256		       int d)
257{
258  aout_process_stab (w, s, t, o, d);
259}
260
261static int
262obj_aout_s_get_desc (symbolS *sym)
263{
264  return aout_symbol (symbol_get_bfdsym (sym))->desc;
265}
266
267static void
268obj_aout_s_set_desc (symbolS *sym, int d)
269{
270  aout_symbol (symbol_get_bfdsym (sym))->desc = d;
271}
272
273static int
274obj_aout_s_get_type (symbolS *sym)
275{
276  return aout_symbol (symbol_get_bfdsym (sym))->type;
277}
278
279static void
280obj_aout_s_set_type (symbolS *sym, int t)
281{
282  aout_symbol (symbol_get_bfdsym (sym))->type = t;
283}
284
285static int
286obj_aout_separate_stab_sections (void)
287{
288  return 0;
289}
290
291/* When changed, make sure these table entries match the single-format
292   definitions in obj-aout.h.  */
293
294const struct format_ops aout_format_ops =
295{
296  bfd_target_aout_flavour,
297  1,	/* dfl_leading_underscore.  */
298  0,	/* emit_section_symbols.  */
299  0,	/* begin.  */
300  0,	/* app_file.  */
301  obj_aout_frob_symbol,
302  0,	/* frob_file.  */
303  0,	/* frob_file_before_adjust.  */
304  obj_aout_frob_file_before_fix,
305  0,	/* frob_file_after_relocs.  */
306  0,	/* s_get_size.  */
307  0,	/* s_set_size.  */
308  0,	/* s_get_align.  */
309  0,	/* s_set_align.  */
310  obj_aout_s_get_other,
311  obj_aout_s_set_other,
312  obj_aout_s_get_desc,
313  obj_aout_s_set_desc,
314  obj_aout_s_get_type,
315  obj_aout_s_set_type,
316  0,	/* copy_symbol_attributes.  */
317  0,	/* generate_asm_lineno.  */
318  obj_aout_process_stab,
319  obj_aout_separate_stab_sections,
320  0,	/* init_stab_section.  */
321  obj_aout_sec_sym_ok_for_reloc,
322  aout_pop_insert,
323  0,	/* ecoff_set_ext.  */
324  0,	/* read_begin_hook.  */
325  0,	/* symbol_new_hook.  */
326  0,	/* symbol_clone_hook.  */
327  0	/* adjust_symtab.  */
328};
329
330const pseudo_typeS aout_pseudo_table[] =
331{
332  {"line", obj_aout_line, 0},	/* Source code line number.  */
333  {"ln", obj_aout_line, 0},	/* COFF line number that we use anyway.  */
334
335  {"weak", obj_aout_weak, 0},	/* Mark symbol as weak.  */
336
337  {"type", obj_aout_type, 0},
338
339  /* coff debug pseudos (ignored) */
340  {"def", s_ignore, 0},
341  {"dim", s_ignore, 0},
342  {"endef", s_ignore, 0},
343  {"ident", s_ignore, 0},
344  {"line", s_ignore, 0},
345  {"ln", s_ignore, 0},
346  {"scl", s_ignore, 0},
347  {"size", s_ignore, 0},
348  {"tag", s_ignore, 0},
349  {"val", s_ignore, 0},
350  {"version", s_ignore, 0},
351
352  {"optim", s_ignore, 0},	/* For sun386i cc (?).  */
353
354  /* other stuff */
355  {"ABORT", s_abort, 0},
356
357  {NULL, NULL, 0}
358};
359