1 /* BFD back-end for RISC iX (Acorn, arm) binaries. 2 Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002 3 Free Software Foundation, Inc. 4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) 5 6 This file is part of BFD, the Binary File Descriptor library. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 21 22 /* RISC iX overloads the MAGIC field to indicate more than just the usual 23 [ZNO]MAGIC values. Also included are squeezing information and 24 shared library usage. */ 25 26 /* The following come from the man page. */ 27 #define SHLIBLEN 60 28 29 #define MF_IMPURE 00200 30 #define MF_SQUEEZED 01000 31 #define MF_USES_SL 02000 32 #define MF_IS_SL 04000 33 34 /* Common combinations. */ 35 #define IMAGIC (MF_IMPURE|ZMAGIC) /* Demand load (impure text) */ 36 #define SPOMAGIC (MF_USES_SL|OMAGIC) /* OMAGIC with large header */ 37 /* -- may contain a ref to a */ 38 /* shared lib required by the */ 39 /* object. */ 40 #define SLOMAGIC (MF_IS_SL|OMAGIC) /* A reference to a shared library */ 41 /* The text portion of the object */ 42 /* contains "overflow text" from */ 43 /* the shared library to be linked */ 44 /* in with an object */ 45 #define QMAGIC (MF_SQUEEZED|ZMAGIC) /* Sqeezed demand paged. */ 46 /* NOTE: This interpretation of */ 47 /* QMAGIC seems to be at variance */ 48 /* With that used on other */ 49 /* architectures. */ 50 #define SPZMAGIC (MF_USES_SL|ZMAGIC) /* program which uses sl */ 51 #define SPQMAGIC (MF_USES_SL|QMAGIC) /* sqeezed ditto */ 52 #define SLZMAGIC (MF_IS_SL|ZMAGIC) /* shared lib part of prog */ 53 #define SLPZMAGIC (MF_USES_SL|SLZMAGIC) /* sl which uses another */ 54 55 #define N_SHARED_LIB(x) ((x).a_info & MF_USES_SL) 56 57 /* Only a pure OMAGIC file has the minimal header */ 58 #define N_TXTOFF(x) \ 59 ((x).a_info == OMAGIC \ 60 ? 32 \ 61 : (N_MAGIC(x) == ZMAGIC \ 62 ? TARGET_PAGE_SIZE \ 63 : 999)) 64 65 #define N_TXTADDR(x) \ 66 (N_MAGIC(x) != ZMAGIC \ 67 ? (bfd_vma) 0 /* object file or NMAGIC */ \ 68 /* Programs with shared libs are loaded at the first page after all the \ 69 text segments of the shared library programs. Without looking this \ 70 up we can't know exactly what the address will be. A reasonable guess \ 71 is that a_entry will be in the first page of the executable. */ \ 72 : (N_SHARED_LIB(x) \ 73 ? ((x).a_entry & ~(bfd_vma) (TARGET_PAGE_SIZE - 1)) \ 74 : (bfd_vma) TEXT_START_ADDR)) 75 76 #define N_SYMOFF(x) \ 77 (N_TXTOFF (x) + (x).a_text + (x).a_data + (x).a_trsize + (x).a_drsize) 78 79 #define N_STROFF(x) (N_SYMOFF (x) + (x).a_syms) 80 81 #define TEXT_START_ADDR 32768 82 #define TARGET_PAGE_SIZE 32768 83 #define SEGMENT_SIZE TARGET_PAGE_SIZE 84 #define DEFAULT_ARCH bfd_arch_arm 85 86 /* Do not "beautify" the CONCAT* macro args. Traditional C will not 87 remove whitespace added here, and thus will fail to concatenate 88 the tokens. */ 89 #define MY(OP) CONCAT2 (riscix_,OP) 90 #define TARGETNAME "a.out-riscix" 91 #define N_BADMAG(x) ((((x).a_info & ~007200) != ZMAGIC) && \ 92 (((x).a_info & ~006000) != OMAGIC) && \ 93 ((x).a_info != NMAGIC)) 94 #define N_MAGIC(x) ((x).a_info & ~07200) 95 96 #include "bfd.h" 97 #include "sysdep.h" 98 #include "libbfd.h" 99 100 #define WRITE_HEADERS(abfd, execp) \ 101 { \ 102 bfd_size_type text_size; /* dummy vars */ \ 103 file_ptr text_end; \ 104 if (adata(abfd).magic == undecided_magic) \ 105 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \ 106 \ 107 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \ 108 execp->a_entry = bfd_get_start_address (abfd); \ 109 \ 110 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \ 111 obj_reloc_entry_size (abfd)); \ 112 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \ 113 obj_reloc_entry_size (abfd)); \ 114 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \ 115 \ 116 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \ 117 || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \ 118 abfd) != EXEC_BYTES_SIZE) \ 119 return FALSE; \ 120 /* Now write out reloc info, followed by syms and strings */ \ 121 \ 122 if (bfd_get_outsymbols (abfd) != (asymbol **) NULL \ 123 && bfd_get_symcount (abfd) != 0) \ 124 { \ 125 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) != 0) \ 126 return FALSE; \ 127 \ 128 if (! NAME(aout,write_syms) (abfd)) return FALSE; \ 129 \ 130 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) != 0) \ 131 return FALSE; \ 132 \ 133 if (! riscix_squirt_out_relocs (abfd, obj_textsec (abfd))) \ 134 return FALSE; \ 135 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) != 0) \ 136 return FALSE; \ 137 \ 138 if (!NAME(aout,squirt_out_relocs) (abfd, obj_datasec (abfd))) \ 139 return FALSE; \ 140 } \ 141 } 142 143 #include "libaout.h" 144 #include "aout/aout64.h" 145 146 static bfd_reloc_status_type 147 riscix_fix_pcrel_26_done PARAMS ((bfd *, arelent *, asymbol *, PTR, 148 asection *, bfd *, char **)); 149 150 static bfd_reloc_status_type 151 riscix_fix_pcrel_26 PARAMS ((bfd *, arelent *, asymbol *, PTR, 152 asection *, bfd *, char **)); 153 static const bfd_target * 154 MY (object_p) PARAMS ((bfd *)); 155 156 reloc_howto_type * 157 riscix_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); 158 159 void 160 riscix_swap_std_reloc_out PARAMS ((bfd *, arelent *, struct reloc_std_external *)); 161 162 bfd_boolean 163 riscix_squirt_out_relocs PARAMS ((bfd *, asection *)); 164 165 long 166 MY (canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, asymbol **)); 167 168 const bfd_target * 169 riscix_some_aout_object_p PARAMS ((bfd *, struct internal_exec *, const bfd_target *(*) (bfd *))); 170 171 172 static reloc_howto_type riscix_std_reloc_howto[] = { 173 /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ 174 HOWTO( 0, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,0,"8", TRUE, 0x000000ff,0x000000ff, FALSE), 175 HOWTO( 1, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,0,"16", TRUE, 0x0000ffff,0x0000ffff, FALSE), 176 HOWTO( 2, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,"32", TRUE, 0xffffffff,0xffffffff, FALSE), 177 HOWTO( 3, 2, 3, 26, TRUE, 0, complain_overflow_signed, riscix_fix_pcrel_26 , "ARM26", TRUE, 0x00ffffff,0x00ffffff, FALSE), 178 HOWTO( 4, 0, 0, 8, TRUE, 0, complain_overflow_signed, 0,"DISP8", TRUE, 0x000000ff,0x000000ff, TRUE), 179 HOWTO( 5, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0,"DISP16", TRUE, 0x0000ffff,0x0000ffff, TRUE), 180 HOWTO( 6, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0,"DISP32", TRUE, 0xffffffff,0xffffffff, TRUE), 181 HOWTO( 7, 2, 3, 26, FALSE, 0, complain_overflow_signed, riscix_fix_pcrel_26_done, "ARM26D",TRUE,0x00ffffff,0x00ffffff, FALSE), 182 EMPTY_HOWTO (-1), 183 HOWTO( 9, 0, -1, 16, FALSE, 0, complain_overflow_bitfield,0,"NEG16", TRUE, 0x0000ffff,0x0000ffff, FALSE), 184 HOWTO( 10, 0, -2, 32, FALSE, 0, complain_overflow_bitfield,0,"NEG32", TRUE, 0xffffffff,0xffffffff, FALSE) 185 }; 186 187 #define RISCIX_TABLE_SIZE \ 188 (sizeof (riscix_std_reloc_howto) / sizeof (reloc_howto_type)) 189 190 static bfd_reloc_status_type 191 riscix_fix_pcrel_26_done (abfd, reloc_entry, symbol, data, input_section, 192 output_bfd, error_message) 193 bfd *abfd ATTRIBUTE_UNUSED; 194 arelent *reloc_entry ATTRIBUTE_UNUSED; 195 asymbol *symbol ATTRIBUTE_UNUSED; 196 PTR data ATTRIBUTE_UNUSED; 197 asection *input_section ATTRIBUTE_UNUSED; 198 bfd *output_bfd ATTRIBUTE_UNUSED; 199 char **error_message ATTRIBUTE_UNUSED; 200 { 201 /* This is dead simple at present. */ 202 return bfd_reloc_ok; 203 } 204 205 static bfd_reloc_status_type 206 riscix_fix_pcrel_26 (abfd, reloc_entry, symbol, data, input_section, 207 output_bfd, error_message) 208 bfd *abfd; 209 arelent *reloc_entry; 210 asymbol *symbol; 211 PTR data; 212 asection *input_section; 213 bfd *output_bfd; 214 char **error_message ATTRIBUTE_UNUSED; 215 { 216 bfd_vma relocation; 217 bfd_size_type addr = reloc_entry->address; 218 long target = bfd_get_32 (abfd, (bfd_byte *) data + addr); 219 bfd_reloc_status_type flag = bfd_reloc_ok; 220 221 /* If this is an undefined symbol, return error */ 222 if (symbol->section == &bfd_und_section 223 && (symbol->flags & BSF_WEAK) == 0) 224 return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined; 225 226 /* If the sections are different, and we are doing a partial relocation, 227 just ignore it for now. */ 228 if (symbol->section->name != input_section->name 229 && output_bfd != (bfd *)NULL) 230 return bfd_reloc_continue; 231 232 relocation = (target & 0x00ffffff) << 2; 233 relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend */ 234 relocation += symbol->value; 235 relocation += symbol->section->output_section->vma; 236 relocation += symbol->section->output_offset; 237 relocation += reloc_entry->addend; 238 relocation -= input_section->output_section->vma; 239 relocation -= input_section->output_offset; 240 relocation -= addr; 241 if (relocation & 3) 242 return bfd_reloc_overflow; 243 244 /* Check for overflow */ 245 if (relocation & 0x02000000) 246 { 247 if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff) 248 flag = bfd_reloc_overflow; 249 } 250 else if (relocation & ~ (bfd_vma) 0x03ffffff) 251 flag = bfd_reloc_overflow; 252 253 target &= ~0x00ffffff; 254 target |= (relocation >> 2) & 0x00ffffff; 255 bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr); 256 257 /* Now the ARM magic... Change the reloc type so that it is marked as done. 258 Strictly this is only necessary if we are doing a partial relocation. */ 259 reloc_entry->howto = &riscix_std_reloc_howto[7]; 260 261 return flag; 262 } 263 264 reloc_howto_type * 265 riscix_reloc_type_lookup (abfd, code) 266 bfd *abfd; 267 bfd_reloc_code_real_type code; 268 { 269 #define ASTD(i,j) case i: return &riscix_std_reloc_howto[j] 270 if (code == BFD_RELOC_CTOR) 271 switch (bfd_get_arch_info (abfd)->bits_per_address) 272 { 273 case 32: 274 code = BFD_RELOC_32; 275 break; 276 default: return (reloc_howto_type *) NULL; 277 } 278 279 switch (code) 280 { 281 ASTD (BFD_RELOC_16, 1); 282 ASTD (BFD_RELOC_32, 2); 283 ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3); 284 ASTD (BFD_RELOC_8_PCREL, 4); 285 ASTD (BFD_RELOC_16_PCREL, 5); 286 ASTD (BFD_RELOC_32_PCREL, 6); 287 default: return (reloc_howto_type *) NULL; 288 } 289 } 290 291 #define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 292 #define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols 293 #define MY_final_link_callback should_not_be_used 294 #define MY_bfd_final_link _bfd_generic_final_link 295 296 #define MY_bfd_reloc_type_lookup riscix_reloc_type_lookup 297 #define MY_canonicalize_reloc riscix_canonicalize_reloc 298 #define MY_object_p riscix_object_p 299 300 static const bfd_target *riscix_callback PARAMS ((bfd *)); 301 302 void 303 riscix_swap_std_reloc_out (abfd, g, natptr) 304 bfd *abfd; 305 arelent *g; 306 struct reloc_std_external *natptr; 307 { 308 int r_index; 309 asymbol *sym = *(g->sym_ptr_ptr); 310 int r_extern; 311 int r_length; 312 int r_pcrel; 313 int r_neg = 0; /* Negative relocs use the BASEREL bit. */ 314 asection *output_section = sym->section->output_section; 315 316 PUT_WORD(abfd, g->address, natptr->r_address); 317 318 r_length = g->howto->size ; /* Size as a power of two */ 319 if (r_length < 0) 320 { 321 r_length = -r_length; 322 r_neg = 1; 323 } 324 325 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ 326 327 /* For RISC iX, in pc-relative relocs the r_pcrel bit means that the 328 relocation has been done already (Only for the 26-bit one I think)???!!! 329 */ 330 331 if (r_length == 3) 332 r_pcrel = r_pcrel ? 0 : 1; 333 334 #if 0 335 /* For a standard reloc, the addend is in the object file. */ 336 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma; 337 #endif 338 339 /* name was clobbered by aout_write_syms to be symbol index */ 340 341 /* If this relocation is relative to a symbol then set the 342 r_index to the symbols index, and the r_extern bit. 343 344 Absolute symbols can come in in two ways, either as an offset 345 from the abs section, or as a symbol which has an abs value. 346 check for that here 347 */ 348 349 if (bfd_is_com_section (output_section) 350 || output_section == &bfd_abs_section 351 || output_section == &bfd_und_section) 352 { 353 if (bfd_abs_section.symbol == sym) 354 { 355 /* Whoops, looked like an abs symbol, but is really an offset 356 from the abs section */ 357 r_index = 0; 358 r_extern = 0; 359 } 360 else 361 { 362 /* Fill in symbol */ 363 r_extern = 1; 364 r_index = (*g->sym_ptr_ptr)->udata.i; 365 } 366 } 367 else 368 { 369 /* Just an ordinary section */ 370 r_extern = 0; 371 r_index = output_section->target_index; 372 } 373 374 /* now the fun stuff */ 375 if (bfd_header_big_endian (abfd)) 376 { 377 natptr->r_index[0] = r_index >> 16; 378 natptr->r_index[1] = r_index >> 8; 379 natptr->r_index[2] = r_index; 380 natptr->r_type[0] = 381 ( (r_extern ? RELOC_STD_BITS_EXTERN_BIG: 0) 382 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG: 0) 383 | (r_neg ? RELOC_STD_BITS_BASEREL_BIG: 0) 384 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG)); 385 } 386 else 387 { 388 natptr->r_index[2] = r_index >> 16; 389 natptr->r_index[1] = r_index >> 8; 390 natptr->r_index[0] = r_index; 391 natptr->r_type[0] = 392 ( (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE: 0) 393 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE: 0) 394 | (r_neg ? RELOC_STD_BITS_BASEREL_LITTLE: 0) 395 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)); 396 } 397 } 398 399 bfd_boolean 400 riscix_squirt_out_relocs (abfd, section) 401 bfd *abfd; 402 asection *section; 403 { 404 arelent **generic; 405 unsigned char *native, *natptr; 406 size_t each_size; 407 408 unsigned int count = section->reloc_count; 409 bfd_size_type natsize; 410 411 if (count == 0) 412 return TRUE; 413 414 each_size = obj_reloc_entry_size (abfd); 415 natsize = each_size; 416 natsize *= count; 417 native = (unsigned char *) bfd_zalloc (abfd, natsize); 418 if (!native) 419 return FALSE; 420 421 generic = section->orelocation; 422 423 for (natptr = native; 424 count != 0; 425 --count, natptr += each_size, ++generic) 426 riscix_swap_std_reloc_out (abfd, *generic, 427 (struct reloc_std_external *) natptr); 428 429 if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize) 430 { 431 bfd_release (abfd, native); 432 return FALSE; 433 } 434 435 bfd_release (abfd, native); 436 return TRUE; 437 } 438 439 /* 440 * This is just like the standard aoutx.h version but we need to do our 441 * own mapping of external reloc type values to howto entries. 442 */ 443 long 444 MY(canonicalize_reloc) (abfd, section, relptr, symbols) 445 bfd *abfd; 446 sec_ptr section; 447 arelent **relptr; 448 asymbol **symbols; 449 { 450 arelent *tblptr = section->relocation; 451 unsigned int count, c; 452 extern reloc_howto_type NAME(aout,std_howto_table)[]; 453 454 /* If we have already read in the relocation table, return the values. */ 455 if (section->flags & SEC_CONSTRUCTOR) { 456 arelent_chain *chain = section->constructor_chain; 457 458 for (count = 0; count < section->reloc_count; count++) { 459 *relptr++ = &chain->relent; 460 chain = chain->next; 461 } 462 *relptr = 0; 463 return section->reloc_count; 464 } 465 if (tblptr && section->reloc_count) { 466 for (count = 0; count++ < section->reloc_count;) 467 *relptr++ = tblptr++; 468 *relptr = 0; 469 return section->reloc_count; 470 } 471 472 if (!NAME(aout,slurp_reloc_table) (abfd, section, symbols)) 473 return -1; 474 tblptr = section->relocation; 475 476 /* fix up howto entries */ 477 for (count = 0; count++ < section->reloc_count;) 478 { 479 c = tblptr->howto - NAME(aout,std_howto_table); 480 BFD_ASSERT (c < RISCIX_TABLE_SIZE); 481 tblptr->howto = &riscix_std_reloc_howto[c]; 482 483 *relptr++ = tblptr++; 484 } 485 *relptr = 0; 486 return section->reloc_count; 487 } 488 489 /* This is the same as NAME(aout,some_aout_object_p), but has different 490 expansions of the macro definitions. */ 491 492 const bfd_target * 493 riscix_some_aout_object_p (abfd, execp, callback_to_real_object_p) 494 bfd *abfd; 495 struct internal_exec *execp; 496 const bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *)); 497 { 498 struct aout_data_struct *rawptr, *oldrawptr; 499 const bfd_target *result; 500 bfd_size_type amt = sizeof (struct aout_data_struct); 501 502 rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt); 503 504 if (rawptr == NULL) 505 return 0; 506 507 oldrawptr = abfd->tdata.aout_data; 508 abfd->tdata.aout_data = rawptr; 509 510 /* Copy the contents of the old tdata struct. 511 In particular, we want the subformat, since for hpux it was set in 512 hp300hpux.c:swap_exec_header_in and will be used in 513 hp300hpux.c:callback. */ 514 if (oldrawptr != NULL) 515 *abfd->tdata.aout_data = *oldrawptr; 516 517 abfd->tdata.aout_data->a.hdr = &rawptr->e; 518 *(abfd->tdata.aout_data->a.hdr) = *execp; /* Copy in the internal_exec 519 struct */ 520 execp = abfd->tdata.aout_data->a.hdr; 521 522 /* Set the file flags */ 523 abfd->flags = BFD_NO_FLAGS; 524 if (execp->a_drsize || execp->a_trsize) 525 abfd->flags |= HAS_RELOC; 526 /* Setting of EXEC_P has been deferred to the bottom of this function */ 527 if (execp->a_syms) 528 abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; 529 if (N_DYNAMIC(*execp)) 530 abfd->flags |= DYNAMIC; 531 532 if ((execp->a_info & MF_SQUEEZED) != 0) /* Squeezed files aren't supported 533 (yet)! */ 534 { 535 bfd_set_error (bfd_error_wrong_format); 536 return NULL; 537 } 538 else if ((execp->a_info & MF_IS_SL) != 0) /* Nor are shared libraries */ 539 { 540 bfd_set_error (bfd_error_wrong_format); 541 return NULL; 542 } 543 else if (N_MAGIC (*execp) == ZMAGIC) 544 { 545 abfd->flags |= D_PAGED | WP_TEXT; 546 adata (abfd).magic = z_magic; 547 } 548 else if (N_MAGIC (*execp) == NMAGIC) 549 { 550 abfd->flags |= WP_TEXT; 551 adata (abfd).magic = n_magic; 552 } 553 else if (N_MAGIC (*execp) == OMAGIC) 554 adata (abfd).magic = o_magic; 555 else 556 { 557 /* Should have been checked with N_BADMAG before this routine 558 was called. */ 559 abort (); 560 } 561 562 bfd_get_start_address (abfd) = execp->a_entry; 563 564 obj_aout_symbols (abfd) = (aout_symbol_type *)NULL; 565 bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist); 566 567 /* The default relocation entry size is that of traditional V7 Unix. */ 568 obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; 569 570 /* The default symbol entry size is that of traditional Unix. */ 571 obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE; 572 573 obj_aout_external_syms (abfd) = NULL; 574 obj_aout_external_strings (abfd) = NULL; 575 obj_aout_sym_hashes (abfd) = NULL; 576 577 if (! NAME(aout,make_sections) (abfd)) 578 return NULL; 579 580 obj_datasec (abfd)->_raw_size = execp->a_data; 581 obj_bsssec (abfd)->_raw_size = execp->a_bss; 582 583 obj_textsec (abfd)->flags = 584 (execp->a_trsize != 0 585 ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) 586 : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)); 587 obj_datasec (abfd)->flags = 588 (execp->a_drsize != 0 589 ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) 590 : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS)); 591 obj_bsssec (abfd)->flags = SEC_ALLOC; 592 593 result = (*callback_to_real_object_p) (abfd); 594 595 #if defined(MACH) || defined(STAT_FOR_EXEC) 596 /* The original heuristic doesn't work in some important cases. The 597 * a.out file has no information about the text start address. For 598 * files (like kernels) linked to non-standard addresses (ld -Ttext 599 * nnn) the entry point may not be between the default text start 600 * (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size 601 * This is not just a mach issue. Many kernels are loaded at non 602 * standard addresses. 603 */ 604 { 605 struct stat stat_buf; 606 if (abfd->iostream != NULL 607 && (abfd->flags & BFD_IN_MEMORY) == 0 608 && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0) 609 && ((stat_buf.st_mode & 0111) != 0)) 610 abfd->flags |= EXEC_P; 611 } 612 #else /* ! MACH */ 613 /* Now that the segment addresses have been worked out, take a better 614 guess at whether the file is executable. If the entry point 615 is within the text segment, assume it is. (This makes files 616 executable even if their entry point address is 0, as long as 617 their text starts at zero.) 618 619 At some point we should probably break down and stat the file and 620 declare it executable if (one of) its 'x' bits are on... */ 621 if ((execp->a_entry >= obj_textsec(abfd)->vma) && 622 (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size)) 623 abfd->flags |= EXEC_P; 624 #endif /* MACH */ 625 if (result) 626 { 627 } 628 else 629 { 630 free (rawptr); 631 abfd->tdata.aout_data = oldrawptr; 632 } 633 return result; 634 } 635 636 static const bfd_target * 637 MY(object_p) (abfd) 638 bfd *abfd; 639 { 640 struct external_exec exec_bytes; /* Raw exec header from file */ 641 struct internal_exec exec; /* Cleaned-up exec header */ 642 const bfd_target *target; 643 644 if (bfd_bread ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd) 645 != EXEC_BYTES_SIZE) 646 { 647 if (bfd_get_error () != bfd_error_system_call) 648 bfd_set_error (bfd_error_wrong_format); 649 return 0; 650 } 651 652 exec.a_info = H_GET_32 (abfd, exec_bytes.e_info); 653 654 if (N_BADMAG (exec)) return 0; 655 #ifdef MACHTYPE_OK 656 if (!(MACHTYPE_OK (N_MACHTYPE (exec)))) return 0; 657 #endif 658 659 NAME(aout,swap_exec_header_in) (abfd, &exec_bytes, &exec); 660 661 target = riscix_some_aout_object_p (abfd, &exec, MY(callback)); 662 663 return target; 664 } 665 666 #include "aout-target.h" 667