1 /* BFD back-end for MIPS Extended-Coff files. 2 Copyright (C) 1990-2018 Free Software Foundation, Inc. 3 Original version by Per Bothner. 4 Full support added by Ian Lance Taylor, ian@cygnus.com. 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 3 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., 51 Franklin Street - Fifth Floor, Boston, 21 MA 02110-1301, USA. */ 22 23 #include "sysdep.h" 24 #include "bfd.h" 25 #include "bfdlink.h" 26 #include "libbfd.h" 27 #include "coff/internal.h" 28 #include "coff/sym.h" 29 #include "coff/symconst.h" 30 #include "coff/ecoff.h" 31 #include "coff/mips.h" 32 #include "libcoff.h" 33 #include "libecoff.h" 34 35 /* Prototypes for static functions. */ 36 static bfd_reloc_status_type 37 mips_generic_reloc 38 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 39 static bfd_reloc_status_type 40 mips_refhi_reloc 41 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 42 static bfd_reloc_status_type 43 mips_reflo_reloc 44 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 45 static bfd_reloc_status_type 46 mips_gprel_reloc 47 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 48 49 50 /* ECOFF has COFF sections, but the debugging information is stored in 51 a completely different format. ECOFF targets use some of the 52 swapping routines from coffswap.h, and some of the generic COFF 53 routines in coffgen.c, but, unlike the real COFF targets, do not 54 use coffcode.h itself. 55 56 Get the generic COFF swapping routines, except for the reloc, 57 symbol, and lineno ones. Give them ECOFF names. */ 58 #define MIPSECOFF 59 #define NO_COFF_RELOCS 60 #define NO_COFF_SYMBOLS 61 #define NO_COFF_LINENOS 62 #define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in 63 #define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out 64 #define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in 65 #define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out 66 #define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in 67 #define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out 68 69 #include "coffswap.h" 70 71 /* Get the ECOFF swapping routines. */ 72 #define ECOFF_32 73 #include "ecoffswap.h" 74 75 /* How to process the various relocs types. */ 76 77 static reloc_howto_type mips_howto_table[] = 78 { 79 /* Reloc type 0 is ignored. The reloc reading code ensures that 80 this is a reference to the .abs section, which will cause 81 bfd_perform_relocation to do nothing. */ 82 HOWTO (MIPS_R_IGNORE, /* type */ 83 0, /* rightshift */ 84 0, /* size (0 = byte, 1 = short, 2 = long) */ 85 8, /* bitsize */ 86 FALSE, /* pc_relative */ 87 0, /* bitpos */ 88 complain_overflow_dont, /* complain_on_overflow */ 89 0, /* special_function */ 90 "IGNORE", /* name */ 91 FALSE, /* partial_inplace */ 92 0, /* src_mask */ 93 0, /* dst_mask */ 94 FALSE), /* pcrel_offset */ 95 96 /* A 16 bit reference to a symbol, normally from a data section. */ 97 HOWTO (MIPS_R_REFHALF, /* type */ 98 0, /* rightshift */ 99 1, /* size (0 = byte, 1 = short, 2 = long) */ 100 16, /* bitsize */ 101 FALSE, /* pc_relative */ 102 0, /* bitpos */ 103 complain_overflow_bitfield, /* complain_on_overflow */ 104 mips_generic_reloc, /* special_function */ 105 "REFHALF", /* name */ 106 TRUE, /* partial_inplace */ 107 0xffff, /* src_mask */ 108 0xffff, /* dst_mask */ 109 FALSE), /* pcrel_offset */ 110 111 /* A 32 bit reference to a symbol, normally from a data section. */ 112 HOWTO (MIPS_R_REFWORD, /* type */ 113 0, /* rightshift */ 114 2, /* size (0 = byte, 1 = short, 2 = long) */ 115 32, /* bitsize */ 116 FALSE, /* pc_relative */ 117 0, /* bitpos */ 118 complain_overflow_bitfield, /* complain_on_overflow */ 119 mips_generic_reloc, /* special_function */ 120 "REFWORD", /* name */ 121 TRUE, /* partial_inplace */ 122 0xffffffff, /* src_mask */ 123 0xffffffff, /* dst_mask */ 124 FALSE), /* pcrel_offset */ 125 126 /* A 26 bit absolute jump address. */ 127 HOWTO (MIPS_R_JMPADDR, /* type */ 128 2, /* rightshift */ 129 2, /* size (0 = byte, 1 = short, 2 = long) */ 130 26, /* bitsize */ 131 FALSE, /* pc_relative */ 132 0, /* bitpos */ 133 complain_overflow_dont, /* complain_on_overflow */ 134 /* This needs complex overflow 135 detection, because the upper four 136 bits must match the PC. */ 137 mips_generic_reloc, /* special_function */ 138 "JMPADDR", /* name */ 139 TRUE, /* partial_inplace */ 140 0x3ffffff, /* src_mask */ 141 0x3ffffff, /* dst_mask */ 142 FALSE), /* pcrel_offset */ 143 144 /* The high 16 bits of a symbol value. Handled by the function 145 mips_refhi_reloc. */ 146 HOWTO (MIPS_R_REFHI, /* type */ 147 16, /* rightshift */ 148 2, /* size (0 = byte, 1 = short, 2 = long) */ 149 16, /* bitsize */ 150 FALSE, /* pc_relative */ 151 0, /* bitpos */ 152 complain_overflow_bitfield, /* complain_on_overflow */ 153 mips_refhi_reloc, /* special_function */ 154 "REFHI", /* name */ 155 TRUE, /* partial_inplace */ 156 0xffff, /* src_mask */ 157 0xffff, /* dst_mask */ 158 FALSE), /* pcrel_offset */ 159 160 /* The low 16 bits of a symbol value. */ 161 HOWTO (MIPS_R_REFLO, /* type */ 162 0, /* rightshift */ 163 2, /* size (0 = byte, 1 = short, 2 = long) */ 164 16, /* bitsize */ 165 FALSE, /* pc_relative */ 166 0, /* bitpos */ 167 complain_overflow_dont, /* complain_on_overflow */ 168 mips_reflo_reloc, /* special_function */ 169 "REFLO", /* name */ 170 TRUE, /* partial_inplace */ 171 0xffff, /* src_mask */ 172 0xffff, /* dst_mask */ 173 FALSE), /* pcrel_offset */ 174 175 /* A reference to an offset from the gp register. Handled by the 176 function mips_gprel_reloc. */ 177 HOWTO (MIPS_R_GPREL, /* type */ 178 0, /* rightshift */ 179 2, /* size (0 = byte, 1 = short, 2 = long) */ 180 16, /* bitsize */ 181 FALSE, /* pc_relative */ 182 0, /* bitpos */ 183 complain_overflow_signed, /* complain_on_overflow */ 184 mips_gprel_reloc, /* special_function */ 185 "GPREL", /* name */ 186 TRUE, /* partial_inplace */ 187 0xffff, /* src_mask */ 188 0xffff, /* dst_mask */ 189 FALSE), /* pcrel_offset */ 190 191 /* A reference to a literal using an offset from the gp register. 192 Handled by the function mips_gprel_reloc. */ 193 HOWTO (MIPS_R_LITERAL, /* type */ 194 0, /* rightshift */ 195 2, /* size (0 = byte, 1 = short, 2 = long) */ 196 16, /* bitsize */ 197 FALSE, /* pc_relative */ 198 0, /* bitpos */ 199 complain_overflow_signed, /* complain_on_overflow */ 200 mips_gprel_reloc, /* special_function */ 201 "LITERAL", /* name */ 202 TRUE, /* partial_inplace */ 203 0xffff, /* src_mask */ 204 0xffff, /* dst_mask */ 205 FALSE), /* pcrel_offset */ 206 207 EMPTY_HOWTO (8), 208 EMPTY_HOWTO (9), 209 EMPTY_HOWTO (10), 210 EMPTY_HOWTO (11), 211 212 /* FIXME: This relocation is used (internally only) to represent branches 213 when assembling. It should never appear in output files, and 214 be removed. (It used to be used for embedded-PIC support.) */ 215 HOWTO (MIPS_R_PCREL16, /* type */ 216 2, /* rightshift */ 217 2, /* size (0 = byte, 1 = short, 2 = long) */ 218 16, /* bitsize */ 219 TRUE, /* pc_relative */ 220 0, /* bitpos */ 221 complain_overflow_signed, /* complain_on_overflow */ 222 mips_generic_reloc, /* special_function */ 223 "PCREL16", /* name */ 224 TRUE, /* partial_inplace */ 225 0xffff, /* src_mask */ 226 0xffff, /* dst_mask */ 227 TRUE), /* pcrel_offset */ 228 }; 229 230 #define MIPS_HOWTO_COUNT \ 231 (sizeof mips_howto_table / sizeof mips_howto_table[0]) 232 233 /* See whether the magic number matches. */ 234 235 static bfd_boolean 236 mips_ecoff_bad_format_hook (bfd * abfd, void * filehdr) 237 { 238 struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; 239 240 switch (internal_f->f_magic) 241 { 242 case MIPS_MAGIC_1: 243 /* I don't know what endianness this implies. */ 244 return TRUE; 245 246 case MIPS_MAGIC_BIG: 247 case MIPS_MAGIC_BIG2: 248 case MIPS_MAGIC_BIG3: 249 return bfd_big_endian (abfd); 250 251 case MIPS_MAGIC_LITTLE: 252 case MIPS_MAGIC_LITTLE2: 253 case MIPS_MAGIC_LITTLE3: 254 return bfd_little_endian (abfd); 255 256 default: 257 return FALSE; 258 } 259 } 260 261 /* Reloc handling. MIPS ECOFF relocs are packed into 8 bytes in 262 external form. They use a bit which indicates whether the symbol 263 is external. */ 264 265 /* Swap a reloc in. */ 266 267 static void 268 mips_ecoff_swap_reloc_in (bfd * abfd, 269 void * ext_ptr, 270 struct internal_reloc *intern) 271 { 272 const RELOC *ext = (RELOC *) ext_ptr; 273 274 intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr); 275 if (bfd_header_big_endian (abfd)) 276 { 277 intern->r_symndx = (((int) ext->r_bits[0] 278 << RELOC_BITS0_SYMNDX_SH_LEFT_BIG) 279 | ((int) ext->r_bits[1] 280 << RELOC_BITS1_SYMNDX_SH_LEFT_BIG) 281 | ((int) ext->r_bits[2] 282 << RELOC_BITS2_SYMNDX_SH_LEFT_BIG)); 283 intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG) 284 >> RELOC_BITS3_TYPE_SH_BIG); 285 intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0; 286 } 287 else 288 { 289 intern->r_symndx = (((int) ext->r_bits[0] 290 << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE) 291 | ((int) ext->r_bits[1] 292 << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE) 293 | ((int) ext->r_bits[2] 294 << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE)); 295 intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE) 296 >> RELOC_BITS3_TYPE_SH_LITTLE) 297 | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE) 298 << RELOC_BITS3_TYPEHI_SH_LITTLE)); 299 intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0; 300 } 301 } 302 303 /* Swap a reloc out. */ 304 305 static void 306 mips_ecoff_swap_reloc_out (bfd * abfd, 307 const struct internal_reloc * intern, 308 void * dst) 309 { 310 RELOC *ext = (RELOC *) dst; 311 long r_symndx; 312 313 BFD_ASSERT (intern->r_extern 314 || (intern->r_symndx >= 0 && intern->r_symndx <= 12)); 315 316 r_symndx = intern->r_symndx; 317 318 H_PUT_32 (abfd, intern->r_vaddr, ext->r_vaddr); 319 if (bfd_header_big_endian (abfd)) 320 { 321 ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG; 322 ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG; 323 ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG; 324 ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG) 325 & RELOC_BITS3_TYPE_BIG) 326 | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0)); 327 } 328 else 329 { 330 ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE; 331 ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE; 332 ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE; 333 ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE) 334 & RELOC_BITS3_TYPE_LITTLE) 335 | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE 336 & RELOC_BITS3_TYPEHI_LITTLE)) 337 | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0)); 338 } 339 } 340 341 /* Finish canonicalizing a reloc. Part of this is generic to all 342 ECOFF targets, and that part is in ecoff.c. The rest is done in 343 this backend routine. It must fill in the howto field. */ 344 345 static void 346 mips_adjust_reloc_in (bfd *abfd, 347 const struct internal_reloc *intern, 348 arelent *rptr) 349 { 350 if (intern->r_type > MIPS_R_PCREL16) 351 abort (); 352 353 if (! intern->r_extern 354 && (intern->r_type == MIPS_R_GPREL 355 || intern->r_type == MIPS_R_LITERAL)) 356 rptr->addend += ecoff_data (abfd)->gp; 357 358 /* If the type is MIPS_R_IGNORE, make sure this is a reference to 359 the absolute section so that the reloc is ignored. */ 360 if (intern->r_type == MIPS_R_IGNORE) 361 rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; 362 363 rptr->howto = &mips_howto_table[intern->r_type]; 364 } 365 366 /* Make any adjustments needed to a reloc before writing it out. None 367 are needed for MIPS. */ 368 369 static void 370 mips_adjust_reloc_out (bfd *abfd ATTRIBUTE_UNUSED, 371 const arelent *rel ATTRIBUTE_UNUSED, 372 struct internal_reloc *intern ATTRIBUTE_UNUSED) 373 { 374 } 375 376 /* ECOFF relocs are either against external symbols, or against 377 sections. If we are producing relocatable output, and the reloc 378 is against an external symbol, and nothing has given us any 379 additional addend, the resulting reloc will also be against the 380 same symbol. In such a case, we don't want to change anything 381 about the way the reloc is handled, since it will all be done at 382 final link time. Rather than put special case code into 383 bfd_perform_relocation, all the reloc types use this howto 384 function. It just short circuits the reloc if producing 385 relocatable output against an external symbol. */ 386 387 static bfd_reloc_status_type 388 mips_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, 389 arelent *reloc_entry, 390 asymbol *symbol, 391 void * data ATTRIBUTE_UNUSED, 392 asection *input_section, 393 bfd *output_bfd, 394 char **error_message ATTRIBUTE_UNUSED) 395 { 396 if (output_bfd != (bfd *) NULL 397 && (symbol->flags & BSF_SECTION_SYM) == 0 398 && reloc_entry->addend == 0) 399 { 400 reloc_entry->address += input_section->output_offset; 401 return bfd_reloc_ok; 402 } 403 404 return bfd_reloc_continue; 405 } 406 407 /* Do a REFHI relocation. This has to be done in combination with a 408 REFLO reloc, because there is a carry from the REFLO to the REFHI. 409 Here we just save the information we need; we do the actual 410 relocation when we see the REFLO. MIPS ECOFF requires that the 411 REFLO immediately follow the REFHI. As a GNU extension, we permit 412 an arbitrary number of HI relocs to be associated with a single LO 413 reloc. This extension permits gcc to output the HI and LO relocs 414 itself. */ 415 416 struct mips_hi 417 { 418 struct mips_hi *next; 419 bfd_byte *addr; 420 bfd_vma addend; 421 }; 422 423 /* FIXME: This should not be a static variable. */ 424 425 static struct mips_hi *mips_refhi_list; 426 427 static bfd_reloc_status_type 428 mips_refhi_reloc (bfd *abfd ATTRIBUTE_UNUSED, 429 arelent *reloc_entry, 430 asymbol *symbol, 431 void * data, 432 asection *input_section, 433 bfd *output_bfd, 434 char **error_message ATTRIBUTE_UNUSED) 435 { 436 bfd_reloc_status_type ret; 437 bfd_vma relocation; 438 struct mips_hi *n; 439 440 /* If we're relocating, and this an external symbol, we don't want 441 to change anything. */ 442 if (output_bfd != (bfd *) NULL 443 && (symbol->flags & BSF_SECTION_SYM) == 0 444 && reloc_entry->addend == 0) 445 { 446 reloc_entry->address += input_section->output_offset; 447 return bfd_reloc_ok; 448 } 449 450 ret = bfd_reloc_ok; 451 if (bfd_is_und_section (symbol->section) 452 && output_bfd == (bfd *) NULL) 453 ret = bfd_reloc_undefined; 454 455 if (bfd_is_com_section (symbol->section)) 456 relocation = 0; 457 else 458 relocation = symbol->value; 459 460 relocation += symbol->section->output_section->vma; 461 relocation += symbol->section->output_offset; 462 relocation += reloc_entry->addend; 463 464 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) 465 return bfd_reloc_outofrange; 466 467 /* Save the information, and let REFLO do the actual relocation. */ 468 n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n); 469 if (n == NULL) 470 return bfd_reloc_outofrange; 471 n->addr = (bfd_byte *) data + reloc_entry->address; 472 n->addend = relocation; 473 n->next = mips_refhi_list; 474 mips_refhi_list = n; 475 476 if (output_bfd != (bfd *) NULL) 477 reloc_entry->address += input_section->output_offset; 478 479 return ret; 480 } 481 482 /* Do a REFLO relocation. This is a straightforward 16 bit inplace 483 relocation; this function exists in order to do the REFHI 484 relocation described above. */ 485 486 static bfd_reloc_status_type 487 mips_reflo_reloc (bfd *abfd ATTRIBUTE_UNUSED, 488 arelent *reloc_entry, 489 asymbol *symbol, 490 void * data, 491 asection *input_section, 492 bfd *output_bfd, 493 char **error_message ATTRIBUTE_UNUSED) 494 { 495 if (mips_refhi_list != NULL) 496 { 497 struct mips_hi *l; 498 499 l = mips_refhi_list; 500 while (l != NULL) 501 { 502 unsigned long insn; 503 unsigned long val; 504 unsigned long vallo; 505 struct mips_hi *next; 506 507 if (! bfd_reloc_offset_in_range (reloc_entry->howto, abfd, 508 input_section, 509 reloc_entry->address 510 * bfd_octets_per_byte (abfd))) 511 return bfd_reloc_outofrange; 512 513 /* Do the REFHI relocation. Note that we actually don't 514 need to know anything about the REFLO itself, except 515 where to find the low 16 bits of the addend needed by the 516 REFHI. */ 517 insn = bfd_get_32 (abfd, l->addr); 518 vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address) 519 & 0xffff); 520 val = ((insn & 0xffff) << 16) + vallo; 521 val += l->addend; 522 523 /* The low order 16 bits are always treated as a signed 524 value. Therefore, a negative value in the low order bits 525 requires an adjustment in the high order bits. We need 526 to make this adjustment in two ways: once for the bits we 527 took from the data, and once for the bits we are putting 528 back in to the data. */ 529 if ((vallo & 0x8000) != 0) 530 val -= 0x10000; 531 if ((val & 0x8000) != 0) 532 val += 0x10000; 533 534 insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff); 535 bfd_put_32 (abfd, (bfd_vma) insn, l->addr); 536 537 next = l->next; 538 free (l); 539 l = next; 540 } 541 542 mips_refhi_list = NULL; 543 } 544 545 /* Now do the REFLO reloc in the usual way. */ 546 return mips_generic_reloc (abfd, reloc_entry, symbol, data, 547 input_section, output_bfd, error_message); 548 } 549 550 /* Do a GPREL relocation. This is a 16 bit value which must become 551 the offset from the gp register. */ 552 553 static bfd_reloc_status_type 554 mips_gprel_reloc (bfd *abfd ATTRIBUTE_UNUSED, 555 arelent *reloc_entry, 556 asymbol *symbol, 557 void * data, 558 asection *input_section, 559 bfd *output_bfd, 560 char **error_message ATTRIBUTE_UNUSED) 561 { 562 bfd_boolean relocatable; 563 bfd_vma gp; 564 bfd_vma relocation; 565 unsigned long val; 566 unsigned long insn; 567 568 /* If we're relocating, and this is an external symbol with no 569 addend, we don't want to change anything. We will only have an 570 addend if this is a newly created reloc, not read from an ECOFF 571 file. */ 572 if (output_bfd != (bfd *) NULL 573 && (symbol->flags & BSF_SECTION_SYM) == 0 574 && reloc_entry->addend == 0) 575 { 576 reloc_entry->address += input_section->output_offset; 577 return bfd_reloc_ok; 578 } 579 580 if (output_bfd != (bfd *) NULL) 581 relocatable = TRUE; 582 else 583 { 584 relocatable = FALSE; 585 output_bfd = symbol->section->output_section->owner; 586 } 587 588 if (bfd_is_und_section (symbol->section) && ! relocatable) 589 return bfd_reloc_undefined; 590 591 /* We have to figure out the gp value, so that we can adjust the 592 symbol value correctly. We look up the symbol _gp in the output 593 BFD. If we can't find it, we're stuck. We cache it in the ECOFF 594 target data. We don't need to adjust the symbol value for an 595 external symbol if we are producing relocatable output. */ 596 gp = _bfd_get_gp_value (output_bfd); 597 if (gp == 0 598 && (! relocatable 599 || (symbol->flags & BSF_SECTION_SYM) != 0)) 600 { 601 if (relocatable) 602 { 603 /* Make up a value. */ 604 gp = symbol->section->output_section->vma + 0x4000; 605 _bfd_set_gp_value (output_bfd, gp); 606 } 607 else 608 { 609 unsigned int count; 610 asymbol **sym; 611 unsigned int i; 612 613 count = bfd_get_symcount (output_bfd); 614 sym = bfd_get_outsymbols (output_bfd); 615 616 if (sym == (asymbol **) NULL) 617 i = count; 618 else 619 { 620 for (i = 0; i < count; i++, sym++) 621 { 622 register const char *name; 623 624 name = bfd_asymbol_name (*sym); 625 if (*name == '_' && strcmp (name, "_gp") == 0) 626 { 627 gp = bfd_asymbol_value (*sym); 628 _bfd_set_gp_value (output_bfd, gp); 629 break; 630 } 631 } 632 } 633 634 if (i >= count) 635 { 636 /* Only get the error once. */ 637 gp = 4; 638 _bfd_set_gp_value (output_bfd, gp); 639 *error_message = 640 (char *) _("GP relative relocation when _gp not defined"); 641 return bfd_reloc_dangerous; 642 } 643 } 644 } 645 646 if (bfd_is_com_section (symbol->section)) 647 relocation = 0; 648 else 649 relocation = symbol->value; 650 651 relocation += symbol->section->output_section->vma; 652 relocation += symbol->section->output_offset; 653 654 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) 655 return bfd_reloc_outofrange; 656 657 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 658 659 /* Set val to the offset into the section or symbol. */ 660 val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff; 661 if (val & 0x8000) 662 val -= 0x10000; 663 664 /* Adjust val for the final section location and GP value. If we 665 are producing relocatable output, we don't want to do this for 666 an external symbol. */ 667 if (! relocatable 668 || (symbol->flags & BSF_SECTION_SYM) != 0) 669 val += relocation - gp; 670 671 insn = (insn &~ (unsigned) 0xffff) | (val & 0xffff); 672 bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + reloc_entry->address); 673 674 if (relocatable) 675 reloc_entry->address += input_section->output_offset; 676 677 /* Make sure it fit in 16 bits. */ 678 if ((long) val >= 0x8000 || (long) val < -0x8000) 679 return bfd_reloc_overflow; 680 681 return bfd_reloc_ok; 682 } 683 684 /* Get the howto structure for a generic reloc type. */ 685 686 static reloc_howto_type * 687 mips_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 688 bfd_reloc_code_real_type code) 689 { 690 int mips_type; 691 692 switch (code) 693 { 694 case BFD_RELOC_16: 695 mips_type = MIPS_R_REFHALF; 696 break; 697 case BFD_RELOC_32: 698 case BFD_RELOC_CTOR: 699 mips_type = MIPS_R_REFWORD; 700 break; 701 case BFD_RELOC_MIPS_JMP: 702 mips_type = MIPS_R_JMPADDR; 703 break; 704 case BFD_RELOC_HI16_S: 705 mips_type = MIPS_R_REFHI; 706 break; 707 case BFD_RELOC_LO16: 708 mips_type = MIPS_R_REFLO; 709 break; 710 case BFD_RELOC_GPREL16: 711 mips_type = MIPS_R_GPREL; 712 break; 713 case BFD_RELOC_MIPS_LITERAL: 714 mips_type = MIPS_R_LITERAL; 715 break; 716 case BFD_RELOC_16_PCREL_S2: 717 mips_type = MIPS_R_PCREL16; 718 break; 719 default: 720 return (reloc_howto_type *) NULL; 721 } 722 723 return &mips_howto_table[mips_type]; 724 } 725 726 static reloc_howto_type * 727 mips_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 728 const char *r_name) 729 { 730 unsigned int i; 731 732 for (i = 0; 733 i < sizeof (mips_howto_table) / sizeof (mips_howto_table[0]); 734 i++) 735 if (mips_howto_table[i].name != NULL 736 && strcasecmp (mips_howto_table[i].name, r_name) == 0) 737 return &mips_howto_table[i]; 738 739 return NULL; 740 } 741 742 /* A helper routine for mips_relocate_section which handles the REFHI 743 relocations. The REFHI relocation must be followed by a REFLO 744 relocation, and the addend used is formed from the addends of both 745 instructions. */ 746 747 static void 748 mips_relocate_hi (struct internal_reloc *refhi, 749 struct internal_reloc *reflo, 750 bfd *input_bfd, 751 asection *input_section, 752 bfd_byte *contents, 753 bfd_vma relocation) 754 { 755 unsigned long insn; 756 unsigned long val; 757 unsigned long vallo; 758 759 if (refhi == NULL) 760 return; 761 762 insn = bfd_get_32 (input_bfd, 763 contents + refhi->r_vaddr - input_section->vma); 764 if (reflo == NULL) 765 vallo = 0; 766 else 767 vallo = (bfd_get_32 (input_bfd, 768 contents + reflo->r_vaddr - input_section->vma) 769 & 0xffff); 770 771 val = ((insn & 0xffff) << 16) + vallo; 772 val += relocation; 773 774 /* The low order 16 bits are always treated as a signed value. 775 Therefore, a negative value in the low order bits requires an 776 adjustment in the high order bits. We need to make this 777 adjustment in two ways: once for the bits we took from the data, 778 and once for the bits we are putting back in to the data. */ 779 if ((vallo & 0x8000) != 0) 780 val -= 0x10000; 781 782 if ((val & 0x8000) != 0) 783 val += 0x10000; 784 785 insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff); 786 bfd_put_32 (input_bfd, (bfd_vma) insn, 787 contents + refhi->r_vaddr - input_section->vma); 788 } 789 790 /* Relocate a section while linking a MIPS ECOFF file. */ 791 792 static bfd_boolean 793 mips_relocate_section (bfd *output_bfd, 794 struct bfd_link_info *info, 795 bfd *input_bfd, 796 asection *input_section, 797 bfd_byte *contents, 798 void * external_relocs) 799 { 800 asection **symndx_to_section; 801 struct ecoff_link_hash_entry **sym_hashes; 802 bfd_vma gp; 803 bfd_boolean gp_undefined; 804 struct external_reloc *ext_rel; 805 struct external_reloc *ext_rel_end; 806 unsigned int i; 807 bfd_boolean got_lo; 808 struct internal_reloc lo_int_rel; 809 bfd_size_type amt; 810 811 BFD_ASSERT (input_bfd->xvec->byteorder 812 == output_bfd->xvec->byteorder); 813 814 /* We keep a table mapping the symndx found in an internal reloc to 815 the appropriate section. This is faster than looking up the 816 section by name each time. */ 817 symndx_to_section = ecoff_data (input_bfd)->symndx_to_section; 818 if (symndx_to_section == (asection **) NULL) 819 { 820 amt = NUM_RELOC_SECTIONS * sizeof (asection *); 821 symndx_to_section = (asection **) bfd_alloc (input_bfd, amt); 822 if (!symndx_to_section) 823 return FALSE; 824 825 symndx_to_section[RELOC_SECTION_NONE] = NULL; 826 symndx_to_section[RELOC_SECTION_TEXT] = 827 bfd_get_section_by_name (input_bfd, ".text"); 828 symndx_to_section[RELOC_SECTION_RDATA] = 829 bfd_get_section_by_name (input_bfd, ".rdata"); 830 symndx_to_section[RELOC_SECTION_DATA] = 831 bfd_get_section_by_name (input_bfd, ".data"); 832 symndx_to_section[RELOC_SECTION_SDATA] = 833 bfd_get_section_by_name (input_bfd, ".sdata"); 834 symndx_to_section[RELOC_SECTION_SBSS] = 835 bfd_get_section_by_name (input_bfd, ".sbss"); 836 symndx_to_section[RELOC_SECTION_BSS] = 837 bfd_get_section_by_name (input_bfd, ".bss"); 838 symndx_to_section[RELOC_SECTION_INIT] = 839 bfd_get_section_by_name (input_bfd, ".init"); 840 symndx_to_section[RELOC_SECTION_LIT8] = 841 bfd_get_section_by_name (input_bfd, ".lit8"); 842 symndx_to_section[RELOC_SECTION_LIT4] = 843 bfd_get_section_by_name (input_bfd, ".lit4"); 844 symndx_to_section[RELOC_SECTION_XDATA] = NULL; 845 symndx_to_section[RELOC_SECTION_PDATA] = NULL; 846 symndx_to_section[RELOC_SECTION_FINI] = 847 bfd_get_section_by_name (input_bfd, ".fini"); 848 symndx_to_section[RELOC_SECTION_LITA] = NULL; 849 symndx_to_section[RELOC_SECTION_ABS] = NULL; 850 851 ecoff_data (input_bfd)->symndx_to_section = symndx_to_section; 852 } 853 854 sym_hashes = ecoff_data (input_bfd)->sym_hashes; 855 856 gp = _bfd_get_gp_value (output_bfd); 857 if (gp == 0) 858 gp_undefined = TRUE; 859 else 860 gp_undefined = FALSE; 861 862 got_lo = FALSE; 863 864 ext_rel = (struct external_reloc *) external_relocs; 865 ext_rel_end = ext_rel + input_section->reloc_count; 866 for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++) 867 { 868 struct internal_reloc int_rel; 869 bfd_boolean use_lo = FALSE; 870 bfd_vma addend; 871 reloc_howto_type *howto; 872 struct ecoff_link_hash_entry *h = NULL; 873 asection *s = NULL; 874 bfd_vma relocation; 875 bfd_reloc_status_type r; 876 877 if (! got_lo) 878 mips_ecoff_swap_reloc_in (input_bfd, ext_rel, &int_rel); 879 else 880 { 881 int_rel = lo_int_rel; 882 got_lo = FALSE; 883 } 884 885 BFD_ASSERT (int_rel.r_type 886 < sizeof mips_howto_table / sizeof mips_howto_table[0]); 887 888 /* The REFHI reloc requires special handling. It must be followed 889 by a REFLO reloc, and the addend is formed from both relocs. */ 890 if (int_rel.r_type == MIPS_R_REFHI) 891 { 892 struct external_reloc *lo_ext_rel; 893 894 /* As a GNU extension, permit an arbitrary number of REFHI 895 relocs before the REFLO reloc. This permits gcc to emit 896 the HI and LO relocs itself. */ 897 for (lo_ext_rel = ext_rel + 1; 898 lo_ext_rel < ext_rel_end; 899 lo_ext_rel++) 900 { 901 mips_ecoff_swap_reloc_in (input_bfd, lo_ext_rel, 902 &lo_int_rel); 903 if (lo_int_rel.r_type != int_rel.r_type) 904 break; 905 } 906 907 if (lo_ext_rel < ext_rel_end 908 && lo_int_rel.r_type == MIPS_R_REFLO 909 && int_rel.r_extern == lo_int_rel.r_extern 910 && int_rel.r_symndx == lo_int_rel.r_symndx) 911 { 912 use_lo = TRUE; 913 if (lo_ext_rel == ext_rel + 1) 914 got_lo = TRUE; 915 } 916 } 917 918 howto = &mips_howto_table[int_rel.r_type]; 919 920 if (int_rel.r_extern) 921 { 922 h = sym_hashes[int_rel.r_symndx]; 923 /* If h is NULL, that means that there is a reloc against an 924 external symbol which we thought was just a debugging 925 symbol. This should not happen. */ 926 if (h == (struct ecoff_link_hash_entry *) NULL) 927 abort (); 928 } 929 else 930 { 931 if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS) 932 s = NULL; 933 else 934 s = symndx_to_section[int_rel.r_symndx]; 935 936 if (s == (asection *) NULL) 937 abort (); 938 } 939 940 /* The GPREL reloc uses an addend: the difference in the GP 941 values. */ 942 if (int_rel.r_type != MIPS_R_GPREL 943 && int_rel.r_type != MIPS_R_LITERAL) 944 addend = 0; 945 else 946 { 947 if (gp_undefined) 948 { 949 (*info->callbacks->reloc_dangerous) 950 (info, _("GP relative relocation used when GP not defined"), 951 input_bfd, input_section, 952 int_rel.r_vaddr - input_section->vma); 953 /* Only give the error once per link. */ 954 gp = 4; 955 _bfd_set_gp_value (output_bfd, gp); 956 gp_undefined = FALSE; 957 } 958 if (! int_rel.r_extern) 959 { 960 /* This is a relocation against a section. The current 961 addend in the instruction is the difference between 962 INPUT_SECTION->vma and the GP value of INPUT_BFD. We 963 must change this to be the difference between the 964 final definition (which will end up in RELOCATION) 965 and the GP value of OUTPUT_BFD (which is in GP). */ 966 addend = ecoff_data (input_bfd)->gp - gp; 967 } 968 else if (! bfd_link_relocatable (info) 969 || h->root.type == bfd_link_hash_defined 970 || h->root.type == bfd_link_hash_defweak) 971 { 972 /* This is a relocation against a defined symbol. The 973 current addend in the instruction is simply the 974 desired offset into the symbol (normally zero). We 975 are going to change this into a relocation against a 976 defined symbol, so we want the instruction to hold 977 the difference between the final definition of the 978 symbol (which will end up in RELOCATION) and the GP 979 value of OUTPUT_BFD (which is in GP). */ 980 addend = - gp; 981 } 982 else 983 { 984 /* This is a relocation against an undefined or common 985 symbol. The current addend in the instruction is 986 simply the desired offset into the symbol (normally 987 zero). We are generating relocatable output, and we 988 aren't going to define this symbol, so we just leave 989 the instruction alone. */ 990 addend = 0; 991 } 992 } 993 994 if (bfd_link_relocatable (info)) 995 { 996 /* We are generating relocatable output, and must convert 997 the existing reloc. */ 998 if (int_rel.r_extern) 999 { 1000 if ((h->root.type == bfd_link_hash_defined 1001 || h->root.type == bfd_link_hash_defweak) 1002 && ! bfd_is_abs_section (h->root.u.def.section)) 1003 { 1004 const char *name; 1005 1006 /* This symbol is defined in the output. Convert 1007 the reloc from being against the symbol to being 1008 against the section. */ 1009 1010 /* Clear the r_extern bit. */ 1011 int_rel.r_extern = 0; 1012 1013 /* Compute a new r_symndx value. */ 1014 s = h->root.u.def.section; 1015 name = bfd_get_section_name (output_bfd, 1016 s->output_section); 1017 1018 int_rel.r_symndx = -1; 1019 switch (name[1]) 1020 { 1021 case 'b': 1022 if (strcmp (name, ".bss") == 0) 1023 int_rel.r_symndx = RELOC_SECTION_BSS; 1024 break; 1025 case 'd': 1026 if (strcmp (name, ".data") == 0) 1027 int_rel.r_symndx = RELOC_SECTION_DATA; 1028 break; 1029 case 'f': 1030 if (strcmp (name, ".fini") == 0) 1031 int_rel.r_symndx = RELOC_SECTION_FINI; 1032 break; 1033 case 'i': 1034 if (strcmp (name, ".init") == 0) 1035 int_rel.r_symndx = RELOC_SECTION_INIT; 1036 break; 1037 case 'l': 1038 if (strcmp (name, ".lit8") == 0) 1039 int_rel.r_symndx = RELOC_SECTION_LIT8; 1040 else if (strcmp (name, ".lit4") == 0) 1041 int_rel.r_symndx = RELOC_SECTION_LIT4; 1042 break; 1043 case 'r': 1044 if (strcmp (name, ".rdata") == 0) 1045 int_rel.r_symndx = RELOC_SECTION_RDATA; 1046 break; 1047 case 's': 1048 if (strcmp (name, ".sdata") == 0) 1049 int_rel.r_symndx = RELOC_SECTION_SDATA; 1050 else if (strcmp (name, ".sbss") == 0) 1051 int_rel.r_symndx = RELOC_SECTION_SBSS; 1052 break; 1053 case 't': 1054 if (strcmp (name, ".text") == 0) 1055 int_rel.r_symndx = RELOC_SECTION_TEXT; 1056 break; 1057 } 1058 1059 if (int_rel.r_symndx == -1) 1060 abort (); 1061 1062 /* Add the section VMA and the symbol value. */ 1063 relocation = (h->root.u.def.value 1064 + s->output_section->vma 1065 + s->output_offset); 1066 1067 /* For a PC relative relocation, the object file 1068 currently holds just the addend. We must adjust 1069 by the address to get the right value. */ 1070 if (howto->pc_relative) 1071 relocation -= int_rel.r_vaddr - input_section->vma; 1072 1073 h = NULL; 1074 } 1075 else 1076 { 1077 /* Change the symndx value to the right one for the 1078 output BFD. */ 1079 int_rel.r_symndx = h->indx; 1080 if (int_rel.r_symndx == -1) 1081 { 1082 /* This symbol is not being written out. */ 1083 (*info->callbacks->unattached_reloc) 1084 (info, h->root.root.string, input_bfd, input_section, 1085 int_rel.r_vaddr - input_section->vma); 1086 int_rel.r_symndx = 0; 1087 } 1088 relocation = 0; 1089 } 1090 } 1091 else 1092 { 1093 /* This is a relocation against a section. Adjust the 1094 value by the amount the section moved. */ 1095 relocation = (s->output_section->vma 1096 + s->output_offset 1097 - s->vma); 1098 } 1099 1100 relocation += addend; 1101 addend = 0; 1102 1103 /* Adjust a PC relative relocation by removing the reference 1104 to the original address in the section and including the 1105 reference to the new address. */ 1106 if (howto->pc_relative) 1107 relocation -= (input_section->output_section->vma 1108 + input_section->output_offset 1109 - input_section->vma); 1110 1111 /* Adjust the contents. */ 1112 if (relocation == 0) 1113 r = bfd_reloc_ok; 1114 else 1115 { 1116 if (int_rel.r_type != MIPS_R_REFHI) 1117 r = _bfd_relocate_contents (howto, input_bfd, relocation, 1118 (contents 1119 + int_rel.r_vaddr 1120 - input_section->vma)); 1121 else 1122 { 1123 mips_relocate_hi (&int_rel, 1124 use_lo ? &lo_int_rel : NULL, 1125 input_bfd, input_section, contents, 1126 relocation); 1127 r = bfd_reloc_ok; 1128 } 1129 } 1130 1131 /* Adjust the reloc address. */ 1132 int_rel.r_vaddr += (input_section->output_section->vma 1133 + input_section->output_offset 1134 - input_section->vma); 1135 1136 /* Save the changed reloc information. */ 1137 mips_ecoff_swap_reloc_out (input_bfd, &int_rel, ext_rel); 1138 } 1139 else 1140 { 1141 /* We are producing a final executable. */ 1142 if (int_rel.r_extern) 1143 { 1144 /* This is a reloc against a symbol. */ 1145 if (h->root.type == bfd_link_hash_defined 1146 || h->root.type == bfd_link_hash_defweak) 1147 { 1148 asection *hsec; 1149 1150 hsec = h->root.u.def.section; 1151 relocation = (h->root.u.def.value 1152 + hsec->output_section->vma 1153 + hsec->output_offset); 1154 } 1155 else 1156 { 1157 (*info->callbacks->undefined_symbol) 1158 (info, h->root.root.string, input_bfd, input_section, 1159 int_rel.r_vaddr - input_section->vma, TRUE); 1160 relocation = 0; 1161 } 1162 } 1163 else 1164 { 1165 /* This is a reloc against a section. */ 1166 relocation = (s->output_section->vma 1167 + s->output_offset 1168 - s->vma); 1169 1170 /* A PC relative reloc is already correct in the object 1171 file. Make it look like a pcrel_offset relocation by 1172 adding in the start address. */ 1173 if (howto->pc_relative) 1174 relocation += int_rel.r_vaddr; 1175 } 1176 1177 if (int_rel.r_type != MIPS_R_REFHI) 1178 r = _bfd_final_link_relocate (howto, 1179 input_bfd, 1180 input_section, 1181 contents, 1182 (int_rel.r_vaddr 1183 - input_section->vma), 1184 relocation, 1185 addend); 1186 else 1187 { 1188 mips_relocate_hi (&int_rel, 1189 use_lo ? &lo_int_rel : NULL, 1190 input_bfd, input_section, contents, 1191 relocation); 1192 r = bfd_reloc_ok; 1193 } 1194 } 1195 1196 /* MIPS_R_JMPADDR requires peculiar overflow detection. The 1197 instruction provides a 28 bit address (the two lower bits are 1198 implicit zeroes) which is combined with the upper four bits 1199 of the instruction address. */ 1200 if (r == bfd_reloc_ok 1201 && int_rel.r_type == MIPS_R_JMPADDR 1202 && (((relocation 1203 + addend 1204 + (int_rel.r_extern ? 0 : s->vma)) 1205 & 0xf0000000) 1206 != ((input_section->output_section->vma 1207 + input_section->output_offset 1208 + (int_rel.r_vaddr - input_section->vma)) 1209 & 0xf0000000))) 1210 r = bfd_reloc_overflow; 1211 1212 if (r != bfd_reloc_ok) 1213 { 1214 switch (r) 1215 { 1216 default: 1217 case bfd_reloc_outofrange: 1218 abort (); 1219 case bfd_reloc_overflow: 1220 { 1221 const char *name; 1222 1223 if (int_rel.r_extern) 1224 name = NULL; 1225 else 1226 name = bfd_section_name (input_bfd, s); 1227 (*info->callbacks->reloc_overflow) 1228 (info, (h ? &h->root : NULL), name, howto->name, 1229 (bfd_vma) 0, input_bfd, input_section, 1230 int_rel.r_vaddr - input_section->vma); 1231 } 1232 break; 1233 } 1234 } 1235 } 1236 1237 return TRUE; 1238 } 1239 1240 static void 1241 mips_ecoff_swap_coff_aux_in (bfd *abfd ATTRIBUTE_UNUSED, 1242 void *ext1 ATTRIBUTE_UNUSED, 1243 int type ATTRIBUTE_UNUSED, 1244 int in_class ATTRIBUTE_UNUSED, 1245 int indx ATTRIBUTE_UNUSED, 1246 int numaux ATTRIBUTE_UNUSED, 1247 void *in1 ATTRIBUTE_UNUSED) 1248 { 1249 } 1250 1251 static void 1252 mips_ecoff_swap_coff_sym_in (bfd *abfd ATTRIBUTE_UNUSED, 1253 void *ext1 ATTRIBUTE_UNUSED, 1254 void *in1 ATTRIBUTE_UNUSED) 1255 { 1256 } 1257 1258 static void 1259 mips_ecoff_swap_coff_lineno_in (bfd *abfd ATTRIBUTE_UNUSED, 1260 void *ext1 ATTRIBUTE_UNUSED, 1261 void *in1 ATTRIBUTE_UNUSED) 1262 { 1263 } 1264 1265 static unsigned int 1266 mips_ecoff_swap_coff_aux_out (bfd *abfd ATTRIBUTE_UNUSED, 1267 void *inp ATTRIBUTE_UNUSED, 1268 int type ATTRIBUTE_UNUSED, 1269 int in_class ATTRIBUTE_UNUSED, 1270 int indx ATTRIBUTE_UNUSED, 1271 int numaux ATTRIBUTE_UNUSED, 1272 void *extp ATTRIBUTE_UNUSED) 1273 { 1274 return 0; 1275 } 1276 1277 static unsigned int 1278 mips_ecoff_swap_coff_sym_out (bfd *abfd ATTRIBUTE_UNUSED, 1279 void *inp ATTRIBUTE_UNUSED, 1280 void *extp ATTRIBUTE_UNUSED) 1281 { 1282 return 0; 1283 } 1284 1285 static unsigned int 1286 mips_ecoff_swap_coff_lineno_out (bfd *abfd ATTRIBUTE_UNUSED, 1287 void *inp ATTRIBUTE_UNUSED, 1288 void *extp ATTRIBUTE_UNUSED) 1289 { 1290 return 0; 1291 } 1292 1293 static unsigned int 1294 mips_ecoff_swap_coff_reloc_out (bfd *abfd ATTRIBUTE_UNUSED, 1295 void *inp ATTRIBUTE_UNUSED, 1296 void *extp ATTRIBUTE_UNUSED) 1297 { 1298 return 0; 1299 } 1300 1301 /* This is the ECOFF backend structure. The backend field of the 1302 target vector points to this. */ 1303 1304 static const struct ecoff_backend_data mips_ecoff_backend_data = 1305 { 1306 /* COFF backend structure. */ 1307 { 1308 mips_ecoff_swap_coff_aux_in, mips_ecoff_swap_coff_sym_in, 1309 mips_ecoff_swap_coff_lineno_in, mips_ecoff_swap_coff_aux_out, 1310 mips_ecoff_swap_coff_sym_out, mips_ecoff_swap_coff_lineno_out, 1311 mips_ecoff_swap_coff_reloc_out, 1312 mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out, 1313 mips_ecoff_swap_scnhdr_out, 1314 FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, 1315 ECOFF_NO_LONG_SECTION_NAMES, 4, FALSE, 2, 32768, 1316 mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in, 1317 mips_ecoff_swap_scnhdr_in, NULL, 1318 mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, 1319 _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags, 1320 _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table, 1321 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1322 NULL, NULL, NULL 1323 }, 1324 /* Supported architecture. */ 1325 bfd_arch_mips, 1326 /* Initial portion of armap string. */ 1327 "__________", 1328 /* The page boundary used to align sections in a demand-paged 1329 executable file. E.g., 0x1000. */ 1330 0x1000, 1331 /* TRUE if the .rdata section is part of the text segment, as on the 1332 Alpha. FALSE if .rdata is part of the data segment, as on the 1333 MIPS. */ 1334 FALSE, 1335 /* Bitsize of constructor entries. */ 1336 32, 1337 /* Reloc to use for constructor entries. */ 1338 &mips_howto_table[MIPS_R_REFWORD], 1339 { 1340 /* Symbol table magic number. */ 1341 magicSym, 1342 /* Alignment of debugging information. E.g., 4. */ 1343 4, 1344 /* Sizes of external symbolic information. */ 1345 sizeof (struct hdr_ext), 1346 sizeof (struct dnr_ext), 1347 sizeof (struct pdr_ext), 1348 sizeof (struct sym_ext), 1349 sizeof (struct opt_ext), 1350 sizeof (struct fdr_ext), 1351 sizeof (struct rfd_ext), 1352 sizeof (struct ext_ext), 1353 /* Functions to swap in external symbolic data. */ 1354 ecoff_swap_hdr_in, 1355 ecoff_swap_dnr_in, 1356 ecoff_swap_pdr_in, 1357 ecoff_swap_sym_in, 1358 ecoff_swap_opt_in, 1359 ecoff_swap_fdr_in, 1360 ecoff_swap_rfd_in, 1361 ecoff_swap_ext_in, 1362 _bfd_ecoff_swap_tir_in, 1363 _bfd_ecoff_swap_rndx_in, 1364 /* Functions to swap out external symbolic data. */ 1365 ecoff_swap_hdr_out, 1366 ecoff_swap_dnr_out, 1367 ecoff_swap_pdr_out, 1368 ecoff_swap_sym_out, 1369 ecoff_swap_opt_out, 1370 ecoff_swap_fdr_out, 1371 ecoff_swap_rfd_out, 1372 ecoff_swap_ext_out, 1373 _bfd_ecoff_swap_tir_out, 1374 _bfd_ecoff_swap_rndx_out, 1375 /* Function to read in symbolic data. */ 1376 _bfd_ecoff_slurp_symbolic_info 1377 }, 1378 /* External reloc size. */ 1379 RELSZ, 1380 /* Reloc swapping functions. */ 1381 mips_ecoff_swap_reloc_in, 1382 mips_ecoff_swap_reloc_out, 1383 /* Backend reloc tweaking. */ 1384 mips_adjust_reloc_in, 1385 mips_adjust_reloc_out, 1386 /* Relocate section contents while linking. */ 1387 mips_relocate_section, 1388 /* Do final adjustments to filehdr and aouthdr. */ 1389 NULL, 1390 /* Read an element from an archive at a given file position. */ 1391 _bfd_get_elt_at_filepos 1392 }; 1393 1394 /* Looking up a reloc type is MIPS specific. */ 1395 #define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup 1396 #define _bfd_ecoff_bfd_reloc_name_lookup mips_bfd_reloc_name_lookup 1397 1398 /* Getting relocated section contents is generic. */ 1399 #define _bfd_ecoff_bfd_get_relocated_section_contents \ 1400 bfd_generic_get_relocated_section_contents 1401 1402 /* Handling file windows is generic. */ 1403 #define _bfd_ecoff_get_section_contents_in_window \ 1404 _bfd_generic_get_section_contents_in_window 1405 1406 /* Relaxing sections is MIPS specific. */ 1407 #define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section 1408 1409 /* GC of sections is not done. */ 1410 #define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections 1411 1412 /* Input section flags is not implemented. */ 1413 #define _bfd_ecoff_bfd_lookup_section_flags bfd_generic_lookup_section_flags 1414 1415 /* Merging of sections is not done. */ 1416 #define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections 1417 1418 #define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section 1419 #define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group 1420 #define _bfd_ecoff_section_already_linked \ 1421 _bfd_coff_section_already_linked 1422 #define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol 1423 #define _bfd_ecoff_bfd_link_hide_symbol _bfd_generic_link_hide_symbol 1424 #define _bfd_ecoff_bfd_define_start_stop bfd_generic_define_start_stop 1425 #define _bfd_ecoff_set_reloc _bfd_generic_set_reloc 1426 1427 extern const bfd_target mips_ecoff_be_vec; 1428 1429 const bfd_target mips_ecoff_le_vec = 1430 { 1431 "ecoff-littlemips", /* name */ 1432 bfd_target_ecoff_flavour, 1433 BFD_ENDIAN_LITTLE, /* data byte order is little */ 1434 BFD_ENDIAN_LITTLE, /* header byte order is little */ 1435 1436 (HAS_RELOC | EXEC_P /* object flags */ 1437 | HAS_LINENO | HAS_DEBUG 1438 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 1439 1440 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA), 1441 0, /* leading underscore */ 1442 ' ', /* ar_pad_char */ 1443 15, /* ar_max_namelen */ 1444 0, /* match priority. */ 1445 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1446 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1447 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ 1448 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1449 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1450 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ 1451 1452 { /* bfd_check_format */ 1453 _bfd_dummy_target, 1454 coff_object_p, 1455 bfd_generic_archive_p, 1456 _bfd_dummy_target 1457 }, 1458 { /* bfd_set_format */ 1459 _bfd_bool_bfd_false_error, 1460 _bfd_ecoff_mkobject, 1461 _bfd_generic_mkarchive, 1462 _bfd_bool_bfd_false_error 1463 }, 1464 { /* bfd_write_contents */ 1465 _bfd_bool_bfd_false_error, 1466 _bfd_ecoff_write_object_contents, 1467 _bfd_write_archive_contents, 1468 _bfd_bool_bfd_false_error 1469 }, 1470 1471 BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), 1472 BFD_JUMP_TABLE_COPY (_bfd_ecoff), 1473 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1474 BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff), 1475 BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff), 1476 BFD_JUMP_TABLE_RELOCS (_bfd_ecoff), 1477 BFD_JUMP_TABLE_WRITE (_bfd_ecoff), 1478 BFD_JUMP_TABLE_LINK (_bfd_ecoff), 1479 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1480 1481 &mips_ecoff_be_vec, 1482 1483 &mips_ecoff_backend_data 1484 }; 1485 1486 const bfd_target mips_ecoff_be_vec = 1487 { 1488 "ecoff-bigmips", /* name */ 1489 bfd_target_ecoff_flavour, 1490 BFD_ENDIAN_BIG, /* data byte order is big */ 1491 BFD_ENDIAN_BIG, /* header byte order is big */ 1492 1493 (HAS_RELOC | EXEC_P /* object flags */ 1494 | HAS_LINENO | HAS_DEBUG 1495 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 1496 1497 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA), 1498 0, /* leading underscore */ 1499 ' ', /* ar_pad_char */ 1500 15, /* ar_max_namelen */ 1501 0, /* match priority. */ 1502 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1503 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1504 bfd_getb16, bfd_getb_signed_16, bfd_putb16, 1505 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1506 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1507 bfd_getb16, bfd_getb_signed_16, bfd_putb16, 1508 1509 { /* bfd_check_format */ 1510 _bfd_dummy_target, 1511 coff_object_p, 1512 bfd_generic_archive_p, 1513 _bfd_dummy_target 1514 }, 1515 { /* bfd_set_format */ 1516 _bfd_bool_bfd_false_error, 1517 _bfd_ecoff_mkobject, 1518 _bfd_generic_mkarchive, 1519 _bfd_bool_bfd_false_error 1520 }, 1521 { /* bfd_write_contents */ 1522 _bfd_bool_bfd_false_error, 1523 _bfd_ecoff_write_object_contents, 1524 _bfd_write_archive_contents, 1525 _bfd_bool_bfd_false_error 1526 }, 1527 1528 BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), 1529 BFD_JUMP_TABLE_COPY (_bfd_ecoff), 1530 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1531 BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff), 1532 BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff), 1533 BFD_JUMP_TABLE_RELOCS (_bfd_ecoff), 1534 BFD_JUMP_TABLE_WRITE (_bfd_ecoff), 1535 BFD_JUMP_TABLE_LINK (_bfd_ecoff), 1536 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1537 1538 &mips_ecoff_le_vec, 1539 1540 &mips_ecoff_backend_data 1541 }; 1542 1543 const bfd_target mips_ecoff_bele_vec = 1544 { 1545 "ecoff-biglittlemips", /* name */ 1546 bfd_target_ecoff_flavour, 1547 BFD_ENDIAN_LITTLE, /* data byte order is little */ 1548 BFD_ENDIAN_BIG, /* header byte order is big */ 1549 1550 (HAS_RELOC | EXEC_P /* object flags */ 1551 | HAS_LINENO | HAS_DEBUG 1552 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 1553 1554 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA), 1555 0, /* leading underscore */ 1556 ' ', /* ar_pad_char */ 1557 15, /* ar_max_namelen */ 1558 0, /* match priority. */ 1559 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1560 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1561 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ 1562 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1563 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1564 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ 1565 1566 { /* bfd_check_format */ 1567 _bfd_dummy_target, 1568 coff_object_p, 1569 bfd_generic_archive_p, 1570 _bfd_dummy_target 1571 }, 1572 { /* bfd_set_format */ 1573 _bfd_bool_bfd_false_error, 1574 _bfd_ecoff_mkobject, 1575 _bfd_generic_mkarchive, 1576 _bfd_bool_bfd_false_error 1577 }, 1578 { /* bfd_write_contents */ 1579 _bfd_bool_bfd_false_error, 1580 _bfd_ecoff_write_object_contents, 1581 _bfd_write_archive_contents, 1582 _bfd_bool_bfd_false_error 1583 }, 1584 1585 BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), 1586 BFD_JUMP_TABLE_COPY (_bfd_ecoff), 1587 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1588 BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff), 1589 BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff), 1590 BFD_JUMP_TABLE_RELOCS (_bfd_ecoff), 1591 BFD_JUMP_TABLE_WRITE (_bfd_ecoff), 1592 BFD_JUMP_TABLE_LINK (_bfd_ecoff), 1593 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1594 1595 NULL, 1596 1597 &mips_ecoff_backend_data 1598 }; 1599