12159047fSniklas /* b.out object file format
2c074d1c9Sdrahn Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1996, 2000, 2001, 2002
3191aa565Sniklas Free Software Foundation, Inc.
42159047fSniklas
52159047fSniklas This file is part of GAS, the GNU Assembler.
62159047fSniklas
72159047fSniklas GAS is free software; you can redistribute it and/or modify
82159047fSniklas it under the terms of the GNU General Public License as
92159047fSniklas published by the Free Software Foundation; either version 2,
102159047fSniklas or (at your option) any later version.
112159047fSniklas
122159047fSniklas GAS is distributed in the hope that it will be useful, but
132159047fSniklas WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
152159047fSniklas the GNU General Public License for more details.
162159047fSniklas
17b305b0f1Sespie You should have received a copy of the GNU General Public License
18b305b0f1Sespie along with GAS; see the file COPYING. If not, write to the Free
19b305b0f1Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20b305b0f1Sespie 02111-1307, USA. */
212159047fSniklas
222159047fSniklas #include "as.h"
232159047fSniklas #include "obstack.h"
24b55d4692Sfgsch
25b55d4692Sfgsch /* In: segT Out: N_TYPE bits */
26b55d4692Sfgsch const short seg_N_TYPE[] =
272159047fSniklas {
282159047fSniklas N_ABS,
292159047fSniklas N_TEXT,
302159047fSniklas N_DATA,
312159047fSniklas N_BSS,
322159047fSniklas N_UNDF, /* unknown */
332159047fSniklas N_UNDF, /* error */
342159047fSniklas N_UNDF, /* expression */
352159047fSniklas N_UNDF, /* debug */
362159047fSniklas N_UNDF, /* ntv */
372159047fSniklas N_UNDF, /* ptv */
382159047fSniklas N_REGISTER, /* register */
392159047fSniklas };
402159047fSniklas
412159047fSniklas const segT N_TYPE_seg[N_TYPE + 2] =
422159047fSniklas { /* N_TYPE == 0x1E = 32-2 */
432159047fSniklas SEG_UNKNOWN, /* N_UNDF == 0 */
442159047fSniklas SEG_GOOF,
452159047fSniklas SEG_ABSOLUTE, /* N_ABS == 2 */
462159047fSniklas SEG_GOOF,
472159047fSniklas SEG_TEXT, /* N_TEXT == 4 */
482159047fSniklas SEG_GOOF,
492159047fSniklas SEG_DATA, /* N_DATA == 6 */
502159047fSniklas SEG_GOOF,
512159047fSniklas SEG_BSS, /* N_BSS == 8 */
522159047fSniklas SEG_GOOF,
532159047fSniklas SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
542159047fSniklas SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
552159047fSniklas SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
562159047fSniklas SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */
572159047fSniklas SEG_GOOF,
582159047fSniklas };
592159047fSniklas
602159047fSniklas static void obj_bout_line PARAMS ((int));
612159047fSniklas
622159047fSniklas const pseudo_typeS obj_pseudo_table[] =
632159047fSniklas {
64b55d4692Sfgsch {"line", obj_bout_line, 0}, /* Source code line number. */
652159047fSniklas
66b55d4692Sfgsch /* coff debugging directives. Currently ignored silently. */
672159047fSniklas {"def", s_ignore, 0},
682159047fSniklas {"dim", s_ignore, 0},
692159047fSniklas {"endef", s_ignore, 0},
702159047fSniklas {"ln", s_ignore, 0},
712159047fSniklas {"scl", s_ignore, 0},
722159047fSniklas {"size", s_ignore, 0},
732159047fSniklas {"tag", s_ignore, 0},
742159047fSniklas {"type", s_ignore, 0},
752159047fSniklas {"val", s_ignore, 0},
762159047fSniklas
772159047fSniklas /* other stuff we don't handle */
782159047fSniklas {"ABORT", s_ignore, 0},
792159047fSniklas {"ident", s_ignore, 0},
802159047fSniklas
81c074d1c9Sdrahn {NULL, NULL, 0} /* End sentinel. */
82b55d4692Sfgsch };
832159047fSniklas
842159047fSniklas /* Relocation. */
852159047fSniklas
86b55d4692Sfgsch /* Crawl along a fixS chain. Emit the segment's relocations. */
87b55d4692Sfgsch
882159047fSniklas void
obj_emit_relocations(where,fixP,segment_address_in_file)892159047fSniklas obj_emit_relocations (where, fixP, segment_address_in_file)
902159047fSniklas char **where;
912159047fSniklas fixS *fixP; /* Fixup chain for this segment. */
922159047fSniklas relax_addressT segment_address_in_file;
932159047fSniklas {
942159047fSniklas for (; fixP; fixP = fixP->fx_next)
952159047fSniklas {
962159047fSniklas if (fixP->fx_done == 0
972159047fSniklas || fixP->fx_r_type != NO_RELOC)
982159047fSniklas {
99191aa565Sniklas symbolS *sym;
100191aa565Sniklas
101191aa565Sniklas sym = fixP->fx_addsy;
102191aa565Sniklas while (sym->sy_value.X_op == O_symbol
103191aa565Sniklas && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
104191aa565Sniklas sym = sym->sy_value.X_add_symbol;
105191aa565Sniklas fixP->fx_addsy = sym;
106191aa565Sniklas
1072159047fSniklas tc_bout_fix_to_chars (*where, fixP, segment_address_in_file);
1082159047fSniklas *where += sizeof (struct relocation_info);
1092159047fSniklas } /* if there's a symbol */
1102159047fSniklas } /* for each fixup */
111b55d4692Sfgsch }
1122159047fSniklas
113b55d4692Sfgsch /* Aout file generation & utilities . */
1142159047fSniklas
115b55d4692Sfgsch /* Convert a lvalue to machine dependent data. */
1162159047fSniklas
1172159047fSniklas void
obj_header_append(where,headers)1182159047fSniklas obj_header_append (where, headers)
1192159047fSniklas char **where;
1202159047fSniklas object_headers *headers;
1212159047fSniklas {
122b55d4692Sfgsch /* Always leave in host byte order. */
1232159047fSniklas
1242159047fSniklas headers->header.a_talign = section_alignment[SEG_TEXT];
1252159047fSniklas
126b55d4692Sfgsch /* Force to at least 2. */
1272159047fSniklas if (headers->header.a_talign < 2)
1282159047fSniklas {
1292159047fSniklas headers->header.a_talign = 2;
130b55d4692Sfgsch }
1312159047fSniklas
1322159047fSniklas headers->header.a_dalign = section_alignment[SEG_DATA];
1332159047fSniklas headers->header.a_balign = section_alignment[SEG_BSS];
1342159047fSniklas
1352159047fSniklas headers->header.a_tload = 0;
136b55d4692Sfgsch headers->header.a_dload =
137b55d4692Sfgsch md_section_align (SEG_DATA, H_GET_TEXT_SIZE (headers));
1382159047fSniklas
1392159047fSniklas headers->header.a_relaxable = linkrelax;
1402159047fSniklas
1412159047fSniklas #ifdef CROSS_COMPILE
1422159047fSniklas md_number_to_chars (*where, headers->header.a_magic, sizeof (headers->header.a_magic));
1432159047fSniklas *where += sizeof (headers->header.a_magic);
1442159047fSniklas md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text));
1452159047fSniklas *where += sizeof (headers->header.a_text);
1462159047fSniklas md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data));
1472159047fSniklas *where += sizeof (headers->header.a_data);
1482159047fSniklas md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss));
1492159047fSniklas *where += sizeof (headers->header.a_bss);
1502159047fSniklas md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms));
1512159047fSniklas *where += sizeof (headers->header.a_syms);
1522159047fSniklas md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry));
1532159047fSniklas *where += sizeof (headers->header.a_entry);
1542159047fSniklas md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize));
1552159047fSniklas *where += sizeof (headers->header.a_trsize);
1562159047fSniklas md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize));
1572159047fSniklas *where += sizeof (headers->header.a_drsize);
1582159047fSniklas md_number_to_chars (*where, headers->header.a_tload, sizeof (headers->header.a_tload));
1592159047fSniklas *where += sizeof (headers->header.a_tload);
1602159047fSniklas md_number_to_chars (*where, headers->header.a_dload, sizeof (headers->header.a_dload));
1612159047fSniklas *where += sizeof (headers->header.a_dload);
1622159047fSniklas md_number_to_chars (*where, headers->header.a_talign, sizeof (headers->header.a_talign));
1632159047fSniklas *where += sizeof (headers->header.a_talign);
1642159047fSniklas md_number_to_chars (*where, headers->header.a_dalign, sizeof (headers->header.a_dalign));
1652159047fSniklas *where += sizeof (headers->header.a_dalign);
1662159047fSniklas md_number_to_chars (*where, headers->header.a_balign, sizeof (headers->header.a_balign));
1672159047fSniklas *where += sizeof (headers->header.a_balign);
1682159047fSniklas md_number_to_chars (*where, headers->header.a_relaxable, sizeof (headers->header.a_relaxable));
1692159047fSniklas *where += sizeof (headers->header.a_relaxable);
1702159047fSniklas #else /* ! CROSS_COMPILE */
1712159047fSniklas append (where, (char *) &headers->header, sizeof (headers->header));
1722159047fSniklas #endif /* ! CROSS_COMPILE */
173b55d4692Sfgsch }
1742159047fSniklas
1752159047fSniklas void
obj_symbol_to_chars(where,symbolP)1762159047fSniklas obj_symbol_to_chars (where, symbolP)
1772159047fSniklas char **where;
1782159047fSniklas symbolS *symbolP;
1792159047fSniklas {
180b55d4692Sfgsch md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)),
181b55d4692Sfgsch S_GET_OFFSET (symbolP),
182b55d4692Sfgsch sizeof (S_GET_OFFSET (symbolP)));
183b55d4692Sfgsch
184b55d4692Sfgsch md_number_to_chars ((char *) &(S_GET_DESC (symbolP)),
185b55d4692Sfgsch S_GET_DESC (symbolP),
186b55d4692Sfgsch sizeof (S_GET_DESC (symbolP)));
187b55d4692Sfgsch
188b55d4692Sfgsch md_number_to_chars ((char *) &symbolP->sy_symbol.n_value,
189b55d4692Sfgsch S_GET_VALUE (symbolP),
190b55d4692Sfgsch sizeof (symbolP->sy_symbol.n_value));
1912159047fSniklas
1922159047fSniklas append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type));
193b55d4692Sfgsch }
1942159047fSniklas
1952159047fSniklas void
obj_emit_symbols(where,symbol_rootP)1962159047fSniklas obj_emit_symbols (where, symbol_rootP)
1972159047fSniklas char **where;
1982159047fSniklas symbolS *symbol_rootP;
1992159047fSniklas {
2002159047fSniklas symbolS *symbolP;
2012159047fSniklas
202b55d4692Sfgsch /* Emit all symbols left in the symbol chain. */
2032159047fSniklas for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
2042159047fSniklas {
205b55d4692Sfgsch /* Used to save the offset of the name. It is used to point to
206b55d4692Sfgsch the string in memory but must be a file offset. */
2072159047fSniklas char *temp;
2082159047fSniklas
2092159047fSniklas temp = S_GET_NAME (symbolP);
2102159047fSniklas S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
2112159047fSniklas
2122159047fSniklas /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
2132159047fSniklas if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
2142159047fSniklas S_SET_EXTERNAL (symbolP);
2152159047fSniklas
2162159047fSniklas obj_symbol_to_chars (where, symbolP);
2172159047fSniklas S_SET_NAME (symbolP, temp);
2182159047fSniklas }
219b55d4692Sfgsch }
2202159047fSniklas
2212159047fSniklas void
obj_symbol_new_hook(symbolP)2222159047fSniklas obj_symbol_new_hook (symbolP)
2232159047fSniklas symbolS *symbolP;
2242159047fSniklas {
2252159047fSniklas S_SET_OTHER (symbolP, 0);
2262159047fSniklas S_SET_DESC (symbolP, 0);
2272159047fSniklas }
2282159047fSniklas
2292159047fSniklas static void
obj_bout_line(ignore)2302159047fSniklas obj_bout_line (ignore)
231c074d1c9Sdrahn int ignore ATTRIBUTE_UNUSED;
2322159047fSniklas {
2332159047fSniklas /* Assume delimiter is part of expression. */
234b55d4692Sfgsch /* BSD4.2 as fails with delightful bug, so we are not being
235b55d4692Sfgsch incompatible here. */
2362159047fSniklas new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
2372159047fSniklas demand_empty_rest_of_line ();
238b55d4692Sfgsch }
2392159047fSniklas
2402159047fSniklas void
obj_read_begin_hook()2412159047fSniklas obj_read_begin_hook ()
2422159047fSniklas {
2432159047fSniklas }
2442159047fSniklas
2452159047fSniklas void
obj_crawl_symbol_chain(headers)2462159047fSniklas obj_crawl_symbol_chain (headers)
2472159047fSniklas object_headers *headers;
2482159047fSniklas {
2492159047fSniklas symbolS **symbolPP;
2502159047fSniklas symbolS *symbolP;
2512159047fSniklas int symbol_number = 0;
2522159047fSniklas
2532159047fSniklas tc_crawl_symbol_chain (headers);
2542159047fSniklas
2552159047fSniklas symbolPP = &symbol_rootP; /* -> last symbol chain link. */
2562159047fSniklas while ((symbolP = *symbolPP) != NULL)
2572159047fSniklas {
2582159047fSniklas if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA))
2592159047fSniklas {
2602159047fSniklas S_SET_SEGMENT (symbolP, SEG_TEXT);
261*007c2a45Smiod } /* if pushing data into text */
2622159047fSniklas
263c074d1c9Sdrahn resolve_symbol_value (symbolP);
2642159047fSniklas
265191aa565Sniklas /* Skip symbols which were equated to undefined or common
266191aa565Sniklas symbols. */
267191aa565Sniklas if (symbolP->sy_value.X_op == O_symbol
268191aa565Sniklas && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)))
269191aa565Sniklas {
270191aa565Sniklas *symbolPP = symbol_next (symbolP);
271191aa565Sniklas continue;
272191aa565Sniklas }
273191aa565Sniklas
2742159047fSniklas /* OK, here is how we decide which symbols go out into the
2752159047fSniklas brave new symtab. Symbols that do are:
2762159047fSniklas
2772159047fSniklas * symbols with no name (stabd's?)
2782159047fSniklas * symbols with debug info in their N_TYPE
2792159047fSniklas
2802159047fSniklas Symbols that don't are:
2812159047fSniklas * symbols that are registers
2822159047fSniklas * symbols with \1 as their 3rd character (numeric labels)
2832159047fSniklas * "local labels" as defined by S_LOCAL_NAME(name)
2842159047fSniklas if the -L switch was passed to gas.
2852159047fSniklas
2862159047fSniklas All other symbols are output. We complain if a deleted
2872159047fSniklas symbol was marked external. */
2882159047fSniklas
2892159047fSniklas if (1
2902159047fSniklas && !S_IS_REGISTER (symbolP)
2912159047fSniklas && (!S_GET_NAME (symbolP)
2922159047fSniklas || S_IS_DEBUG (symbolP)
2932159047fSniklas #ifdef TC_I960
2942159047fSniklas /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */
2952159047fSniklas || !S_IS_DEFINED (symbolP)
2962159047fSniklas || S_IS_EXTERNAL (symbolP)
2972159047fSniklas #endif /* TC_I960 */
298b55d4692Sfgsch || (S_GET_NAME (symbolP)[0] != '\001'
299b55d4692Sfgsch && (flag_keep_locals || !S_LOCAL_NAME (symbolP)))))
3002159047fSniklas {
3012159047fSniklas symbolP->sy_number = symbol_number++;
3022159047fSniklas
303b55d4692Sfgsch /* The + 1 after strlen account for the \0 at the end of
304b55d4692Sfgsch each string. */
3052159047fSniklas if (!S_IS_STABD (symbolP))
3062159047fSniklas {
3072159047fSniklas /* Ordinary case. */
3082159047fSniklas symbolP->sy_name_offset = string_byte_count;
3092159047fSniklas string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
3102159047fSniklas }
3112159047fSniklas else /* .Stabd case. */
3122159047fSniklas symbolP->sy_name_offset = 0;
313b55d4692Sfgsch symbolPP = &(symbolP->sy_next);
3142159047fSniklas }
3152159047fSniklas else
3162159047fSniklas {
3172159047fSniklas if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
3182159047fSniklas {
319b55d4692Sfgsch as_bad (_("Local symbol %s never defined"),
320b55d4692Sfgsch S_GET_NAME (symbolP));
321b55d4692Sfgsch } /* Oops. */
3222159047fSniklas
323b55d4692Sfgsch /* Unhook it from the chain. */
3242159047fSniklas *symbolPP = symbol_next (symbolP);
3252159047fSniklas } /* if this symbol should be in the output */
3262159047fSniklas } /* for each symbol */
3272159047fSniklas
3282159047fSniklas H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
3292159047fSniklas }
3302159047fSniklas
331b55d4692Sfgsch /* Find strings by crawling along symbol table chain. */
3322159047fSniklas
3332159047fSniklas void
obj_emit_strings(where)3342159047fSniklas obj_emit_strings (where)
3352159047fSniklas char **where;
3362159047fSniklas {
3372159047fSniklas symbolS *symbolP;
3382159047fSniklas
3392159047fSniklas #ifdef CROSS_COMPILE
3402159047fSniklas /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
3412159047fSniklas md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count));
3422159047fSniklas *where += sizeof (string_byte_count);
3432159047fSniklas #else /* CROSS_COMPILE */
344b55d4692Sfgsch append (where, (char *) &string_byte_count,
345b55d4692Sfgsch (unsigned long) sizeof (string_byte_count));
3462159047fSniklas #endif /* CROSS_COMPILE */
3472159047fSniklas
3482159047fSniklas for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
3492159047fSniklas {
3502159047fSniklas if (S_GET_NAME (symbolP))
351b55d4692Sfgsch append (where, S_GET_NAME (symbolP),
352b55d4692Sfgsch (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
353b55d4692Sfgsch } /* Walk symbol chain. */
3542159047fSniklas }
355