2005-04-12 Paul Brook <paul@codesourcery.com>
[binutils.git] / gas / config / obj-aout.c
blob720d09c6c2d5682c0962a200f156b6f2dbbca153
1 /* a.out object file format
2 Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2,
10 or (at your option) any later version.
12 GAS is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
22 #define OBJ_HEADER "obj-aout.h"
24 #include "as.h"
25 #ifdef BFD_ASSEMBLER
26 #undef NO_RELOC
27 #include "aout/aout64.h"
28 #endif
29 #include "obstack.h"
31 #ifndef BFD_ASSEMBLER
32 /* in: segT out: N_TYPE bits. */
33 const short seg_N_TYPE[] =
35 N_ABS,
36 N_TEXT,
37 N_DATA,
38 N_BSS,
39 N_UNDF, /* Unknown. */
40 N_UNDF, /* Error. */
41 N_UNDF, /* Expression. */
42 N_UNDF, /* Debug. */
43 N_UNDF, /* Ntv. */
44 N_UNDF, /* Ptv. */
45 N_REGISTER, /* Register. */
48 const segT N_TYPE_seg[N_TYPE + 2] =
49 { /* N_TYPE == 0x1E = 32-2 */
50 SEG_UNKNOWN, /* N_UNDF == 0 */
51 SEG_GOOF,
52 SEG_ABSOLUTE, /* N_ABS == 2 */
53 SEG_GOOF,
54 SEG_TEXT, /* N_TEXT == 4 */
55 SEG_GOOF,
56 SEG_DATA, /* N_DATA == 6 */
57 SEG_GOOF,
58 SEG_BSS, /* N_BSS == 8 */
59 SEG_GOOF,
60 SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
61 SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
62 SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
63 SEG_REGISTER, /* Dummy N_REGISTER for regs = 30. */
64 SEG_GOOF,
66 #endif
68 #ifdef BFD_ASSEMBLER
70 void
71 obj_aout_frob_symbol (symbolS *sym, int *punt ATTRIBUTE_UNUSED)
73 flagword flags;
74 asection *sec;
75 int desc, type, other;
77 flags = symbol_get_bfdsym (sym)->flags;
78 desc = aout_symbol (symbol_get_bfdsym (sym))->desc;
79 type = aout_symbol (symbol_get_bfdsym (sym))->type;
80 other = aout_symbol (symbol_get_bfdsym (sym))->other;
81 sec = S_GET_SEGMENT (sym);
83 /* Only frob simple symbols this way right now. */
84 if (! (type & ~ (N_TYPE | N_EXT)))
86 if (type == (N_UNDF | N_EXT)
87 && sec == &bfd_abs_section)
89 sec = bfd_und_section_ptr;
90 S_SET_SEGMENT (sym, sec);
93 if ((type & N_TYPE) != N_INDR
94 && (type & N_TYPE) != N_SETA
95 && (type & N_TYPE) != N_SETT
96 && (type & N_TYPE) != N_SETD
97 && (type & N_TYPE) != N_SETB
98 && type != N_WARNING
99 && (sec == &bfd_abs_section
100 || sec == &bfd_und_section))
101 return;
102 if (flags & BSF_EXPORT)
103 type |= N_EXT;
105 switch (type & N_TYPE)
107 case N_SETA:
108 case N_SETT:
109 case N_SETD:
110 case N_SETB:
111 /* Set the debugging flag for constructor symbols so that
112 BFD leaves them alone. */
113 symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
115 /* You can't put a common symbol in a set. The way a set
116 element works is that the symbol has a definition and a
117 name, and the linker adds the definition to the set of
118 that name. That does not work for a common symbol,
119 because the linker can't tell which common symbol the
120 user means. FIXME: Using as_bad here may be
121 inappropriate, since the user may want to force a
122 particular type without regard to the semantics of sets;
123 on the other hand, we certainly don't want anybody to be
124 mislead into thinking that their code will work. */
125 if (S_IS_COMMON (sym))
126 as_bad (_("Attempt to put a common symbol into set %s"),
127 S_GET_NAME (sym));
128 /* Similarly, you can't put an undefined symbol in a set. */
129 else if (! S_IS_DEFINED (sym))
130 as_bad (_("Attempt to put an undefined symbol into set %s"),
131 S_GET_NAME (sym));
133 break;
134 case N_INDR:
135 /* Put indirect symbols in the indirect section. */
136 S_SET_SEGMENT (sym, bfd_ind_section_ptr);
137 symbol_get_bfdsym (sym)->flags |= BSF_INDIRECT;
138 if (type & N_EXT)
140 symbol_get_bfdsym (sym)->flags |= BSF_EXPORT;
141 symbol_get_bfdsym (sym)->flags &=~ BSF_LOCAL;
143 break;
144 case N_WARNING:
145 /* Mark warning symbols. */
146 symbol_get_bfdsym (sym)->flags |= BSF_WARNING;
147 break;
150 else
151 symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
153 aout_symbol (symbol_get_bfdsym (sym))->type = type;
155 /* Double check weak symbols. */
156 if (S_IS_WEAK (sym) && S_IS_COMMON (sym))
157 as_bad (_("Symbol `%s' can not be both weak and common"),
158 S_GET_NAME (sym));
161 void
162 obj_aout_frob_file_before_fix (void)
164 /* Relocation processing may require knowing the VMAs of the sections.
165 Since writing to a section will cause the BFD back end to compute the
166 VMAs, fake it out here.... */
167 bfd_byte b = 0;
168 bfd_boolean x = TRUE;
169 if (bfd_section_size (stdoutput, text_section) != 0)
170 x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0,
171 (bfd_size_type) 1);
172 else if (bfd_section_size (stdoutput, data_section) != 0)
173 x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0,
174 (bfd_size_type) 1);
176 assert (x);
179 #else /* ! BFD_ASSEMBLER */
181 /* Relocation. */
183 /** Crawl along a fixS chain. Emit the segment's relocations. */
185 void
186 obj_emit_relocations (char **where,
187 fixS *fixP, /* Fixup chain for this segment. */
188 relax_addressT segment_address_in_file)
190 for (; fixP; fixP = fixP->fx_next)
191 if (fixP->fx_done == 0)
193 symbolS *sym;
195 sym = fixP->fx_addsy;
196 while (sym->sy_value.X_op == O_symbol
197 && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
198 sym = sym->sy_value.X_add_symbol;
199 fixP->fx_addsy = sym;
201 if (! sym->sy_resolved && ! S_IS_DEFINED (sym))
203 char *file;
204 unsigned int line;
206 if (expr_symbol_where (sym, &file, &line))
207 as_bad_where (file, line, _("unresolved relocation"));
208 else
209 as_bad (_("bad relocation: symbol `%s' not in symbol table"),
210 S_GET_NAME (sym));
213 tc_aout_fix_to_chars (*where, fixP, segment_address_in_file);
214 *where += md_reloc_size;
218 #ifndef obj_header_append
219 /* Aout file generation & utilities. */
221 /* An AOUT header on disk is laid out in target byte order. */
223 void
224 obj_header_append (char **where, object_headers *headers)
226 char *p;
228 tc_headers_hook (headers);
230 #ifdef __A_OUT_GNU_H__
231 #define SIZEOF_HEADER(PIECE) (sizeof (((struct exec_bytes *) 0)->PIECE))
232 #else
233 #define SIZEOF_HEADER(PIECE) 4
234 #endif
235 #define DO(PIECE) \
236 md_number_to_chars (p, headers->header.PIECE, SIZEOF_HEADER (PIECE)); \
237 p += SIZEOF_HEADER (PIECE);
239 p = *where;
240 DO (a_info);
241 DO (a_text);
242 DO (a_data);
243 DO (a_bss);
244 DO (a_syms);
245 DO (a_entry);
246 DO (a_trsize);
247 DO (a_drsize);
248 *where = p;
249 #undef DO
250 #undef SIZEOF_HEADER
252 #endif /* ! defined (obj_header_append) */
254 void
255 obj_symbol_to_chars (char **where, symbolS *symbolP)
257 char *p = *where;
258 md_number_to_chars (p, S_GET_OFFSET (symbolP), 4);
259 p += 4;
260 /* Can't use S_GET_TYPE here as it masks. */
261 *p++ = symbolP->sy_symbol.n_type;
262 *p++ = symbolP->sy_symbol.n_other;
263 md_number_to_chars (p, S_GET_DESC (symbolP), 2);
264 p += 2;
265 md_number_to_chars (p, S_GET_VALUE (symbolP), 4);
266 p += 4;
267 *where = p;
270 void
271 obj_emit_symbols (char **where, symbolS *symbol_rootP)
273 symbolS *symbolP;
275 /* Emit all symbols left in the symbol chain. */
276 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
278 /* Used to save the offset of the name. It is used to point
279 to the string in memory but must be a file offset. */
280 char *temp;
282 temp = S_GET_NAME (symbolP);
283 S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
285 /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
286 if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
287 S_SET_EXTERNAL (symbolP);
289 /* Adjust the type of a weak symbol. */
290 if (S_GET_WEAK (symbolP))
292 switch (S_GET_TYPE (symbolP))
294 case N_UNDF: S_SET_TYPE (symbolP, N_WEAKU); break;
295 case N_ABS: S_SET_TYPE (symbolP, N_WEAKA); break;
296 case N_TEXT: S_SET_TYPE (symbolP, N_WEAKT); break;
297 case N_DATA: S_SET_TYPE (symbolP, N_WEAKD); break;
298 case N_BSS: S_SET_TYPE (symbolP, N_WEAKB); break;
299 default: as_bad (_("%s: bad type for weak symbol"), temp); break;
303 obj_symbol_to_chars (where, symbolP);
304 S_SET_NAME (symbolP, temp);
308 #endif /* ! BFD_ASSEMBLER */
310 static void
311 obj_aout_line (int ignore ATTRIBUTE_UNUSED)
313 /* Assume delimiter is part of expression.
314 BSD4.2 as fails with delightful bug, so we
315 are not being incompatible here. */
316 new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
317 demand_empty_rest_of_line ();
320 /* Handle .weak. This is a GNU extension. */
322 static void
323 obj_aout_weak (int ignore ATTRIBUTE_UNUSED)
325 char *name;
326 int c;
327 symbolS *symbolP;
331 name = input_line_pointer;
332 c = get_symbol_end ();
333 symbolP = symbol_find_or_make (name);
334 *input_line_pointer = c;
335 SKIP_WHITESPACE ();
336 S_SET_WEAK (symbolP);
337 if (c == ',')
339 input_line_pointer++;
340 SKIP_WHITESPACE ();
341 if (*input_line_pointer == '\n')
342 c = '\n';
345 while (c == ',');
346 demand_empty_rest_of_line ();
349 /* Handle .type. On {Net,Open}BSD, this is used to set the n_other field,
350 which is then apparently used when doing dynamic linking. Older
351 versions of gas ignored the .type pseudo-op, so we also ignore it if
352 we can't parse it. */
354 static void
355 obj_aout_type (int ignore ATTRIBUTE_UNUSED)
357 char *name;
358 int c;
359 symbolS *sym;
361 name = input_line_pointer;
362 c = get_symbol_end ();
363 sym = symbol_find_or_make (name);
364 *input_line_pointer = c;
365 SKIP_WHITESPACE ();
366 if (*input_line_pointer == ',')
368 ++input_line_pointer;
369 SKIP_WHITESPACE ();
370 if (*input_line_pointer == '@')
372 ++input_line_pointer;
373 if (strncmp (input_line_pointer, "object", 6) == 0)
374 S_SET_OTHER (sym, 1);
375 else if (strncmp (input_line_pointer, "function", 8) == 0)
376 S_SET_OTHER (sym, 2);
380 /* Ignore everything else on the line. */
381 s_ignore (0);
384 #ifndef BFD_ASSEMBLER
386 void
387 obj_crawl_symbol_chain (object_headers *headers)
389 symbolS *symbolP;
390 symbolS **symbolPP;
391 int symbol_number = 0;
393 tc_crawl_symbol_chain (headers);
395 symbolPP = &symbol_rootP; /*->last symbol chain link. */
396 while ((symbolP = *symbolPP) != NULL)
398 if (symbolP->sy_mri_common)
400 if (S_IS_EXTERNAL (symbolP))
401 as_bad (_("%s: global symbols not supported in common sections"),
402 S_GET_NAME (symbolP));
403 *symbolPP = symbol_next (symbolP);
404 continue;
407 if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA))
409 S_SET_SEGMENT (symbolP, SEG_TEXT);
412 resolve_symbol_value (symbolP);
414 /* Skip symbols which were equated to undefined or common
415 symbols. Also skip defined uncommon symbols which can
416 be resolved since in this case they should have been
417 resolved to a non-symbolic constant. */
418 if (symbolP->sy_value.X_op == O_symbol
419 && (! S_IS_DEFINED (symbolP)
420 || S_IS_COMMON (symbolP)
421 || symbol_resolved_p (symbolP)))
423 *symbolPP = symbol_next (symbolP);
424 continue;
427 /* OK, here is how we decide which symbols go out into the brave
428 new symtab. Symbols that do are:
430 * symbols with no name (stabd's?)
431 * symbols with debug info in their N_TYPE
433 Symbols that don't are:
434 * symbols that are registers
435 * symbols with \1 as their 3rd character (numeric labels)
436 * "local labels" as defined by S_LOCAL_NAME(name) if the -L
437 switch was passed to gas.
439 All other symbols are output. We complain if a deleted
440 symbol was marked external. */
442 if (!S_IS_REGISTER (symbolP)
443 && (!S_GET_NAME (symbolP)
444 || S_IS_DEBUG (symbolP)
445 || !S_IS_DEFINED (symbolP)
446 || S_IS_EXTERNAL (symbolP)
447 || (S_GET_NAME (symbolP)[0] != '\001'
448 && (flag_keep_locals || !S_LOCAL_NAME (symbolP)))))
450 symbolP->sy_number = symbol_number++;
452 /* The + 1 after strlen account for the \0 at the
453 end of each string */
454 if (!S_IS_STABD (symbolP))
456 /* Ordinary case. */
457 symbolP->sy_name_offset = string_byte_count;
458 string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
460 else /* .Stabd case. */
461 symbolP->sy_name_offset = 0;
462 symbolPP = &symbolP->sy_next;
464 else
466 if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
467 /* This warning should never get triggered any more.
468 Well, maybe if you're doing twisted things with
469 register names... */
470 as_bad (_("Local symbol %s never defined."),
471 decode_local_label_name (S_GET_NAME (symbolP)));
473 /* Unhook it from the chain */
474 *symbolPP = symbol_next (symbolP);
478 H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
481 /* Find strings by crawling along symbol table chain. */
483 void
484 obj_emit_strings (char **where)
486 symbolS *symbolP;
488 md_number_to_chars (*where, string_byte_count, 4);
489 *where += 4;
491 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
492 if (S_GET_NAME (symbolP))
493 append (where, S_GET_NAME (symbolP),
494 (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
497 #ifndef AOUT_VERSION
498 #define AOUT_VERSION 0
499 #endif
501 void
502 obj_pre_write_hook (object_headers *headers)
504 H_SET_DYNAMIC (headers, 0);
505 H_SET_VERSION (headers, AOUT_VERSION);
506 H_SET_MACHTYPE (headers, AOUT_MACHTYPE);
507 tc_aout_pre_write_hook (headers);
510 #endif /* ! BFD_ASSEMBLER */
512 #ifdef BFD_ASSEMBLER
514 /* Support for an AOUT emulation. */
516 static void
517 aout_pop_insert (void)
519 pop_insert (aout_pseudo_table);
522 static int
523 obj_aout_s_get_other (symbolS *sym)
525 return aout_symbol (symbol_get_bfdsym (sym))->other;
528 static void
529 obj_aout_s_set_other (symbolS *sym, int o)
531 aout_symbol (symbol_get_bfdsym (sym))->other = o;
534 static int
535 obj_aout_sec_sym_ok_for_reloc (asection *sec ATTRIBUTE_UNUSED)
537 return obj_sec_sym_ok_for_reloc (sec);
540 static void
541 obj_aout_process_stab (segT seg ATTRIBUTE_UNUSED,
542 int w,
543 const char *s,
544 int t,
545 int o,
546 int d)
548 aout_process_stab (w, s, t, o, d);
551 static int
552 obj_aout_s_get_desc (symbolS *sym)
554 return aout_symbol (symbol_get_bfdsym (sym))->desc;
557 static void
558 obj_aout_s_set_desc (symbolS *sym, int d)
560 aout_symbol (symbol_get_bfdsym (sym))->desc = d;
563 static int
564 obj_aout_s_get_type (symbolS *sym)
566 return aout_symbol (symbol_get_bfdsym (sym))->type;
569 static void
570 obj_aout_s_set_type (symbolS *sym, int t)
572 aout_symbol (symbol_get_bfdsym (sym))->type = t;
575 static int
576 obj_aout_separate_stab_sections (void)
578 return 0;
581 /* When changed, make sure these table entries match the single-format
582 definitions in obj-aout.h. */
584 const struct format_ops aout_format_ops =
586 bfd_target_aout_flavour,
587 1, /* dfl_leading_underscore. */
588 0, /* emit_section_symbols. */
589 0, /* begin. */
590 0, /* app_file. */
591 obj_aout_frob_symbol,
592 0, /* frob_file. */
593 0, /* frob_file_before_adjust. */
594 obj_aout_frob_file_before_fix,
595 0, /* frob_file_after_relocs. */
596 0, /* s_get_size. */
597 0, /* s_set_size. */
598 0, /* s_get_align. */
599 0, /* s_set_align. */
600 obj_aout_s_get_other,
601 obj_aout_s_set_other,
602 obj_aout_s_get_desc,
603 obj_aout_s_set_desc,
604 obj_aout_s_get_type,
605 obj_aout_s_set_type,
606 0, /* copy_symbol_attributes. */
607 0, /* generate_asm_lineno. */
608 obj_aout_process_stab,
609 obj_aout_separate_stab_sections,
610 0, /* init_stab_section. */
611 obj_aout_sec_sym_ok_for_reloc,
612 aout_pop_insert,
613 0, /* ecoff_set_ext. */
614 0, /* read_begin_hook. */
615 0 /* symbol_new_hook. */
617 #endif /* BFD_ASSEMBLER */
619 const pseudo_typeS aout_pseudo_table[] =
621 {"line", obj_aout_line, 0}, /* Source code line number. */
622 {"ln", obj_aout_line, 0}, /* COFF line number that we use anyway. */
624 {"weak", obj_aout_weak, 0}, /* Mark symbol as weak. */
626 {"type", obj_aout_type, 0},
628 /* coff debug pseudos (ignored) */
629 {"def", s_ignore, 0},
630 {"dim", s_ignore, 0},
631 {"endef", s_ignore, 0},
632 {"ident", s_ignore, 0},
633 {"line", s_ignore, 0},
634 {"ln", s_ignore, 0},
635 {"scl", s_ignore, 0},
636 {"size", s_ignore, 0},
637 {"tag", s_ignore, 0},
638 {"val", s_ignore, 0},
639 {"version", s_ignore, 0},
641 {"optim", s_ignore, 0}, /* For sun386i cc (?). */
643 /* other stuff */
644 {"ABORT", s_abort, 0},
646 {NULL, NULL, 0}