133965Sjdp/* a.out object file format 2130561Sobrien Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 3218822Sdim 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 433965Sjdp 5218822Sdim This file is part of GAS, the GNU Assembler. 633965Sjdp 7218822Sdim GAS is free software; you can redistribute it and/or modify 8218822Sdim it under the terms of the GNU General Public License as 9218822Sdim published by the Free Software Foundation; either version 2, 10218822Sdim or (at your option) any later version. 1133965Sjdp 12218822Sdim GAS is distributed in the hope that it will be useful, but 13218822Sdim WITHOUT ANY WARRANTY; without even the implied warranty of 14218822Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15218822Sdim the GNU General Public License for more details. 1633965Sjdp 17218822Sdim You should have received a copy of the GNU General Public License 18218822Sdim along with GAS; see the file COPYING. If not, write to the Free 19218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20218822Sdim 02110-1301, USA. */ 2133965Sjdp 2260484Sobrien#define OBJ_HEADER "obj-aout.h" 2360484Sobrien 2433965Sjdp#include "as.h" 2533965Sjdp#undef NO_RELOC 2633965Sjdp#include "aout/aout64.h" 2733965Sjdp#include "obstack.h" 2833965Sjdp 2933965Sjdpvoid 30218822Sdimobj_aout_frob_symbol (symbolS *sym, int *punt ATTRIBUTE_UNUSED) 3133965Sjdp{ 3233965Sjdp flagword flags; 3333965Sjdp asection *sec; 3433965Sjdp int desc, type, other; 3533965Sjdp 3660484Sobrien flags = symbol_get_bfdsym (sym)->flags; 3760484Sobrien desc = aout_symbol (symbol_get_bfdsym (sym))->desc; 3860484Sobrien type = aout_symbol (symbol_get_bfdsym (sym))->type; 3960484Sobrien other = aout_symbol (symbol_get_bfdsym (sym))->other; 4060484Sobrien sec = S_GET_SEGMENT (sym); 4133965Sjdp 4233965Sjdp /* Only frob simple symbols this way right now. */ 4333965Sjdp if (! (type & ~ (N_TYPE | N_EXT))) 4433965Sjdp { 4533965Sjdp if (type == (N_UNDF | N_EXT) 4633965Sjdp && sec == &bfd_abs_section) 4760484Sobrien { 4860484Sobrien sec = bfd_und_section_ptr; 4960484Sobrien S_SET_SEGMENT (sym, sec); 5060484Sobrien } 5133965Sjdp 5233965Sjdp if ((type & N_TYPE) != N_INDR 5333965Sjdp && (type & N_TYPE) != N_SETA 5433965Sjdp && (type & N_TYPE) != N_SETT 5533965Sjdp && (type & N_TYPE) != N_SETD 5633965Sjdp && (type & N_TYPE) != N_SETB 5733965Sjdp && type != N_WARNING 5833965Sjdp && (sec == &bfd_abs_section 5933965Sjdp || sec == &bfd_und_section)) 6033965Sjdp return; 6133965Sjdp if (flags & BSF_EXPORT) 6233965Sjdp type |= N_EXT; 6333965Sjdp 6433965Sjdp switch (type & N_TYPE) 6533965Sjdp { 6633965Sjdp case N_SETA: 6733965Sjdp case N_SETT: 6833965Sjdp case N_SETD: 6933965Sjdp case N_SETB: 7033965Sjdp /* Set the debugging flag for constructor symbols so that 7133965Sjdp BFD leaves them alone. */ 7260484Sobrien symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING; 7333965Sjdp 7433965Sjdp /* You can't put a common symbol in a set. The way a set 7533965Sjdp element works is that the symbol has a definition and a 7633965Sjdp name, and the linker adds the definition to the set of 7733965Sjdp that name. That does not work for a common symbol, 7833965Sjdp because the linker can't tell which common symbol the 7933965Sjdp user means. FIXME: Using as_bad here may be 8033965Sjdp inappropriate, since the user may want to force a 8133965Sjdp particular type without regard to the semantics of sets; 8233965Sjdp on the other hand, we certainly don't want anybody to be 8333965Sjdp mislead into thinking that their code will work. */ 8433965Sjdp if (S_IS_COMMON (sym)) 8560484Sobrien as_bad (_("Attempt to put a common symbol into set %s"), 8633965Sjdp S_GET_NAME (sym)); 8733965Sjdp /* Similarly, you can't put an undefined symbol in a set. */ 8833965Sjdp else if (! S_IS_DEFINED (sym)) 8960484Sobrien as_bad (_("Attempt to put an undefined symbol into set %s"), 9033965Sjdp S_GET_NAME (sym)); 9133965Sjdp 9233965Sjdp break; 9333965Sjdp case N_INDR: 9433965Sjdp /* Put indirect symbols in the indirect section. */ 9560484Sobrien S_SET_SEGMENT (sym, bfd_ind_section_ptr); 9660484Sobrien symbol_get_bfdsym (sym)->flags |= BSF_INDIRECT; 9733965Sjdp if (type & N_EXT) 9833965Sjdp { 9960484Sobrien symbol_get_bfdsym (sym)->flags |= BSF_EXPORT; 10060484Sobrien symbol_get_bfdsym (sym)->flags &=~ BSF_LOCAL; 10133965Sjdp } 10233965Sjdp break; 10333965Sjdp case N_WARNING: 10433965Sjdp /* Mark warning symbols. */ 10560484Sobrien symbol_get_bfdsym (sym)->flags |= BSF_WARNING; 10633965Sjdp break; 10733965Sjdp } 10833965Sjdp } 10933965Sjdp else 110218822Sdim symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING; 11133965Sjdp 11260484Sobrien aout_symbol (symbol_get_bfdsym (sym))->type = type; 11333965Sjdp 11433965Sjdp /* Double check weak symbols. */ 115218822Sdim if (S_IS_WEAK (sym) && S_IS_COMMON (sym)) 116218822Sdim as_bad (_("Symbol `%s' can not be both weak and common"), 117218822Sdim S_GET_NAME (sym)); 11833965Sjdp} 11933965Sjdp 12033965Sjdpvoid 121218822Sdimobj_aout_frob_file_before_fix (void) 12233965Sjdp{ 12333965Sjdp /* Relocation processing may require knowing the VMAs of the sections. 12433965Sjdp Since writing to a section will cause the BFD back end to compute the 12533965Sjdp VMAs, fake it out here.... */ 12633965Sjdp bfd_byte b = 0; 127130561Sobrien bfd_boolean x = TRUE; 12833965Sjdp if (bfd_section_size (stdoutput, text_section) != 0) 129218822Sdim x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0, 130218822Sdim (bfd_size_type) 1); 13133965Sjdp else if (bfd_section_size (stdoutput, data_section) != 0) 132218822Sdim x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0, 133218822Sdim (bfd_size_type) 1); 134218822Sdim 135130561Sobrien assert (x); 13633965Sjdp} 13733965Sjdp 13833965Sjdpstatic void 139218822Sdimobj_aout_line (int ignore ATTRIBUTE_UNUSED) 14033965Sjdp{ 14133965Sjdp /* Assume delimiter is part of expression. 14233965Sjdp BSD4.2 as fails with delightful bug, so we 14377298Sobrien are not being incompatible here. */ 14433965Sjdp new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); 14533965Sjdp demand_empty_rest_of_line (); 146218822Sdim} 14733965Sjdp 14833965Sjdp/* Handle .weak. This is a GNU extension. */ 14933965Sjdp 15033965Sjdpstatic void 151218822Sdimobj_aout_weak (int ignore ATTRIBUTE_UNUSED) 15233965Sjdp{ 15333965Sjdp char *name; 15433965Sjdp int c; 15533965Sjdp symbolS *symbolP; 15633965Sjdp 15733965Sjdp do 15833965Sjdp { 15933965Sjdp name = input_line_pointer; 16033965Sjdp c = get_symbol_end (); 16133965Sjdp symbolP = symbol_find_or_make (name); 16233965Sjdp *input_line_pointer = c; 16333965Sjdp SKIP_WHITESPACE (); 16433965Sjdp S_SET_WEAK (symbolP); 16533965Sjdp if (c == ',') 16633965Sjdp { 16733965Sjdp input_line_pointer++; 16833965Sjdp SKIP_WHITESPACE (); 16933965Sjdp if (*input_line_pointer == '\n') 17033965Sjdp c = '\n'; 17133965Sjdp } 17233965Sjdp } 17333965Sjdp while (c == ','); 17433965Sjdp demand_empty_rest_of_line (); 17533965Sjdp} 17633965Sjdp 17733965Sjdp/* Handle .type. On {Net,Open}BSD, this is used to set the n_other field, 17833965Sjdp which is then apparently used when doing dynamic linking. Older 17977298Sobrien versions of gas ignored the .type pseudo-op, so we also ignore it if 18033965Sjdp we can't parse it. */ 18133965Sjdp 18233965Sjdpstatic void 183218822Sdimobj_aout_type (int ignore ATTRIBUTE_UNUSED) 18433965Sjdp{ 18533965Sjdp char *name; 18633965Sjdp int c; 18733965Sjdp symbolS *sym; 18833965Sjdp 18933965Sjdp name = input_line_pointer; 19033965Sjdp c = get_symbol_end (); 19177298Sobrien sym = symbol_find_or_make (name); 19233965Sjdp *input_line_pointer = c; 19377298Sobrien SKIP_WHITESPACE (); 19477298Sobrien if (*input_line_pointer == ',') 19533965Sjdp { 19677298Sobrien ++input_line_pointer; 19733965Sjdp SKIP_WHITESPACE (); 19877298Sobrien if (*input_line_pointer == '@') 19933965Sjdp { 20033965Sjdp ++input_line_pointer; 20177298Sobrien if (strncmp (input_line_pointer, "object", 6) == 0) 202218822Sdim S_SET_OTHER (sym, 1); 20377298Sobrien else if (strncmp (input_line_pointer, "function", 8) == 0) 204218822Sdim S_SET_OTHER (sym, 2); 20533965Sjdp } 20633965Sjdp } 20733965Sjdp 20833965Sjdp /* Ignore everything else on the line. */ 20933965Sjdp s_ignore (0); 21033965Sjdp} 21133965Sjdp 21260484Sobrien/* Support for an AOUT emulation. */ 21360484Sobrien 21460484Sobrienstatic void 215218822Sdimaout_pop_insert (void) 21660484Sobrien{ 21760484Sobrien pop_insert (aout_pseudo_table); 21860484Sobrien} 21960484Sobrien 22060484Sobrienstatic int 221218822Sdimobj_aout_s_get_other (symbolS *sym) 22260484Sobrien{ 22360484Sobrien return aout_symbol (symbol_get_bfdsym (sym))->other; 22460484Sobrien} 22560484Sobrien 22677298Sobrienstatic void 227218822Sdimobj_aout_s_set_other (symbolS *sym, int o) 22877298Sobrien{ 22977298Sobrien aout_symbol (symbol_get_bfdsym (sym))->other = o; 23077298Sobrien} 23177298Sobrien 23260484Sobrienstatic int 233218822Sdimobj_aout_sec_sym_ok_for_reloc (asection *sec ATTRIBUTE_UNUSED) 23477298Sobrien{ 23577298Sobrien return obj_sec_sym_ok_for_reloc (sec); 23677298Sobrien} 23777298Sobrien 23877298Sobrienstatic void 239218822Sdimobj_aout_process_stab (segT seg ATTRIBUTE_UNUSED, 240218822Sdim int w, 241218822Sdim const char *s, 242218822Sdim int t, 243218822Sdim int o, 244218822Sdim int d) 24577298Sobrien{ 24677298Sobrien aout_process_stab (w, s, t, o, d); 24777298Sobrien} 24877298Sobrien 24977298Sobrienstatic int 250218822Sdimobj_aout_s_get_desc (symbolS *sym) 25160484Sobrien{ 25260484Sobrien return aout_symbol (symbol_get_bfdsym (sym))->desc; 25360484Sobrien} 25460484Sobrien 25577298Sobrienstatic void 256218822Sdimobj_aout_s_set_desc (symbolS *sym, int d) 25777298Sobrien{ 25877298Sobrien aout_symbol (symbol_get_bfdsym (sym))->desc = d; 25977298Sobrien} 26060484Sobrien 26177298Sobrienstatic int 262218822Sdimobj_aout_s_get_type (symbolS *sym) 26377298Sobrien{ 26477298Sobrien return aout_symbol (symbol_get_bfdsym (sym))->type; 26577298Sobrien} 26677298Sobrien 26777298Sobrienstatic void 268218822Sdimobj_aout_s_set_type (symbolS *sym, int t) 26977298Sobrien{ 27077298Sobrien aout_symbol (symbol_get_bfdsym (sym))->type = t; 27177298Sobrien} 27277298Sobrien 27377298Sobrienstatic int 274218822Sdimobj_aout_separate_stab_sections (void) 27577298Sobrien{ 27677298Sobrien return 0; 27777298Sobrien} 27877298Sobrien 27977298Sobrien/* When changed, make sure these table entries match the single-format 28077298Sobrien definitions in obj-aout.h. */ 281218822Sdim 28260484Sobrienconst struct format_ops aout_format_ops = 28360484Sobrien{ 28460484Sobrien bfd_target_aout_flavour, 285218822Sdim 1, /* dfl_leading_underscore. */ 286218822Sdim 0, /* emit_section_symbols. */ 287218822Sdim 0, /* begin. */ 288218822Sdim 0, /* app_file. */ 28960484Sobrien obj_aout_frob_symbol, 290218822Sdim 0, /* frob_file. */ 291218822Sdim 0, /* frob_file_before_adjust. */ 292130561Sobrien obj_aout_frob_file_before_fix, 293218822Sdim 0, /* frob_file_after_relocs. */ 294218822Sdim 0, /* s_get_size. */ 295218822Sdim 0, /* s_set_size. */ 296218822Sdim 0, /* s_get_align. */ 297218822Sdim 0, /* s_set_align. */ 29860484Sobrien obj_aout_s_get_other, 29977298Sobrien obj_aout_s_set_other, 30060484Sobrien obj_aout_s_get_desc, 30177298Sobrien obj_aout_s_set_desc, 30277298Sobrien obj_aout_s_get_type, 30377298Sobrien obj_aout_s_set_type, 304218822Sdim 0, /* copy_symbol_attributes. */ 305218822Sdim 0, /* generate_asm_lineno. */ 30677298Sobrien obj_aout_process_stab, 30777298Sobrien obj_aout_separate_stab_sections, 308218822Sdim 0, /* init_stab_section. */ 30977298Sobrien obj_aout_sec_sym_ok_for_reloc, 31060484Sobrien aout_pop_insert, 311218822Sdim 0, /* ecoff_set_ext. */ 312218822Sdim 0, /* read_begin_hook. */ 313218822Sdim 0 /* symbol_new_hook. */ 31460484Sobrien}; 315218822Sdim 316218822Sdimconst pseudo_typeS aout_pseudo_table[] = 317218822Sdim{ 318218822Sdim {"line", obj_aout_line, 0}, /* Source code line number. */ 319218822Sdim {"ln", obj_aout_line, 0}, /* COFF line number that we use anyway. */ 320218822Sdim 321218822Sdim {"weak", obj_aout_weak, 0}, /* Mark symbol as weak. */ 322218822Sdim 323218822Sdim {"type", obj_aout_type, 0}, 324218822Sdim 325218822Sdim /* coff debug pseudos (ignored) */ 326218822Sdim {"def", s_ignore, 0}, 327218822Sdim {"dim", s_ignore, 0}, 328218822Sdim {"endef", s_ignore, 0}, 329218822Sdim {"ident", s_ignore, 0}, 330218822Sdim {"line", s_ignore, 0}, 331218822Sdim {"ln", s_ignore, 0}, 332218822Sdim {"scl", s_ignore, 0}, 333218822Sdim {"size", s_ignore, 0}, 334218822Sdim {"tag", s_ignore, 0}, 335218822Sdim {"val", s_ignore, 0}, 336218822Sdim {"version", s_ignore, 0}, 337218822Sdim 338218822Sdim {"optim", s_ignore, 0}, /* For sun386i cc (?). */ 339218822Sdim 340218822Sdim /* other stuff */ 341218822Sdim {"ABORT", s_abort, 0}, 342218822Sdim 343218822Sdim {NULL, NULL, 0} 344218822Sdim}; 345