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