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