1 /* a.out object file format
2 Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2,
9 or (at your option) any later version.
11 GAS is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 the GNU General Public License for more details.
16 You should have received a copy of the GNU General Public
17 License along with GAS; see the file COPYING. If not, write
18 to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 /* in: segT out: N_TYPE bits */
27 const short seg_N_TYPE[] = {
36 N_UNDF, /* bignum/flonum */
37 N_UNDF, /* difference */
41 N_REGISTER, /* register */
44 const segT N_TYPE_seg[N_TYPE+2] = { /* N_TYPE == 0x1E = 32-2 */
45 SEG_UNKNOWN, SEG_GOOF, /* N_UNDF == 0 */
46 SEG_ABSOLUTE, SEG_GOOF, /* N_ABS == 2 */
47 SEG_TEXT, SEG_GOOF, /* N_TEXT == 4 */
48 SEG_DATA, SEG_GOOF, /* N_DATA == 6 */
49 SEG_BSS, SEG_GOOF, /* N_BSS == 8 */
50 SEG_GOOF, SEG_GOOF, /* N_INDR == 0xa */
51 SEG_GOOF, SEG_GOOF, /* 0xc */
52 SEG_GOOF, SEG_GOOF, /* 0xe */
53 SEG_GOOF, SEG_GOOF, /* 0x10 */
54 SEG_REGISTER, SEG_GOOF, /* 0x12 (dummy N_REGISTER) */
55 SEG_GOOF, SEG_GOOF, /* N_SETA == 0x14 */
56 SEG_GOOF, SEG_GOOF, /* N_SETT == 0x16 */
57 SEG_GOOF, SEG_GOOF, /* N_SETD == 0x18 */
58 SEG_GOOF, SEG_GOOF, /* N_SETB == 0x1a */
59 SEG_GOOF, SEG_GOOF, /* N_SETV == 0x1c */
60 SEG_GOOF, SEG_GOOF, /* N_WARNING == 0x1e */
64 static void obj_aout_stab(int what);
65 static void obj_aout_line(void);
66 static void obj_aout_desc(void);
67 #else /* not __STDC__ */
68 static void obj_aout_desc();
69 static void obj_aout_stab();
70 static void obj_aout_line();
71 #endif /* not __STDC__ */
73 const pseudo_typeS obj_pseudo_table[] = {
75 /* stabs debug info */
76 { "line", obj_aout_line, 0 }, /* source code line number */
77 { "ln", obj_aout_line, 0 }, /* coff line number that we use anyway */
78 { "desc", obj_aout_desc, 0 }, /* desc */
79 { "stabd", obj_aout_stab, 'd' }, /* stabs */
80 { "stabn", obj_aout_stab, 'n' }, /* stabs */
81 { "stabs", obj_aout_stab, 's' }, /* stabs */
82 #else /* IGNORE_DEBUG */
83 { "line", obj_aout_line, 0 }, /* source code line number */
84 { "ln", obj_aout_line, 0 }, /* coff line number that we use anyway */
85 { "desc", obj_aout_desc, 0 }, /* desc */
86 { "stabd", obj_aout_stab, 'd' }, /* stabs */
87 { "stabn", obj_aout_stab, 'n' }, /* stabs */
88 { "stabs", obj_aout_stab, 's' }, /* stabs */
89 #endif /* IGNORE_DEBUG */
91 /* coff debug pseudos (ignored) */
92 { "def", s_ignore, 0 },
93 { "dim", s_ignore, 0 },
94 { "endef", s_ignore, 0 },
95 { "ident", s_ignore, 0 },
96 { "line", s_ignore, 0 },
97 { "ln", s_ignore, 0 },
98 { "scl", s_ignore, 0 },
99 { "size", s_size, 0 },
100 { "tag", s_ignore, 0 },
101 { "type", s_type, 0 },
102 { "val", s_ignore, 0 },
103 { "version", s_ignore, 0 },
104 { "weak", s_weak, 0 },
106 /* stabs-in-coff (?) debug pseudos (ignored) */
107 { "optim", s_ignore, 0 }, /* For sun386i cc (?) */
110 { "ABORT", s_abort, 0 },
112 { NULL} /* end sentinel */
113 }; /* obj_pseudo_table */
121 * Crawl along a fixS chain. Emit the segment's relocations.
123 void obj_emit_relocations(where, fixP, segment_address_in_file)
125 fixS *fixP; /* Fixup chain for this segment. */
126 relax_addressT segment_address_in_file;
128 for (; fixP; fixP = fixP->fx_next) {
129 if (fixP->fx_addsy != NULL) {
130 tc_aout_fix_to_chars(*where, fixP, segment_address_in_file);
131 *where += md_reloc_size;
132 } /* if there is an add symbol */
136 } /* obj_emit_relocations() */
138 /* Aout file generation & utilities */
139 void obj_header_append(where, headers)
141 object_headers *headers;
143 tc_headers_hook(headers);
145 #if defined(NETBSD_AOUT)
146 /* `a_info' (magic, mid, flags) is in network byte-order */
147 (*where)[0] = ((char *)&headers->header.a_info)[0];
148 (*where)[1] = ((char *)&headers->header.a_info)[1];
149 (*where)[2] = ((char *)&headers->header.a_info)[2];
150 (*where)[3] = ((char *)&headers->header.a_info)[3];
152 md_number_to_chars(*where, headers->header.a_info,
153 sizeof(headers->header.a_info));
155 *where += sizeof(headers->header.a_info);
158 md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare1 */
159 md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare2 */
162 md_number_to_chars(*where, headers->header.a_text, 4); *where += 4;
163 md_number_to_chars(*where, headers->header.a_data, 4); *where += 4;
164 md_number_to_chars(*where, headers->header.a_bss, 4); *where += 4;
167 md_number_to_chars(*where, headers->header.a_syms, 4); *where += 4;
168 md_number_to_chars(*where, headers->header.a_entry, 4); *where += 4;
169 #endif /* not TE_HPUX */
171 md_number_to_chars(*where, headers->header.a_trsize, 4); *where += 4;
172 md_number_to_chars(*where, headers->header.a_drsize, 4); *where += 4;
175 memset(*where, '\0', 3 * 2 * 4); *where += 3 * 2 * 4; /* global descriptor table? */
176 md_number_to_chars(*where, 0, 4); *where += 4; /* shdata - length of initialized shared data */
177 md_number_to_chars(*where, 0, 4); *where += 4; /* shbss - length of uninitialized shared data */
178 md_number_to_chars(*where, 0, 4); *where += 4; /* shdrsize - length of shared data relocation */
180 memset(*where, '\0', 11 * 4); *where += 11 * 4; /* boostrap for standalone */
181 memset(*where, '\0', 3 * 4); *where += 3 * 4; /* reserved */
182 md_number_to_chars(*where, 0, 4); *where += 4; /* version */
183 #endif /* TE_SEQUENT */
186 md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare3 - HP = pascal interface size */
187 md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare4 - HP = symbol table size */
188 md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare5 - HP = debug name table size */
190 md_number_to_chars(*where, headers->header.a_entry, 4); *where += 4;
192 md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare6 - HP = source line table size */
193 md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare7 - HP = value table size */
195 md_number_to_chars(*where, headers->header.a_syms, 4); *where += 4;
197 md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare8 */
201 } /* obj_append_header() */
203 void obj_symbol_to_chars(where, symbolP)
207 md_number_to_chars((char *)&(S_GET_OFFSET(symbolP)), S_GET_OFFSET(symbolP), sizeof(S_GET_OFFSET(symbolP)));
208 md_number_to_chars((char *)&(S_GET_DESC(symbolP)), S_GET_DESC(symbolP), sizeof(S_GET_DESC(symbolP)));
209 md_number_to_chars((char *)&(S_GET_VALUE(symbolP)), S_GET_VALUE(symbolP), sizeof(S_GET_VALUE(symbolP)));
211 append(where, (char *)&symbolP->sy_symbol, sizeof(obj_symbol_type));
212 } /* obj_symbol_to_chars() */
214 void obj_emit_symbols(where, symbol_rootP)
216 symbolS *symbol_rootP;
221 * Emit all symbols left in the symbol chain.
223 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
224 /* Used to save the offset of the name. It is used to point
225 to the string in memory but must be a file offset. */
228 temp = S_GET_NAME(symbolP);
229 S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
231 /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
232 if (!S_IS_DEBUG(symbolP) && !S_IS_DEFINED(symbolP))
233 S_SET_EXTERNAL(symbolP);
236 * Put aux info in lower four bits of `n_other' field
237 * Do this only now, because things like S_IS_DEFINED()
238 * depend on S_GET_OTHER() for some unspecified reason.
241 (symbolP->sy_bind << 4) | (symbolP->sy_aux & 0xf));
243 if (S_GET_TYPE(symbolP) == N_SIZE) {
244 expressionS *exp = (expressionS*)symbolP->sy_sizexp;
248 as_bad("Internal error: no size expression");
252 switch (exp->X_seg) {
254 size = exp->X_add_number;
257 size = S_GET_VALUE(exp->X_add_symbol) -
258 S_GET_VALUE(exp->X_subtract_symbol) +
262 as_bad("Unsupported .size expression");
265 S_SET_VALUE(symbolP, size);
268 obj_symbol_to_chars(where, symbolP);
269 S_SET_NAME(symbolP,temp);
271 } /* emit_symbols() */
274 /* uneeded if symbol is born zeroed. */
275 void obj_symbol_new_hook(symbolP)
278 S_SET_OTHER(symbolP, 0);
279 S_SET_DESC(symbolP, 0);
281 } /* obj_symbol_new_hook() */
284 static void obj_aout_line() {
285 /* Assume delimiter is part of expression. */
286 /* BSD4.2 as fails with delightful bug, so we */
287 /* are not being incompatible here. */
288 new_logical_line((char *)NULL, (int)(get_absolute_expression()));
289 demand_empty_rest_of_line();
290 } /* obj_aout_line() */
295 * Handle .stabX directives, which used to be open-coded.
296 * So much creeping featurism overloaded the semantics that we decided
297 * to put all .stabX thinking in one place. Here.
299 * We try to make any .stabX directive legal. Other people's AS will often
300 * do assembly-time consistency checks: eg assigning meaning to n_type bits
301 * and "protecting" you from setting them to certain values. (They also zero
302 * certain bits before emitting symbols. Tut tut.)
304 * If an expression is not absolute we either gripe or use the relocation
305 * information. Other people's assemblers silently forget information they
306 * don't need and invent information they need that you didn't supply.
308 * .stabX directives always make a symbol table entry. It may be junk if
309 * the rest of your .stabX directive is malformed.
311 static void obj_aout_stab(what)
316 #endif /* NO_LISTING */
318 register symbolS *symbolP = 0;
319 register char *string;
322 int goof; /* TRUE if we have aborted. */
326 * Enter with input_line_pointer pointing past .stabX and any following
329 goof = 0; /* JF who forgot this?? */
331 string = demand_copy_C_string(& length);
333 if (* input_line_pointer == ',')
334 input_line_pointer ++;
336 as_bad("I need a comma after symbol's name");
343 * Input_line_pointer->after ','. String->symbol name.
346 symbolP = symbol_new(string,
352 S_SET_NAME(symbolP, NULL); /* .stabd feature. */
353 S_SET_VALUE(symbolP, obstack_next_free(&frags) - frag_now->fr_literal);
354 symbolP->sy_frag = frag_now;
358 symbolP->sy_frag = &zero_address_frag;
362 symbolP->sy_frag = & zero_address_frag;
370 if (get_absolute_expression_and_terminator(&longint) == ',')
371 symbolP->sy_symbol.n_type = saved_type = longint;
373 as_bad("I want a comma after the n_type expression");
375 input_line_pointer --; /* Backup over a non-',' char. */
380 if (get_absolute_expression_and_terminator(&longint) == ',')
381 S_SET_OTHER(symbolP, longint);
383 as_bad("I want a comma after the n_other expression");
385 input_line_pointer--; /* Backup over a non-',' char. */
390 S_SET_DESC(symbolP, get_absolute_expression());
391 if (what == 's' || what == 'n') {
392 if (*input_line_pointer != ',') {
393 as_bad("I want a comma after the n_desc expression");
396 input_line_pointer++;
401 if ((!goof) && (what == 's' || what == 'n')) {
403 symbolP->sy_symbol.n_type = saved_type;
406 if (listing && !goof)
408 if (symbolP->sy_symbol.n_type == N_SLINE)
411 listing_source_line(symbolP->sy_symbol.n_desc);
413 else if (symbolP->sy_symbol.n_type == N_SO
414 || symbolP->sy_symbol.n_type == N_SOL)
416 listing_source_file(string);
422 ignore_rest_of_line();
424 demand_empty_rest_of_line ();
425 } /* obj_aout_stab() */
427 static void obj_aout_desc() {
431 register symbolS *symbolP;
435 * Frob invented at RMS' request. Set the n_desc of a symbol.
437 name = input_line_pointer;
438 c = get_symbol_end();
439 p = input_line_pointer;
442 if (*input_line_pointer != ',') {
444 as_bad("Expected comma after name \"%s\"", name);
446 ignore_rest_of_line();
448 input_line_pointer ++;
449 temp = get_absolute_expression();
451 symbolP = symbol_find_or_make(name);
453 S_SET_DESC(symbolP,temp);
455 demand_empty_rest_of_line();
456 } /* obj_aout_desc() */
458 void obj_read_begin_hook() {
460 } /* obj_read_begin_hook() */
462 void obj_crawl_symbol_chain(headers)
463 object_headers *headers;
467 int symbol_number = 0;
469 /* JF deal with forward references first... */
470 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
471 if (symbolP->sy_forward && symbolP->sy_forward != symbolP) {
472 switch (S_GET_TYPE(symbolP)) {
479 * Don't change the segments of SET symbols,
480 * because that would turn them into regular
486 S_SET_SEGMENT(symbolP,
487 S_GET_SEGMENT(symbolP->sy_forward));
490 S_SET_VALUE(symbolP, S_GET_VALUE(symbolP)
491 + S_GET_VALUE(symbolP->sy_forward)
492 + symbolP->sy_forward->sy_frag->fr_address);
494 symbolP->sy_aux |= symbolP->sy_forward->sy_aux;
495 symbolP->sy_sizexp = symbolP->sy_forward->sy_sizexp;
496 if (S_IS_EXTERNAL(symbolP->sy_forward))
497 S_SET_EXTERNAL(symbolP);
498 } /* if it has a forward reference */
499 symbolP->sy_forward=0;
500 } /* walk the symbol chain */
502 tc_crawl_symbol_chain(headers);
504 symbolPP = &symbol_rootP; /*->last symbol chain link. */
505 while ((symbolP = *symbolPP) != NULL) {
506 if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_DATA)) {
507 S_SET_SEGMENT(symbolP, SEG_TEXT);
508 } /* if pushing data into text */
510 S_SET_VALUE(symbolP, S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
512 /* OK, here is how we decide which symbols go out into the
513 brave new symtab. Symbols that do are:
515 * symbols with no name (stabd's?)
516 * symbols with debug info in their N_TYPE
517 * symbols marked "forceout" (to force out local `L'
520 Symbols that don't are:
521 * symbols that are registers
522 * symbols with \1 as their 3rd character (numeric labels)
523 * "local labels" as defined by S_LOCAL_NAME(name)
524 if the -L switch was passed to gas.
526 All other symbols are output. We complain if a deleted
527 symbol was marked external. */
530 if (!S_IS_REGISTER(symbolP)
531 && (!S_GET_NAME(symbolP)
532 || S_IS_DEBUG(symbolP)
534 /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */
535 || !S_IS_DEFINED(symbolP)
536 || S_IS_EXTERNAL(symbolP)
538 || (S_GET_NAME(symbolP)[0] != '\001' &&
539 (flagseen['L'] || ! S_LOCAL_NAME(symbolP))
541 || (picmode && symbolP->sy_forceout)
547 symbolP != GOT_symbol || got_referenced != 0
551 symbolP->sy_number = symbol_number++;
553 /* The + 1 after strlen account for the \0 at the
554 end of each string */
555 if (!S_IS_STABD(symbolP)) {
557 symbolP->sy_name_offset = string_byte_count;
558 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
560 else /* .Stabd case. */
561 symbolP->sy_name_offset = 0;
564 * If symbol has a known size, output an extra symbol
565 * of type N_SIZE and with the same name.
566 * We cannot evaluate the size expression just yet, as
567 * some its terms may not have had their final values
568 * set. We defer this until `obj_emit_symbols()'
571 S_GET_TYPE(symbolP) != N_SIZE &&
572 #ifndef GRACE_PERIOD_EXPIRED
573 /*Can be enabled when no more old ld's around*/
574 (symbolP->sy_aux == AUX_OBJECT) &&
576 symbolP->sy_sizexp) {
580 /* Put a new symbol on the chain */
581 #ifdef NSIZE_PREFIX /*XXX*/
584 buf[0] = NSIZE_PREFIX;
585 strncpy(buf+1, S_GET_NAME(symbolP), BUFSIZ-2);
586 addme = symbol_make(buf);
588 addme = symbol_make(S_GET_NAME(symbolP));
590 /* Set type and transfer size expression */
591 addme->sy_symbol.n_type = N_SIZE;
592 addme->sy_sizexp = symbolP->sy_sizexp;
593 symbolP->sy_sizexp = NULL;
595 /* Set external if symbolP is */
596 if (S_IS_EXTERN(symbolP))
597 S_SET_EXTERNAL(addme);
600 symbolPP = &(symbol_next(symbolP));
602 if ((S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP))
605 symbolP != GOT_symbol || got_referenced != 0
609 as_bad("Local symbol %s never defined.", decode_local_label_name(S_GET_NAME(symbolP)));
612 /* Unhook it from the chain */
613 *symbolPP = symbol_next(symbolP);
614 } /* if this symbol should be in the output */
615 } /* for each symbol */
617 H_SET_SYMBOL_TABLE_SIZE(headers, symbol_number);
620 } /* obj_crawl_symbol_chain() */
623 * Find strings by crawling along symbol table chain.
626 void obj_emit_strings(where)
632 /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
633 md_number_to_chars(*where, string_byte_count, sizeof(string_byte_count));
634 *where += sizeof(string_byte_count);
635 #else /* CROSS_COMPILE */
636 append (where, (char *)&string_byte_count, (unsigned long)sizeof(string_byte_count));
637 #endif /* CROSS_COMPILE */
639 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
640 if (S_GET_NAME(symbolP))
641 append(&next_object_file_charP, S_GET_NAME(symbolP),
642 (unsigned long)(strlen (S_GET_NAME(symbolP)) + 1));
643 } /* walk symbol chain */
646 } /* obj_emit_strings() */
648 void obj_pre_write_hook(headers)
649 object_headers *headers;
652 DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE,
657 H_SET_ENTRY_POINT(headers, 0);
659 tc_aout_pre_write_hook(headers);
661 } /* obj_pre_write_hook() */
670 /* end of obj-aout.c */