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