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