obj-aout.c revision 256281
1295011Sandrew/* a.out object file format 2295011Sandrew Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 3295011Sandrew 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 4295011Sandrew 5295011Sandrew This file is part of GAS, the GNU Assembler. 6295011Sandrew 7295011Sandrew GAS is free software; you can redistribute it and/or modify 8295011Sandrew it under the terms of the GNU General Public License as 9295011Sandrew published by the Free Software Foundation; either version 2, 10295011Sandrew or (at your option) any later version. 11295011Sandrew 12295011Sandrew GAS is distributed in the hope that it will be useful, but 13295011Sandrew WITHOUT ANY WARRANTY; without even the implied warranty of 14295011Sandrew MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15295011Sandrew the GNU General Public License for more details. 16295011Sandrew 17295011Sandrew You should have received a copy of the GNU General Public License 18295011Sandrew along with GAS; see the file COPYING. If not, write to the Free 19295011Sandrew Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20295011Sandrew 02110-1301, USA. */ 21295011Sandrew 22295011Sandrew#define OBJ_HEADER "obj-aout.h" 23295011Sandrew 24295011Sandrew#include "as.h" 25295011Sandrew#undef NO_RELOC 26295011Sandrew#include "aout/aout64.h" 27295011Sandrew#include "obstack.h" 28295011Sandrew 29295011Sandrewvoid 30295011Sandrewobj_aout_frob_symbol (symbolS *sym, int *punt ATTRIBUTE_UNUSED) 31295011Sandrew{ 32295011Sandrew flagword flags; 33295011Sandrew asection *sec; 34295011Sandrew int desc, type, other; 35295011Sandrew 36295011Sandrew flags = symbol_get_bfdsym (sym)->flags; 37295011Sandrew desc = aout_symbol (symbol_get_bfdsym (sym))->desc; 38295011Sandrew type = aout_symbol (symbol_get_bfdsym (sym))->type; 39295011Sandrew other = aout_symbol (symbol_get_bfdsym (sym))->other; 40295011Sandrew sec = S_GET_SEGMENT (sym); 41295011Sandrew 42295011Sandrew /* Only frob simple symbols this way right now. */ 43295011Sandrew if (! (type & ~ (N_TYPE | N_EXT))) 44295011Sandrew { 45295011Sandrew if (type == (N_UNDF | N_EXT) 46295011Sandrew && sec == &bfd_abs_section) 47295011Sandrew { 48295011Sandrew sec = bfd_und_section_ptr; 49295011Sandrew S_SET_SEGMENT (sym, sec); 50295011Sandrew } 51295011Sandrew 52295011Sandrew if ((type & N_TYPE) != N_INDR 53295011Sandrew && (type & N_TYPE) != N_SETA 54295011Sandrew && (type & N_TYPE) != N_SETT 55295011Sandrew && (type & N_TYPE) != N_SETD 56295011Sandrew && (type & N_TYPE) != N_SETB 57295011Sandrew && type != N_WARNING 58295011Sandrew && (sec == &bfd_abs_section 59295011Sandrew || sec == &bfd_und_section)) 60295011Sandrew return; 61295011Sandrew if (flags & BSF_EXPORT) 62295011Sandrew type |= N_EXT; 63295011Sandrew 64295011Sandrew switch (type & N_TYPE) 65295011Sandrew { 66295011Sandrew case N_SETA: 67295011Sandrew case N_SETT: 68295011Sandrew case N_SETD: 69295011Sandrew case N_SETB: 70295011Sandrew /* Set the debugging flag for constructor symbols so that 71295011Sandrew BFD leaves them alone. */ 72295011Sandrew symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING; 73295011Sandrew 74295011Sandrew /* You can't put a common symbol in a set. The way a set 75295011Sandrew element works is that the symbol has a definition and a 76295011Sandrew name, and the linker adds the definition to the set of 77295011Sandrew that name. That does not work for a common symbol, 78295011Sandrew because the linker can't tell which common symbol the 79295011Sandrew user means. FIXME: Using as_bad here may be 80295011Sandrew inappropriate, since the user may want to force a 81295011Sandrew particular type without regard to the semantics of sets; 82295011Sandrew on the other hand, we certainly don't want anybody to be 83295011Sandrew mislead into thinking that their code will work. */ 84295011Sandrew if (S_IS_COMMON (sym)) 85295011Sandrew as_bad (_("Attempt to put a common symbol into set %s"), 86295011Sandrew S_GET_NAME (sym)); 87295011Sandrew /* Similarly, you can't put an undefined symbol in a set. */ 88295011Sandrew else if (! S_IS_DEFINED (sym)) 89295011Sandrew as_bad (_("Attempt to put an undefined symbol into set %s"), 90295011Sandrew S_GET_NAME (sym)); 91295011Sandrew 92295011Sandrew break; 93295011Sandrew case N_INDR: 94295011Sandrew /* Put indirect symbols in the indirect section. */ 95295011Sandrew S_SET_SEGMENT (sym, bfd_ind_section_ptr); 96295011Sandrew symbol_get_bfdsym (sym)->flags |= BSF_INDIRECT; 97295011Sandrew if (type & N_EXT) 98295011Sandrew { 99295011Sandrew symbol_get_bfdsym (sym)->flags |= BSF_EXPORT; 100295011Sandrew symbol_get_bfdsym (sym)->flags &=~ BSF_LOCAL; 101295011Sandrew } 102295011Sandrew break; 103295011Sandrew case N_WARNING: 104295011Sandrew /* Mark warning symbols. */ 105295011Sandrew symbol_get_bfdsym (sym)->flags |= BSF_WARNING; 106295011Sandrew break; 107295011Sandrew } 108295011Sandrew } 109295011Sandrew else 110295011Sandrew symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING; 111295011Sandrew 112295011Sandrew aout_symbol (symbol_get_bfdsym (sym))->type = type; 113295011Sandrew 114295011Sandrew /* Double check weak symbols. */ 115295011Sandrew if (S_IS_WEAK (sym) && S_IS_COMMON (sym)) 116295011Sandrew as_bad (_("Symbol `%s' can not be both weak and common"), 117295011Sandrew S_GET_NAME (sym)); 118295011Sandrew} 119295011Sandrew 120295011Sandrewvoid 121295011Sandrewobj_aout_frob_file_before_fix (void) 122295011Sandrew{ 123295011Sandrew /* Relocation processing may require knowing the VMAs of the sections. 124295011Sandrew Since writing to a section will cause the BFD back end to compute the 125295011Sandrew VMAs, fake it out here.... */ 126295011Sandrew bfd_byte b = 0; 127295011Sandrew bfd_boolean x = TRUE; 128295011Sandrew if (bfd_section_size (stdoutput, text_section) != 0) 129295011Sandrew x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0, 130295011Sandrew (bfd_size_type) 1); 131295011Sandrew else if (bfd_section_size (stdoutput, data_section) != 0) 132295011Sandrew x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0, 133295011Sandrew (bfd_size_type) 1); 134295011Sandrew 135295011Sandrew assert (x); 136295011Sandrew} 137295011Sandrew 138295011Sandrewstatic void 139295011Sandrewobj_aout_line (int ignore ATTRIBUTE_UNUSED) 140295011Sandrew{ 141295011Sandrew /* Assume delimiter is part of expression. 142295011Sandrew BSD4.2 as fails with delightful bug, so we 143295011Sandrew are not being incompatible here. */ 144295011Sandrew new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); 145295011Sandrew demand_empty_rest_of_line (); 146295011Sandrew} 147295011Sandrew 148295011Sandrew/* Handle .weak. This is a GNU extension. */ 149295011Sandrew 150295011Sandrewstatic void 151295011Sandrewobj_aout_weak (int ignore ATTRIBUTE_UNUSED) 152295011Sandrew{ 153295011Sandrew char *name; 154295011Sandrew int c; 155295011Sandrew symbolS *symbolP; 156295011Sandrew 157295011Sandrew do 158295011Sandrew { 159295011Sandrew name = input_line_pointer; 160295011Sandrew c = get_symbol_end (); 161295011Sandrew symbolP = symbol_find_or_make (name); 162295011Sandrew *input_line_pointer = c; 163295011Sandrew SKIP_WHITESPACE (); 164295011Sandrew S_SET_WEAK (symbolP); 165295011Sandrew if (c == ',') 166295011Sandrew { 167295011Sandrew input_line_pointer++; 168295011Sandrew SKIP_WHITESPACE (); 169295011Sandrew if (*input_line_pointer == '\n') 170295011Sandrew c = '\n'; 171295011Sandrew } 172295011Sandrew } 173295011Sandrew while (c == ','); 174295011Sandrew demand_empty_rest_of_line (); 175295011Sandrew} 176295011Sandrew 177295011Sandrew/* Handle .type. On {Net,Open}BSD, this is used to set the n_other field, 178295011Sandrew which is then apparently used when doing dynamic linking. Older 179295011Sandrew versions of gas ignored the .type pseudo-op, so we also ignore it if 180295011Sandrew we can't parse it. */ 181295011Sandrew 182295011Sandrewstatic void 183295011Sandrewobj_aout_type (int ignore ATTRIBUTE_UNUSED) 184295011Sandrew{ 185295011Sandrew char *name; 186295011Sandrew int c; 187295011Sandrew symbolS *sym; 188295011Sandrew 189295011Sandrew name = input_line_pointer; 190295011Sandrew c = get_symbol_end (); 191295011Sandrew sym = symbol_find_or_make (name); 192295011Sandrew *input_line_pointer = c; 193295011Sandrew SKIP_WHITESPACE (); 194295011Sandrew if (*input_line_pointer == ',') 195295011Sandrew { 196295011Sandrew ++input_line_pointer; 197295011Sandrew SKIP_WHITESPACE (); 198295011Sandrew if (*input_line_pointer == '@') 199295011Sandrew { 200295011Sandrew ++input_line_pointer; 201295011Sandrew if (strncmp (input_line_pointer, "object", 6) == 0) 202295011Sandrew S_SET_OTHER (sym, 1); 203295011Sandrew else if (strncmp (input_line_pointer, "function", 8) == 0) 204295011Sandrew S_SET_OTHER (sym, 2); 205295011Sandrew } 206295011Sandrew } 207295011Sandrew 208295011Sandrew /* Ignore everything else on the line. */ 209295011Sandrew s_ignore (0); 210295011Sandrew} 211295011Sandrew 212295011Sandrew/* Support for an AOUT emulation. */ 213295011Sandrew 214295011Sandrewstatic void 215295011Sandrewaout_pop_insert (void) 216295011Sandrew{ 217295011Sandrew pop_insert (aout_pseudo_table); 218295011Sandrew} 219295011Sandrew 220295011Sandrewstatic int 221295011Sandrewobj_aout_s_get_other (symbolS *sym) 222295011Sandrew{ 223295011Sandrew return aout_symbol (symbol_get_bfdsym (sym))->other; 224295011Sandrew} 225295011Sandrew 226295011Sandrewstatic void 227295011Sandrewobj_aout_s_set_other (symbolS *sym, int o) 228295011Sandrew{ 229295011Sandrew aout_symbol (symbol_get_bfdsym (sym))->other = o; 230295011Sandrew} 231295011Sandrew 232295011Sandrewstatic int 233295011Sandrewobj_aout_sec_sym_ok_for_reloc (asection *sec ATTRIBUTE_UNUSED) 234295011Sandrew{ 235295011Sandrew return obj_sec_sym_ok_for_reloc (sec); 236295011Sandrew} 237295011Sandrew 238295011Sandrewstatic void 239295011Sandrewobj_aout_process_stab (segT seg ATTRIBUTE_UNUSED, 240295011Sandrew int w, 241295011Sandrew const char *s, 242295011Sandrew int t, 243295011Sandrew int o, 244295011Sandrew int d) 245295011Sandrew{ 246295011Sandrew aout_process_stab (w, s, t, o, d); 247295011Sandrew} 248295011Sandrew 249295011Sandrewstatic int 250295011Sandrewobj_aout_s_get_desc (symbolS *sym) 251295011Sandrew{ 252295011Sandrew return aout_symbol (symbol_get_bfdsym (sym))->desc; 253295011Sandrew} 254295011Sandrew 255295011Sandrewstatic void 256295011Sandrewobj_aout_s_set_desc (symbolS *sym, int d) 257295011Sandrew{ 258295011Sandrew aout_symbol (symbol_get_bfdsym (sym))->desc = d; 259295011Sandrew} 260295011Sandrew 261295011Sandrewstatic int 262295011Sandrewobj_aout_s_get_type (symbolS *sym) 263295011Sandrew{ 264295011Sandrew return aout_symbol (symbol_get_bfdsym (sym))->type; 265295011Sandrew} 266295011Sandrew 267295011Sandrewstatic void 268295011Sandrewobj_aout_s_set_type (symbolS *sym, int t) 269295011Sandrew{ 270295011Sandrew aout_symbol (symbol_get_bfdsym (sym))->type = t; 271295011Sandrew} 272295011Sandrew 273295011Sandrewstatic int 274295011Sandrewobj_aout_separate_stab_sections (void) 275295011Sandrew{ 276295011Sandrew return 0; 277295011Sandrew} 278295011Sandrew 279295011Sandrew/* When changed, make sure these table entries match the single-format 280295011Sandrew definitions in obj-aout.h. */ 281295011Sandrew 282295011Sandrewconst struct format_ops aout_format_ops = 283295011Sandrew{ 284295011Sandrew bfd_target_aout_flavour, 285295011Sandrew 1, /* dfl_leading_underscore. */ 286295011Sandrew 0, /* emit_section_symbols. */ 287295011Sandrew 0, /* begin. */ 288295011Sandrew 0, /* app_file. */ 289295011Sandrew obj_aout_frob_symbol, 290295011Sandrew 0, /* frob_file. */ 291295011Sandrew 0, /* frob_file_before_adjust. */ 292295011Sandrew obj_aout_frob_file_before_fix, 293295011Sandrew 0, /* frob_file_after_relocs. */ 294295011Sandrew 0, /* s_get_size. */ 295295011Sandrew 0, /* s_set_size. */ 296295011Sandrew 0, /* s_get_align. */ 297295011Sandrew 0, /* s_set_align. */ 298295011Sandrew obj_aout_s_get_other, 299295011Sandrew obj_aout_s_set_other, 300295011Sandrew obj_aout_s_get_desc, 301295011Sandrew obj_aout_s_set_desc, 302295011Sandrew obj_aout_s_get_type, 303295011Sandrew obj_aout_s_set_type, 304295011Sandrew 0, /* copy_symbol_attributes. */ 305295011Sandrew 0, /* generate_asm_lineno. */ 306295011Sandrew obj_aout_process_stab, 307295011Sandrew obj_aout_separate_stab_sections, 308295011Sandrew 0, /* init_stab_section. */ 309295011Sandrew obj_aout_sec_sym_ok_for_reloc, 310295011Sandrew aout_pop_insert, 311295011Sandrew 0, /* ecoff_set_ext. */ 312295011Sandrew 0, /* read_begin_hook. */ 313295011Sandrew 0 /* symbol_new_hook. */ 314295011Sandrew}; 315295011Sandrew 316295011Sandrewconst pseudo_typeS aout_pseudo_table[] = 317295011Sandrew{ 318295011Sandrew {"line", obj_aout_line, 0}, /* Source code line number. */ 319295011Sandrew {"ln", obj_aout_line, 0}, /* COFF line number that we use anyway. */ 320295011Sandrew 321295011Sandrew {"weak", obj_aout_weak, 0}, /* Mark symbol as weak. */ 322295011Sandrew 323295011Sandrew {"type", obj_aout_type, 0}, 324295011Sandrew 325295011Sandrew /* coff debug pseudos (ignored) */ 326295011Sandrew {"def", s_ignore, 0}, 327295011Sandrew {"dim", s_ignore, 0}, 328295011Sandrew {"endef", s_ignore, 0}, 329295011Sandrew {"ident", s_ignore, 0}, 330295011Sandrew {"line", s_ignore, 0}, 331295011Sandrew {"ln", s_ignore, 0}, 332295011Sandrew {"scl", s_ignore, 0}, 333295011Sandrew {"size", s_ignore, 0}, 334295011Sandrew {"tag", s_ignore, 0}, 335295011Sandrew {"val", s_ignore, 0}, 336295011Sandrew {"version", s_ignore, 0}, 337295011Sandrew 338295011Sandrew {"optim", s_ignore, 0}, /* For sun386i cc (?). */ 339295011Sandrew 340295011Sandrew /* other stuff */ 341295011Sandrew {"ABORT", s_abort, 0}, 342295011Sandrew 343295011Sandrew {NULL, NULL, 0} 344295011Sandrew}; 345295011Sandrew