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