1 /* BFD back-end for i386 a.out binaries under LynxOS. 2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 2001, 2002, 2003 3 Free Software Foundation, Inc. 4 5 This file is part of BFD, the Binary File Descriptor library. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 20 21 #define N_SHARED_LIB(x) 0 22 23 #define TEXT_START_ADDR 0 24 #define TARGET_PAGE_SIZE 4096 25 #define SEGMENT_SIZE TARGET_PAGE_SIZE 26 #define DEFAULT_ARCH bfd_arch_i386 27 28 /* Do not "beautify" the CONCAT* macro args. Traditional C will not 29 remove whitespace added here, and thus will fail to concatenate 30 the tokens. */ 31 #define MY(OP) CONCAT2 (i386lynx_aout_,OP) 32 #define TARGETNAME "a.out-i386-lynx" 33 34 #include "bfd.h" 35 #include "sysdep.h" 36 #include "libbfd.h" 37 38 #ifndef WRITE_HEADERS 39 #define WRITE_HEADERS(abfd, execp) \ 40 { \ 41 bfd_size_type text_size; /* dummy vars */ \ 42 file_ptr text_end; \ 43 if (adata(abfd).magic == undecided_magic) \ 44 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \ 45 \ 46 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \ 47 execp->a_entry = bfd_get_start_address (abfd); \ 48 \ 49 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \ 50 obj_reloc_entry_size (abfd)); \ 51 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \ 52 obj_reloc_entry_size (abfd)); \ 53 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \ 54 \ 55 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \ 56 || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \ 57 abfd) != EXEC_BYTES_SIZE) \ 58 return FALSE; \ 59 /* Now write out reloc info, followed by syms and strings */ \ 60 \ 61 if (bfd_get_symcount (abfd) != 0) \ 62 { \ 63 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) \ 64 != 0) \ 65 return FALSE; \ 66 \ 67 if (! NAME(aout,write_syms) (abfd)) return FALSE; \ 68 \ 69 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \ 70 != 0) \ 71 return FALSE; \ 72 \ 73 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \ 74 return FALSE; \ 75 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) \ 76 != 0) \ 77 return 0; \ 78 \ 79 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \ 80 return FALSE; \ 81 } \ 82 } 83 #endif 84 85 #include "libaout.h" 86 #include "aout/aout64.h" 87 88 void NAME (lynx,swap_std_reloc_out) 89 PARAMS ((bfd *, arelent *, struct reloc_std_external *)); 90 void NAME (lynx,swap_ext_reloc_out) 91 PARAMS ((bfd *, arelent *, struct reloc_ext_external *)); 92 void NAME (lynx,swap_ext_reloc_in) 93 PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **, 94 bfd_size_type)); 95 void NAME (lynx,swap_std_reloc_in) 96 PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **, 97 bfd_size_type)); 98 bfd_boolean NAME (lynx,slurp_reloc_table) 99 PARAMS ((bfd *, sec_ptr, asymbol **)); 100 bfd_boolean NAME (lynx,squirt_out_relocs) 101 PARAMS ((bfd *, asection *)); 102 long NAME (lynx,canonicalize_reloc) 103 PARAMS ((bfd *, sec_ptr, arelent **, asymbol **)); 104 105 #ifdef LYNX_CORE 106 107 char *lynx_core_file_failing_command (); 108 int lynx_core_file_failing_signal (); 109 bfd_boolean lynx_core_file_matches_executable_p (); 110 const bfd_target *lynx_core_file_p (); 111 112 #define MY_core_file_failing_command lynx_core_file_failing_command 113 #define MY_core_file_failing_signal lynx_core_file_failing_signal 114 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p 115 #define MY_core_file_p lynx_core_file_p 116 117 #endif /* LYNX_CORE */ 118 119 120 #define KEEPIT udata.i 121 122 extern reloc_howto_type aout_32_ext_howto_table[]; 123 extern reloc_howto_type aout_32_std_howto_table[]; 124 125 /* Standard reloc stuff */ 126 /* Output standard relocation information to a file in target byte order. */ 127 128 void 129 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr) 130 bfd *abfd; 131 arelent *g; 132 struct reloc_std_external *natptr; 133 { 134 int r_index; 135 asymbol *sym = *(g->sym_ptr_ptr); 136 int r_extern; 137 unsigned int r_length; 138 int r_pcrel; 139 int r_baserel, r_jmptable, r_relative; 140 unsigned int r_addend; 141 asection *output_section = sym->section->output_section; 142 143 PUT_WORD (abfd, g->address, natptr->r_address); 144 145 r_length = g->howto->size; /* Size as a power of two */ 146 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ 147 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */ 148 r_baserel = 0; 149 r_jmptable = 0; 150 r_relative = 0; 151 152 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma; 153 154 /* name was clobbered by aout_write_syms to be symbol index */ 155 156 /* If this relocation is relative to a symbol then set the 157 r_index to the symbols index, and the r_extern bit. 158 159 Absolute symbols can come in in two ways, either as an offset 160 from the abs section, or as a symbol which has an abs value. 161 check for that here 162 */ 163 164 165 if (bfd_is_com_section (output_section) 166 || bfd_is_abs_section (output_section) 167 || bfd_is_und_section (output_section)) 168 { 169 if (bfd_abs_section_ptr->symbol == sym) 170 { 171 /* Whoops, looked like an abs symbol, but is really an offset 172 from the abs section */ 173 r_index = 0; 174 r_extern = 0; 175 } 176 else 177 { 178 /* Fill in symbol */ 179 r_extern = 1; 180 r_index = (*g->sym_ptr_ptr)->KEEPIT; 181 } 182 } 183 else 184 { 185 /* Just an ordinary section */ 186 r_extern = 0; 187 r_index = output_section->target_index; 188 } 189 190 /* now the fun stuff */ 191 if (bfd_header_big_endian (abfd)) 192 { 193 natptr->r_index[0] = r_index >> 16; 194 natptr->r_index[1] = r_index >> 8; 195 natptr->r_index[2] = r_index; 196 natptr->r_type[0] = 197 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) 198 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) 199 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) 200 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) 201 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) 202 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG); 203 } 204 else 205 { 206 natptr->r_index[2] = r_index >> 16; 207 natptr->r_index[1] = r_index >> 8; 208 natptr->r_index[0] = r_index; 209 natptr->r_type[0] = 210 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0) 211 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0) 212 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0) 213 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0) 214 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0) 215 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE); 216 } 217 } 218 219 220 /* Extended stuff */ 221 /* Output extended relocation information to a file in target byte order. */ 222 223 void 224 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr) 225 bfd *abfd; 226 arelent *g; 227 register struct reloc_ext_external *natptr; 228 { 229 int r_index; 230 int r_extern; 231 unsigned int r_type; 232 unsigned int r_addend; 233 asymbol *sym = *(g->sym_ptr_ptr); 234 asection *output_section = sym->section->output_section; 235 236 PUT_WORD (abfd, g->address, natptr->r_address); 237 238 r_type = (unsigned int) g->howto->type; 239 240 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma; 241 242 243 /* If this relocation is relative to a symbol then set the 244 r_index to the symbols index, and the r_extern bit. 245 246 Absolute symbols can come in in two ways, either as an offset 247 from the abs section, or as a symbol which has an abs value. 248 check for that here 249 */ 250 251 if (bfd_is_com_section (output_section) 252 || bfd_is_abs_section (output_section) 253 || bfd_is_und_section (output_section)) 254 { 255 if (bfd_abs_section_ptr->symbol == sym) 256 { 257 /* Whoops, looked like an abs symbol, but is really an offset 258 from the abs section */ 259 r_index = 0; 260 r_extern = 0; 261 } 262 else 263 { 264 r_extern = 1; 265 r_index = (*g->sym_ptr_ptr)->KEEPIT; 266 } 267 } 268 else 269 { 270 /* Just an ordinary section */ 271 r_extern = 0; 272 r_index = output_section->target_index; 273 } 274 275 276 /* now the fun stuff */ 277 if (bfd_header_big_endian (abfd)) 278 { 279 natptr->r_index[0] = r_index >> 16; 280 natptr->r_index[1] = r_index >> 8; 281 natptr->r_index[2] = r_index; 282 natptr->r_type[0] = 283 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0) 284 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG); 285 } 286 else 287 { 288 natptr->r_index[2] = r_index >> 16; 289 natptr->r_index[1] = r_index >> 8; 290 natptr->r_index[0] = r_index; 291 natptr->r_type[0] = 292 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0) 293 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE); 294 } 295 296 PUT_WORD (abfd, r_addend, natptr->r_addend); 297 } 298 299 /* BFD deals internally with all things based from the section they're 300 in. so, something in 10 bytes into a text section with a base of 301 50 would have a symbol (.text+10) and know .text vma was 50. 302 303 Aout keeps all it's symbols based from zero, so the symbol would 304 contain 60. This macro subs the base of each section from the value 305 to give the true offset from the section */ 306 307 308 #define MOVE_ADDRESS(ad) \ 309 if (r_extern) { \ 310 /* undefined symbol */ \ 311 cache_ptr->sym_ptr_ptr = symbols + r_index; \ 312 cache_ptr->addend = ad; \ 313 } else { \ 314 /* defined, section relative. replace symbol with pointer to \ 315 symbol which points to section */ \ 316 switch (r_index) { \ 317 case N_TEXT: \ 318 case N_TEXT | N_EXT: \ 319 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \ 320 cache_ptr->addend = ad - su->textsec->vma; \ 321 break; \ 322 case N_DATA: \ 323 case N_DATA | N_EXT: \ 324 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \ 325 cache_ptr->addend = ad - su->datasec->vma; \ 326 break; \ 327 case N_BSS: \ 328 case N_BSS | N_EXT: \ 329 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \ 330 cache_ptr->addend = ad - su->bsssec->vma; \ 331 break; \ 332 default: \ 333 case N_ABS: \ 334 case N_ABS | N_EXT: \ 335 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \ 336 cache_ptr->addend = ad; \ 337 break; \ 338 } \ 339 } \ 340 341 void 342 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount) 343 bfd *abfd; 344 struct reloc_ext_external *bytes; 345 arelent *cache_ptr; 346 asymbol **symbols; 347 bfd_size_type symcount ATTRIBUTE_UNUSED; 348 { 349 int r_index; 350 int r_extern; 351 unsigned int r_type; 352 struct aoutdata *su = &(abfd->tdata.aout_data->a); 353 354 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address)); 355 356 r_index = bytes->r_index[1]; 357 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG)); 358 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG) 359 >> RELOC_EXT_BITS_TYPE_SH_BIG; 360 361 cache_ptr->howto = aout_32_ext_howto_table + r_type; 362 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend)); 363 } 364 365 void 366 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount) 367 bfd *abfd; 368 struct reloc_std_external *bytes; 369 arelent *cache_ptr; 370 asymbol **symbols; 371 bfd_size_type symcount ATTRIBUTE_UNUSED; 372 { 373 int r_index; 374 int r_extern; 375 unsigned int r_length; 376 int r_pcrel; 377 int r_baserel, r_jmptable, r_relative; 378 struct aoutdata *su = &(abfd->tdata.aout_data->a); 379 380 cache_ptr->address = H_GET_32 (abfd, bytes->r_address); 381 382 r_index = bytes->r_index[1]; 383 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG)); 384 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG)); 385 r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG)); 386 r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG)); 387 r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG)); 388 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG) 389 >> RELOC_STD_BITS_LENGTH_SH_BIG; 390 391 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel; 392 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */ 393 394 MOVE_ADDRESS (0); 395 } 396 397 /* Reloc hackery */ 398 399 bfd_boolean 400 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols) 401 bfd *abfd; 402 sec_ptr asect; 403 asymbol **symbols; 404 { 405 bfd_size_type count; 406 bfd_size_type reloc_size; 407 PTR relocs; 408 arelent *reloc_cache; 409 size_t each_size; 410 411 if (asect->relocation) 412 return TRUE; 413 414 if (asect->flags & SEC_CONSTRUCTOR) 415 return TRUE; 416 417 if (asect == obj_datasec (abfd)) 418 { 419 reloc_size = exec_hdr (abfd)->a_drsize; 420 goto doit; 421 } 422 423 if (asect == obj_textsec (abfd)) 424 { 425 reloc_size = exec_hdr (abfd)->a_trsize; 426 goto doit; 427 } 428 429 bfd_set_error (bfd_error_invalid_operation); 430 return FALSE; 431 432 doit: 433 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0) 434 return FALSE; 435 each_size = obj_reloc_entry_size (abfd); 436 437 count = reloc_size / each_size; 438 439 440 reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent)); 441 if (!reloc_cache && count != 0) 442 return FALSE; 443 444 relocs = (PTR) bfd_alloc (abfd, reloc_size); 445 if (!relocs && reloc_size != 0) 446 { 447 free (reloc_cache); 448 return FALSE; 449 } 450 451 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size) 452 { 453 bfd_release (abfd, relocs); 454 free (reloc_cache); 455 return FALSE; 456 } 457 458 if (each_size == RELOC_EXT_SIZE) 459 { 460 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs; 461 unsigned int counter = 0; 462 arelent *cache_ptr = reloc_cache; 463 464 for (; counter < count; counter++, rptr++, cache_ptr++) 465 { 466 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols, 467 (bfd_size_type) bfd_get_symcount (abfd)); 468 } 469 } 470 else 471 { 472 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs; 473 unsigned int counter = 0; 474 arelent *cache_ptr = reloc_cache; 475 476 for (; counter < count; counter++, rptr++, cache_ptr++) 477 { 478 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols, 479 (bfd_size_type) bfd_get_symcount (abfd)); 480 } 481 482 } 483 484 bfd_release (abfd, relocs); 485 asect->relocation = reloc_cache; 486 asect->reloc_count = count; 487 return TRUE; 488 } 489 490 491 492 /* Write out a relocation section into an object file. */ 493 494 bfd_boolean 495 NAME(lynx,squirt_out_relocs) (abfd, section) 496 bfd *abfd; 497 asection *section; 498 { 499 arelent **generic; 500 unsigned char *native, *natptr; 501 size_t each_size; 502 503 unsigned int count = section->reloc_count; 504 bfd_size_type natsize; 505 506 if (count == 0) 507 return TRUE; 508 509 each_size = obj_reloc_entry_size (abfd); 510 natsize = count; 511 natsize *= each_size; 512 native = (unsigned char *) bfd_zalloc (abfd, natsize); 513 if (!native) 514 return FALSE; 515 516 generic = section->orelocation; 517 518 if (each_size == RELOC_EXT_SIZE) 519 { 520 for (natptr = native; 521 count != 0; 522 --count, natptr += each_size, ++generic) 523 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr); 524 } 525 else 526 { 527 for (natptr = native; 528 count != 0; 529 --count, natptr += each_size, ++generic) 530 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr); 531 } 532 533 if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize) 534 { 535 bfd_release (abfd, native); 536 return FALSE; 537 } 538 bfd_release (abfd, native); 539 540 return TRUE; 541 } 542 543 /* This is stupid. This function should be a boolean predicate */ 544 long 545 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols) 546 bfd *abfd; 547 sec_ptr section; 548 arelent **relptr; 549 asymbol **symbols; 550 { 551 arelent *tblptr = section->relocation; 552 unsigned int count; 553 554 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols))) 555 return -1; 556 557 if (section->flags & SEC_CONSTRUCTOR) 558 { 559 arelent_chain *chain = section->constructor_chain; 560 for (count = 0; count < section->reloc_count; count++) 561 { 562 *relptr++ = &chain->relent; 563 chain = chain->next; 564 } 565 } 566 else 567 { 568 tblptr = section->relocation; 569 570 for (count = 0; count++ < section->reloc_count;) 571 { 572 *relptr++ = tblptr++; 573 } 574 } 575 *relptr = 0; 576 577 return section->reloc_count; 578 } 579 580 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc) 581 582 #include "aout-target.h" 583