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