| 1 | /* b.out object file format
|
|---|
| 2 | Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1996, 2000, 2001, 2002
|
|---|
| 3 | 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, 59 Temple Place - Suite 330, Boston, MA
|
|---|
| 20 | 02111-1307, USA. */
|
|---|
| 21 |
|
|---|
| 22 | #include "as.h"
|
|---|
| 23 | #include "obstack.h"
|
|---|
| 24 |
|
|---|
| 25 | /* In: segT Out: N_TYPE bits */
|
|---|
| 26 | const short seg_N_TYPE[] =
|
|---|
| 27 | {
|
|---|
| 28 | N_ABS,
|
|---|
| 29 | N_TEXT,
|
|---|
| 30 | N_DATA,
|
|---|
| 31 | N_BSS,
|
|---|
| 32 | N_UNDF, /* unknown */
|
|---|
| 33 | N_UNDF, /* error */
|
|---|
| 34 | N_UNDF, /* expression */
|
|---|
| 35 | N_UNDF, /* debug */
|
|---|
| 36 | N_UNDF, /* ntv */
|
|---|
| 37 | N_UNDF, /* ptv */
|
|---|
| 38 | N_REGISTER, /* register */
|
|---|
| 39 | };
|
|---|
| 40 |
|
|---|
| 41 | const segT N_TYPE_seg[N_TYPE + 2] =
|
|---|
| 42 | { /* N_TYPE == 0x1E = 32-2 */
|
|---|
| 43 | SEG_UNKNOWN, /* N_UNDF == 0 */
|
|---|
| 44 | SEG_GOOF,
|
|---|
| 45 | SEG_ABSOLUTE, /* N_ABS == 2 */
|
|---|
| 46 | SEG_GOOF,
|
|---|
| 47 | SEG_TEXT, /* N_TEXT == 4 */
|
|---|
| 48 | SEG_GOOF,
|
|---|
| 49 | SEG_DATA, /* N_DATA == 6 */
|
|---|
| 50 | SEG_GOOF,
|
|---|
| 51 | SEG_BSS, /* N_BSS == 8 */
|
|---|
| 52 | SEG_GOOF,
|
|---|
| 53 | SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
|
|---|
| 54 | SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
|
|---|
| 55 | SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
|
|---|
| 56 | SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */
|
|---|
| 57 | SEG_GOOF,
|
|---|
| 58 | };
|
|---|
| 59 |
|
|---|
| 60 | static void obj_bout_line PARAMS ((int));
|
|---|
| 61 |
|
|---|
| 62 | const pseudo_typeS obj_pseudo_table[] =
|
|---|
| 63 | {
|
|---|
| 64 | {"line", obj_bout_line, 0}, /* Source code line number. */
|
|---|
| 65 |
|
|---|
| 66 | /* coff debugging directives. Currently ignored silently. */
|
|---|
| 67 | {"def", s_ignore, 0},
|
|---|
| 68 | {"dim", s_ignore, 0},
|
|---|
| 69 | {"endef", s_ignore, 0},
|
|---|
| 70 | {"ln", s_ignore, 0},
|
|---|
| 71 | {"scl", s_ignore, 0},
|
|---|
| 72 | {"size", s_ignore, 0},
|
|---|
| 73 | {"tag", s_ignore, 0},
|
|---|
| 74 | {"type", s_ignore, 0},
|
|---|
| 75 | {"val", s_ignore, 0},
|
|---|
| 76 |
|
|---|
| 77 | /* other stuff we don't handle */
|
|---|
| 78 | {"ABORT", s_ignore, 0},
|
|---|
| 79 | {"ident", s_ignore, 0},
|
|---|
| 80 |
|
|---|
| 81 | {NULL, NULL, 0} /* End sentinel. */
|
|---|
| 82 | };
|
|---|
| 83 |
|
|---|
| 84 | /* Relocation. */
|
|---|
| 85 |
|
|---|
| 86 | /* Crawl along a fixS chain. Emit the segment's relocations. */
|
|---|
| 87 |
|
|---|
| 88 | void
|
|---|
| 89 | obj_emit_relocations (where, fixP, segment_address_in_file)
|
|---|
| 90 | char **where;
|
|---|
| 91 | fixS *fixP; /* Fixup chain for this segment. */
|
|---|
| 92 | relax_addressT segment_address_in_file;
|
|---|
| 93 | {
|
|---|
| 94 | for (; fixP; fixP = fixP->fx_next)
|
|---|
| 95 | {
|
|---|
| 96 | if (fixP->fx_done == 0
|
|---|
| 97 | || fixP->fx_r_type != NO_RELOC)
|
|---|
| 98 | {
|
|---|
| 99 | symbolS *sym;
|
|---|
| 100 |
|
|---|
| 101 | sym = fixP->fx_addsy;
|
|---|
| 102 | while (sym->sy_value.X_op == O_symbol
|
|---|
| 103 | && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
|
|---|
| 104 | sym = sym->sy_value.X_add_symbol;
|
|---|
| 105 | fixP->fx_addsy = sym;
|
|---|
| 106 |
|
|---|
| 107 | tc_bout_fix_to_chars (*where, fixP, segment_address_in_file);
|
|---|
| 108 | *where += sizeof (struct relocation_info);
|
|---|
| 109 | } /* if there's a symbol */
|
|---|
| 110 | } /* for each fixup */
|
|---|
| 111 | }
|
|---|
| 112 |
|
|---|
| 113 | /* Aout file generation & utilities . */
|
|---|
| 114 |
|
|---|
| 115 | /* Convert a lvalue to machine dependent data. */
|
|---|
| 116 |
|
|---|
| 117 | void
|
|---|
| 118 | obj_header_append (where, headers)
|
|---|
| 119 | char **where;
|
|---|
| 120 | object_headers *headers;
|
|---|
| 121 | {
|
|---|
| 122 | /* Always leave in host byte order. */
|
|---|
| 123 |
|
|---|
| 124 | headers->header.a_talign = section_alignment[SEG_TEXT];
|
|---|
| 125 |
|
|---|
| 126 | /* Force to at least 2. */
|
|---|
| 127 | if (headers->header.a_talign < 2)
|
|---|
| 128 | {
|
|---|
| 129 | headers->header.a_talign = 2;
|
|---|
| 130 | }
|
|---|
| 131 |
|
|---|
| 132 | headers->header.a_dalign = section_alignment[SEG_DATA];
|
|---|
| 133 | headers->header.a_balign = section_alignment[SEG_BSS];
|
|---|
| 134 |
|
|---|
| 135 | headers->header.a_tload = 0;
|
|---|
| 136 | headers->header.a_dload =
|
|---|
| 137 | md_section_align (SEG_DATA, H_GET_TEXT_SIZE (headers));
|
|---|
| 138 |
|
|---|
| 139 | headers->header.a_relaxable = linkrelax;
|
|---|
| 140 |
|
|---|
| 141 | #ifdef CROSS_COMPILE
|
|---|
| 142 | md_number_to_chars (*where, headers->header.a_magic, sizeof (headers->header.a_magic));
|
|---|
| 143 | *where += sizeof (headers->header.a_magic);
|
|---|
| 144 | md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text));
|
|---|
| 145 | *where += sizeof (headers->header.a_text);
|
|---|
| 146 | md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data));
|
|---|
| 147 | *where += sizeof (headers->header.a_data);
|
|---|
| 148 | md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss));
|
|---|
| 149 | *where += sizeof (headers->header.a_bss);
|
|---|
| 150 | md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms));
|
|---|
| 151 | *where += sizeof (headers->header.a_syms);
|
|---|
| 152 | md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry));
|
|---|
| 153 | *where += sizeof (headers->header.a_entry);
|
|---|
| 154 | md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize));
|
|---|
| 155 | *where += sizeof (headers->header.a_trsize);
|
|---|
| 156 | md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize));
|
|---|
| 157 | *where += sizeof (headers->header.a_drsize);
|
|---|
| 158 | md_number_to_chars (*where, headers->header.a_tload, sizeof (headers->header.a_tload));
|
|---|
| 159 | *where += sizeof (headers->header.a_tload);
|
|---|
| 160 | md_number_to_chars (*where, headers->header.a_dload, sizeof (headers->header.a_dload));
|
|---|
| 161 | *where += sizeof (headers->header.a_dload);
|
|---|
| 162 | md_number_to_chars (*where, headers->header.a_talign, sizeof (headers->header.a_talign));
|
|---|
| 163 | *where += sizeof (headers->header.a_talign);
|
|---|
| 164 | md_number_to_chars (*where, headers->header.a_dalign, sizeof (headers->header.a_dalign));
|
|---|
| 165 | *where += sizeof (headers->header.a_dalign);
|
|---|
| 166 | md_number_to_chars (*where, headers->header.a_balign, sizeof (headers->header.a_balign));
|
|---|
| 167 | *where += sizeof (headers->header.a_balign);
|
|---|
| 168 | md_number_to_chars (*where, headers->header.a_relaxable, sizeof (headers->header.a_relaxable));
|
|---|
| 169 | *where += sizeof (headers->header.a_relaxable);
|
|---|
| 170 | #else /* ! CROSS_COMPILE */
|
|---|
| 171 | append (where, (char *) &headers->header, sizeof (headers->header));
|
|---|
| 172 | #endif /* ! CROSS_COMPILE */
|
|---|
| 173 | }
|
|---|
| 174 |
|
|---|
| 175 | void
|
|---|
| 176 | obj_symbol_to_chars (where, symbolP)
|
|---|
| 177 | char **where;
|
|---|
| 178 | symbolS *symbolP;
|
|---|
| 179 | {
|
|---|
| 180 | md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)),
|
|---|
| 181 | S_GET_OFFSET (symbolP),
|
|---|
| 182 | sizeof (S_GET_OFFSET (symbolP)));
|
|---|
| 183 |
|
|---|
| 184 | md_number_to_chars ((char *) &(S_GET_DESC (symbolP)),
|
|---|
| 185 | S_GET_DESC (symbolP),
|
|---|
| 186 | sizeof (S_GET_DESC (symbolP)));
|
|---|
| 187 |
|
|---|
| 188 | md_number_to_chars ((char *) &symbolP->sy_symbol.n_value,
|
|---|
| 189 | S_GET_VALUE (symbolP),
|
|---|
| 190 | sizeof (symbolP->sy_symbol.n_value));
|
|---|
| 191 |
|
|---|
| 192 | append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type));
|
|---|
| 193 | }
|
|---|
| 194 |
|
|---|
| 195 | void
|
|---|
| 196 | obj_emit_symbols (where, symbol_rootP)
|
|---|
| 197 | char **where;
|
|---|
| 198 | symbolS *symbol_rootP;
|
|---|
| 199 | {
|
|---|
| 200 | symbolS *symbolP;
|
|---|
| 201 |
|
|---|
| 202 | /* Emit all symbols left in the symbol chain. */
|
|---|
| 203 | for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
|
|---|
| 204 | {
|
|---|
| 205 | /* Used to save the offset of the name. It is used to point to
|
|---|
| 206 | the string in memory but must be a file offset. */
|
|---|
| 207 | char *temp;
|
|---|
| 208 |
|
|---|
| 209 | temp = S_GET_NAME (symbolP);
|
|---|
| 210 | S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
|
|---|
| 211 |
|
|---|
| 212 | /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
|
|---|
| 213 | if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
|
|---|
| 214 | S_SET_EXTERNAL (symbolP);
|
|---|
| 215 |
|
|---|
| 216 | obj_symbol_to_chars (where, symbolP);
|
|---|
| 217 | S_SET_NAME (symbolP, temp);
|
|---|
| 218 | }
|
|---|
| 219 | }
|
|---|
| 220 |
|
|---|
| 221 | void
|
|---|
| 222 | obj_symbol_new_hook (symbolP)
|
|---|
| 223 | symbolS *symbolP;
|
|---|
| 224 | {
|
|---|
| 225 | S_SET_OTHER (symbolP, 0);
|
|---|
| 226 | S_SET_DESC (symbolP, 0);
|
|---|
| 227 | }
|
|---|
| 228 |
|
|---|
| 229 | static void
|
|---|
| 230 | obj_bout_line (ignore)
|
|---|
| 231 | int ignore ATTRIBUTE_UNUSED;
|
|---|
| 232 | {
|
|---|
| 233 | /* Assume delimiter is part of expression. */
|
|---|
| 234 | /* BSD4.2 as fails with delightful bug, so we are not being
|
|---|
| 235 | incompatible here. */
|
|---|
| 236 | new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
|
|---|
| 237 | demand_empty_rest_of_line ();
|
|---|
| 238 | }
|
|---|
| 239 |
|
|---|
| 240 | void
|
|---|
| 241 | obj_read_begin_hook ()
|
|---|
| 242 | {
|
|---|
| 243 | }
|
|---|
| 244 |
|
|---|
| 245 | void
|
|---|
| 246 | obj_crawl_symbol_chain (headers)
|
|---|
| 247 | object_headers *headers;
|
|---|
| 248 | {
|
|---|
| 249 | symbolS **symbolPP;
|
|---|
| 250 | symbolS *symbolP;
|
|---|
| 251 | int symbol_number = 0;
|
|---|
| 252 |
|
|---|
| 253 | tc_crawl_symbol_chain (headers);
|
|---|
| 254 |
|
|---|
| 255 | symbolPP = &symbol_rootP; /* -> last symbol chain link. */
|
|---|
| 256 | while ((symbolP = *symbolPP) != NULL)
|
|---|
| 257 | {
|
|---|
| 258 | if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA))
|
|---|
| 259 | {
|
|---|
| 260 | S_SET_SEGMENT (symbolP, SEG_TEXT);
|
|---|
| 261 | } /* if pusing data into text */
|
|---|
| 262 |
|
|---|
| 263 | resolve_symbol_value (symbolP);
|
|---|
| 264 |
|
|---|
| 265 | /* Skip symbols which were equated to undefined or common
|
|---|
| 266 | symbols. */
|
|---|
| 267 | if (symbolP->sy_value.X_op == O_symbol
|
|---|
| 268 | && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)))
|
|---|
| 269 | {
|
|---|
| 270 | *symbolPP = symbol_next (symbolP);
|
|---|
| 271 | continue;
|
|---|
| 272 | }
|
|---|
| 273 |
|
|---|
| 274 | /* OK, here is how we decide which symbols go out into the
|
|---|
| 275 | brave new symtab. Symbols that do are:
|
|---|
| 276 |
|
|---|
| 277 | * symbols with no name (stabd's?)
|
|---|
| 278 | * symbols with debug info in their N_TYPE
|
|---|
| 279 |
|
|---|
| 280 | Symbols that don't are:
|
|---|
| 281 | * symbols that are registers
|
|---|
| 282 | * symbols with \1 as their 3rd character (numeric labels)
|
|---|
| 283 | * "local labels" as defined by S_LOCAL_NAME(name)
|
|---|
| 284 | if the -L switch was passed to gas.
|
|---|
| 285 |
|
|---|
| 286 | All other symbols are output. We complain if a deleted
|
|---|
| 287 | symbol was marked external. */
|
|---|
| 288 |
|
|---|
| 289 | if (1
|
|---|
| 290 | && !S_IS_REGISTER (symbolP)
|
|---|
| 291 | && (!S_GET_NAME (symbolP)
|
|---|
| 292 | || S_IS_DEBUG (symbolP)
|
|---|
| 293 | #ifdef TC_I960
|
|---|
| 294 | /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */
|
|---|
| 295 | || !S_IS_DEFINED (symbolP)
|
|---|
| 296 | || S_IS_EXTERNAL (symbolP)
|
|---|
| 297 | #endif /* TC_I960 */
|
|---|
| 298 | || (S_GET_NAME (symbolP)[0] != '\001'
|
|---|
| 299 | && (flag_keep_locals || !S_LOCAL_NAME (symbolP)))))
|
|---|
| 300 | {
|
|---|
| 301 | symbolP->sy_number = symbol_number++;
|
|---|
| 302 |
|
|---|
| 303 | /* The + 1 after strlen account for the \0 at the end of
|
|---|
| 304 | each string. */
|
|---|
| 305 | if (!S_IS_STABD (symbolP))
|
|---|
| 306 | {
|
|---|
| 307 | /* Ordinary case. */
|
|---|
| 308 | symbolP->sy_name_offset = string_byte_count;
|
|---|
| 309 | string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
|
|---|
| 310 | }
|
|---|
| 311 | else /* .Stabd case. */
|
|---|
| 312 | symbolP->sy_name_offset = 0;
|
|---|
| 313 | symbolPP = &(symbolP->sy_next);
|
|---|
| 314 | }
|
|---|
| 315 | else
|
|---|
| 316 | {
|
|---|
| 317 | if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
|
|---|
| 318 | {
|
|---|
| 319 | as_bad (_("Local symbol %s never defined"),
|
|---|
| 320 | S_GET_NAME (symbolP));
|
|---|
| 321 | } /* Oops. */
|
|---|
| 322 |
|
|---|
| 323 | /* Unhook it from the chain. */
|
|---|
| 324 | *symbolPP = symbol_next (symbolP);
|
|---|
| 325 | } /* if this symbol should be in the output */
|
|---|
| 326 | } /* for each symbol */
|
|---|
| 327 |
|
|---|
| 328 | H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
|
|---|
| 329 | }
|
|---|
| 330 |
|
|---|
| 331 | /* Find strings by crawling along symbol table chain. */
|
|---|
| 332 |
|
|---|
| 333 | void
|
|---|
| 334 | obj_emit_strings (where)
|
|---|
| 335 | char **where;
|
|---|
| 336 | {
|
|---|
| 337 | symbolS *symbolP;
|
|---|
| 338 |
|
|---|
| 339 | #ifdef CROSS_COMPILE
|
|---|
| 340 | /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
|
|---|
| 341 | md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count));
|
|---|
| 342 | *where += sizeof (string_byte_count);
|
|---|
| 343 | #else /* CROSS_COMPILE */
|
|---|
| 344 | append (where, (char *) &string_byte_count,
|
|---|
| 345 | (unsigned long) sizeof (string_byte_count));
|
|---|
| 346 | #endif /* CROSS_COMPILE */
|
|---|
| 347 |
|
|---|
| 348 | for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
|
|---|
| 349 | {
|
|---|
| 350 | if (S_GET_NAME (symbolP))
|
|---|
| 351 | append (where, S_GET_NAME (symbolP),
|
|---|
| 352 | (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
|
|---|
| 353 | } /* Walk symbol chain. */
|
|---|
| 354 | }
|
|---|