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