coff-mips.c revision 1.1.1.8
1/* BFD back-end for MIPS Extended-Coff files. 2 Copyright (C) 1990-2022 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. */ 39static bfd_reloc_status_type 40mips_generic_reloc 41 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 42static bfd_reloc_status_type 43mips_refhi_reloc 44 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 45static bfd_reloc_status_type 46mips_reflo_reloc 47 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 48static bfd_reloc_status_type 49mips_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 80static 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 238static bool 239mips_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 270static void 271mips_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 308static void 309mips_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 348static void 349mips_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 379static void 380mips_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 397static bfd_reloc_status_type 398mips_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 426struct mips_hi 427{ 428 struct mips_hi *next; 429 bfd_byte *addr; 430 bfd_vma addend; 431}; 432 433/* FIXME: This should not be a static variable. */ 434 435static struct mips_hi *mips_refhi_list; 436 437static bfd_reloc_status_type 438mips_refhi_reloc (bfd *abfd ATTRIBUTE_UNUSED, 439 arelent *reloc_entry, 440 asymbol *symbol, 441 void * data, 442 asection *input_section, 443 bfd *output_bfd, 444 char **error_message ATTRIBUTE_UNUSED) 445{ 446 bfd_reloc_status_type ret; 447 bfd_vma relocation; 448 struct mips_hi *n; 449 450 /* If we're relocating, and this an external symbol, we don't want 451 to change anything. */ 452 if (output_bfd != (bfd *) NULL 453 && (symbol->flags & BSF_SECTION_SYM) == 0 454 && reloc_entry->addend == 0) 455 { 456 reloc_entry->address += input_section->output_offset; 457 return bfd_reloc_ok; 458 } 459 460 ret = bfd_reloc_ok; 461 if (bfd_is_und_section (symbol->section) 462 && output_bfd == (bfd *) NULL) 463 ret = bfd_reloc_undefined; 464 465 if (bfd_is_com_section (symbol->section)) 466 relocation = 0; 467 else 468 relocation = symbol->value; 469 470 relocation += symbol->section->output_section->vma; 471 relocation += symbol->section->output_offset; 472 relocation += reloc_entry->addend; 473 474 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) 475 return bfd_reloc_outofrange; 476 477 /* Save the information, and let REFLO do the actual relocation. */ 478 n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n); 479 if (n == NULL) 480 return bfd_reloc_outofrange; 481 n->addr = (bfd_byte *) data + reloc_entry->address; 482 n->addend = relocation; 483 n->next = mips_refhi_list; 484 mips_refhi_list = n; 485 486 if (output_bfd != (bfd *) NULL) 487 reloc_entry->address += input_section->output_offset; 488 489 return ret; 490} 491 492/* Do a REFLO relocation. This is a straightforward 16 bit inplace 493 relocation; this function exists in order to do the REFHI 494 relocation described above. */ 495 496static bfd_reloc_status_type 497mips_reflo_reloc (bfd *abfd, 498 arelent *reloc_entry, 499 asymbol *symbol, 500 void * data, 501 asection *input_section, 502 bfd *output_bfd, 503 char **error_message) 504{ 505 if (mips_refhi_list != NULL) 506 { 507 struct mips_hi *l; 508 509 l = mips_refhi_list; 510 while (l != NULL) 511 { 512 unsigned long insn; 513 unsigned long val; 514 unsigned long vallo; 515 struct mips_hi *next; 516 bfd_size_type octets = (reloc_entry->address 517 * OCTETS_PER_BYTE (abfd, input_section)); 518 bfd_byte *loc = (bfd_byte *) data + octets; 519 520 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, 521 input_section, octets)) 522 return bfd_reloc_outofrange; 523 524 /* Do the REFHI relocation. Note that we actually don't 525 need to know anything about the REFLO itself, except 526 where to find the low 16 bits of the addend needed by the 527 REFHI. */ 528 insn = bfd_get_32 (abfd, l->addr); 529 vallo = bfd_get_32 (abfd, loc) & 0xffff; 530 val = ((insn & 0xffff) << 16) + vallo; 531 val += l->addend; 532 533 /* The low order 16 bits are always treated as a signed 534 value. Therefore, a negative value in the low order bits 535 requires an adjustment in the high order bits. We need 536 to make this adjustment in two ways: once for the bits we 537 took from the data, and once for the bits we are putting 538 back in to the data. */ 539 if ((vallo & 0x8000) != 0) 540 val -= 0x10000; 541 if ((val & 0x8000) != 0) 542 val += 0x10000; 543 544 insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff); 545 bfd_put_32 (abfd, (bfd_vma) insn, l->addr); 546 547 next = l->next; 548 free (l); 549 l = next; 550 } 551 552 mips_refhi_list = NULL; 553 } 554 555 /* Now do the REFLO reloc in the usual way. */ 556 return mips_generic_reloc (abfd, reloc_entry, symbol, data, 557 input_section, output_bfd, error_message); 558} 559 560/* Do a GPREL relocation. This is a 16 bit value which must become 561 the offset from the gp register. */ 562 563static bfd_reloc_status_type 564mips_gprel_reloc (bfd *abfd ATTRIBUTE_UNUSED, 565 arelent *reloc_entry, 566 asymbol *symbol, 567 void * data, 568 asection *input_section, 569 bfd *output_bfd, 570 char **error_message ATTRIBUTE_UNUSED) 571{ 572 bool relocatable; 573 bfd_vma gp; 574 bfd_vma relocation; 575 unsigned long val; 576 unsigned long insn; 577 578 /* If we're relocating, and this is an external symbol with no 579 addend, we don't want to change anything. We will only have an 580 addend if this is a newly created reloc, not read from an ECOFF 581 file. */ 582 if (output_bfd != (bfd *) NULL 583 && (symbol->flags & BSF_SECTION_SYM) == 0 584 && reloc_entry->addend == 0) 585 { 586 reloc_entry->address += input_section->output_offset; 587 return bfd_reloc_ok; 588 } 589 590 if (output_bfd != (bfd *) NULL) 591 relocatable = true; 592 else 593 { 594 relocatable = false; 595 output_bfd = symbol->section->output_section->owner; 596 if (output_bfd == NULL) 597 return bfd_reloc_undefined; 598 } 599 600 /* We have to figure out the gp value, so that we can adjust the 601 symbol value correctly. We look up the symbol _gp in the output 602 BFD. If we can't find it, we're stuck. We cache it in the ECOFF 603 target data. We don't need to adjust the symbol value for an 604 external symbol if we are producing relocatable output. */ 605 gp = _bfd_get_gp_value (output_bfd); 606 if (gp == 0 607 && (! relocatable 608 || (symbol->flags & BSF_SECTION_SYM) != 0)) 609 { 610 if (relocatable) 611 { 612 /* Make up a value. */ 613 gp = symbol->section->output_section->vma + 0x4000; 614 _bfd_set_gp_value (output_bfd, gp); 615 } 616 else 617 { 618 unsigned int count; 619 asymbol **sym; 620 unsigned int i; 621 622 count = bfd_get_symcount (output_bfd); 623 sym = bfd_get_outsymbols (output_bfd); 624 625 if (sym == (asymbol **) NULL) 626 i = count; 627 else 628 { 629 for (i = 0; i < count; i++, sym++) 630 { 631 register const char *name; 632 633 name = bfd_asymbol_name (*sym); 634 if (*name == '_' && strcmp (name, "_gp") == 0) 635 { 636 gp = bfd_asymbol_value (*sym); 637 _bfd_set_gp_value (output_bfd, gp); 638 break; 639 } 640 } 641 } 642 643 if (i >= count) 644 { 645 /* Only get the error once. */ 646 gp = 4; 647 _bfd_set_gp_value (output_bfd, gp); 648 *error_message = 649 (char *) _("GP relative relocation when _gp not defined"); 650 return bfd_reloc_dangerous; 651 } 652 } 653 } 654 655 if (bfd_is_com_section (symbol->section)) 656 relocation = 0; 657 else 658 relocation = symbol->value; 659 660 relocation += symbol->section->output_section->vma; 661 relocation += symbol->section->output_offset; 662 663 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) 664 return bfd_reloc_outofrange; 665 666 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 667 668 /* Set val to the offset into the section or symbol. */ 669 val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff; 670 if (val & 0x8000) 671 val -= 0x10000; 672 673 /* Adjust val for the final section location and GP value. If we 674 are producing relocatable output, we don't want to do this for 675 an external symbol. */ 676 if (! relocatable 677 || (symbol->flags & BSF_SECTION_SYM) != 0) 678 val += relocation - gp; 679 680 insn = (insn &~ (unsigned) 0xffff) | (val & 0xffff); 681 bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + reloc_entry->address); 682 683 if (relocatable) 684 reloc_entry->address += input_section->output_offset; 685 686 /* Make sure it fit in 16 bits. */ 687 if ((long) val >= 0x8000 || (long) val < -0x8000) 688 return bfd_reloc_overflow; 689 690 return bfd_reloc_ok; 691} 692 693/* Get the howto structure for a generic reloc type. */ 694 695static reloc_howto_type * 696mips_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 697 bfd_reloc_code_real_type code) 698{ 699 int mips_type; 700 701 switch (code) 702 { 703 case BFD_RELOC_16: 704 mips_type = MIPS_R_REFHALF; 705 break; 706 case BFD_RELOC_32: 707 case BFD_RELOC_CTOR: 708 mips_type = MIPS_R_REFWORD; 709 break; 710 case BFD_RELOC_MIPS_JMP: 711 mips_type = MIPS_R_JMPADDR; 712 break; 713 case BFD_RELOC_HI16_S: 714 mips_type = MIPS_R_REFHI; 715 break; 716 case BFD_RELOC_LO16: 717 mips_type = MIPS_R_REFLO; 718 break; 719 case BFD_RELOC_GPREL16: 720 mips_type = MIPS_R_GPREL; 721 break; 722 case BFD_RELOC_MIPS_LITERAL: 723 mips_type = MIPS_R_LITERAL; 724 break; 725 case BFD_RELOC_16_PCREL_S2: 726 mips_type = MIPS_R_PCREL16; 727 break; 728 default: 729 return (reloc_howto_type *) NULL; 730 } 731 732 return &mips_howto_table[mips_type]; 733} 734 735static reloc_howto_type * 736mips_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 737 const char *r_name) 738{ 739 unsigned int i; 740 741 for (i = 0; 742 i < sizeof (mips_howto_table) / sizeof (mips_howto_table[0]); 743 i++) 744 if (mips_howto_table[i].name != NULL 745 && strcasecmp (mips_howto_table[i].name, r_name) == 0) 746 return &mips_howto_table[i]; 747 748 return NULL; 749} 750 751/* A helper routine for mips_relocate_section which handles the REFHI 752 relocations. The REFHI relocation must be followed by a REFLO 753 relocation, and the addend used is formed from the addends of both 754 instructions. */ 755 756static void 757mips_relocate_hi (struct internal_reloc *refhi, 758 struct internal_reloc *reflo, 759 bfd *input_bfd, 760 asection *input_section, 761 bfd_byte *contents, 762 bfd_vma relocation) 763{ 764 unsigned long insn; 765 unsigned long val; 766 unsigned long vallo; 767 768 if (refhi == NULL) 769 return; 770 771 insn = bfd_get_32 (input_bfd, 772 contents + refhi->r_vaddr - input_section->vma); 773 if (reflo == NULL) 774 vallo = 0; 775 else 776 vallo = (bfd_get_32 (input_bfd, 777 contents + reflo->r_vaddr - input_section->vma) 778 & 0xffff); 779 780 val = ((insn & 0xffff) << 16) + vallo; 781 val += relocation; 782 783 /* The low order 16 bits are always treated as a signed value. 784 Therefore, a negative value in the low order bits requires an 785 adjustment in the high order bits. We need to make this 786 adjustment in two ways: once for the bits we took from the data, 787 and once for the bits we are putting back in to the data. */ 788 if ((vallo & 0x8000) != 0) 789 val -= 0x10000; 790 791 if ((val & 0x8000) != 0) 792 val += 0x10000; 793 794 insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff); 795 bfd_put_32 (input_bfd, (bfd_vma) insn, 796 contents + refhi->r_vaddr - input_section->vma); 797} 798 799/* Relocate a section while linking a MIPS ECOFF file. */ 800 801static bool 802mips_relocate_section (bfd *output_bfd, 803 struct bfd_link_info *info, 804 bfd *input_bfd, 805 asection *input_section, 806 bfd_byte *contents, 807 void * external_relocs) 808{ 809 asection **symndx_to_section; 810 struct ecoff_link_hash_entry **sym_hashes; 811 bfd_vma gp; 812 bool gp_undefined; 813 struct external_reloc *ext_rel; 814 struct external_reloc *ext_rel_end; 815 unsigned int i; 816 bool got_lo; 817 struct internal_reloc lo_int_rel; 818 bfd_size_type amt; 819 820 BFD_ASSERT (input_bfd->xvec->byteorder 821 == output_bfd->xvec->byteorder); 822 823 /* We keep a table mapping the symndx found in an internal reloc to 824 the appropriate section. This is faster than looking up the 825 section by name each time. */ 826 symndx_to_section = ecoff_data (input_bfd)->symndx_to_section; 827 if (symndx_to_section == (asection **) NULL) 828 { 829 amt = NUM_RELOC_SECTIONS * sizeof (asection *); 830 symndx_to_section = (asection **) bfd_alloc (input_bfd, amt); 831 if (!symndx_to_section) 832 return false; 833 834 symndx_to_section[RELOC_SECTION_NONE] = NULL; 835 symndx_to_section[RELOC_SECTION_TEXT] = 836 bfd_get_section_by_name (input_bfd, ".text"); 837 symndx_to_section[RELOC_SECTION_RDATA] = 838 bfd_get_section_by_name (input_bfd, ".rdata"); 839 symndx_to_section[RELOC_SECTION_DATA] = 840 bfd_get_section_by_name (input_bfd, ".data"); 841 symndx_to_section[RELOC_SECTION_SDATA] = 842 bfd_get_section_by_name (input_bfd, ".sdata"); 843 symndx_to_section[RELOC_SECTION_SBSS] = 844 bfd_get_section_by_name (input_bfd, ".sbss"); 845 symndx_to_section[RELOC_SECTION_BSS] = 846 bfd_get_section_by_name (input_bfd, ".bss"); 847 symndx_to_section[RELOC_SECTION_INIT] = 848 bfd_get_section_by_name (input_bfd, ".init"); 849 symndx_to_section[RELOC_SECTION_LIT8] = 850 bfd_get_section_by_name (input_bfd, ".lit8"); 851 symndx_to_section[RELOC_SECTION_LIT4] = 852 bfd_get_section_by_name (input_bfd, ".lit4"); 853 symndx_to_section[RELOC_SECTION_XDATA] = NULL; 854 symndx_to_section[RELOC_SECTION_PDATA] = NULL; 855 symndx_to_section[RELOC_SECTION_FINI] = 856 bfd_get_section_by_name (input_bfd, ".fini"); 857 symndx_to_section[RELOC_SECTION_LITA] = NULL; 858 symndx_to_section[RELOC_SECTION_ABS] = NULL; 859 860 ecoff_data (input_bfd)->symndx_to_section = symndx_to_section; 861 } 862 863 sym_hashes = ecoff_data (input_bfd)->sym_hashes; 864 865 gp = _bfd_get_gp_value (output_bfd); 866 if (gp == 0) 867 gp_undefined = true; 868 else 869 gp_undefined = false; 870 871 got_lo = false; 872 873 ext_rel = (struct external_reloc *) external_relocs; 874 ext_rel_end = ext_rel + input_section->reloc_count; 875 for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++) 876 { 877 struct internal_reloc int_rel; 878 bool use_lo = false; 879 bfd_vma addend; 880 reloc_howto_type *howto; 881 struct ecoff_link_hash_entry *h = NULL; 882 asection *s = NULL; 883 bfd_vma relocation; 884 bfd_reloc_status_type r; 885 886 if (! got_lo) 887 mips_ecoff_swap_reloc_in (input_bfd, ext_rel, &int_rel); 888 else 889 { 890 int_rel = lo_int_rel; 891 got_lo = false; 892 } 893 894 BFD_ASSERT (int_rel.r_type 895 < sizeof mips_howto_table / sizeof mips_howto_table[0]); 896 897 /* The REFHI reloc requires special handling. It must be followed 898 by a REFLO reloc, and the addend is formed from both relocs. */ 899 if (int_rel.r_type == MIPS_R_REFHI) 900 { 901 struct external_reloc *lo_ext_rel; 902 903 /* As a GNU extension, permit an arbitrary number of REFHI 904 relocs before the REFLO reloc. This permits gcc to emit 905 the HI and LO relocs itself. */ 906 for (lo_ext_rel = ext_rel + 1; 907 lo_ext_rel < ext_rel_end; 908 lo_ext_rel++) 909 { 910 mips_ecoff_swap_reloc_in (input_bfd, lo_ext_rel, 911 &lo_int_rel); 912 if (lo_int_rel.r_type != int_rel.r_type) 913 break; 914 } 915 916 if (lo_ext_rel < ext_rel_end 917 && lo_int_rel.r_type == MIPS_R_REFLO 918 && int_rel.r_extern == lo_int_rel.r_extern 919 && int_rel.r_symndx == lo_int_rel.r_symndx) 920 { 921 use_lo = true; 922 if (lo_ext_rel == ext_rel + 1) 923 got_lo = true; 924 } 925 } 926 927 howto = &mips_howto_table[int_rel.r_type]; 928 929 if (int_rel.r_extern) 930 { 931 h = sym_hashes[int_rel.r_symndx]; 932 /* If h is NULL, that means that there is a reloc against an 933 external symbol which we thought was just a debugging 934 symbol. This should not happen. */ 935 if (h == (struct ecoff_link_hash_entry *) NULL) 936 abort (); 937 } 938 else 939 { 940 if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS) 941 s = NULL; 942 else 943 s = symndx_to_section[int_rel.r_symndx]; 944 945 if (s == (asection *) NULL) 946 abort (); 947 } 948 949 /* The GPREL reloc uses an addend: the difference in the GP 950 values. */ 951 if (int_rel.r_type != MIPS_R_GPREL 952 && int_rel.r_type != MIPS_R_LITERAL) 953 addend = 0; 954 else 955 { 956 if (gp_undefined) 957 { 958 (*info->callbacks->reloc_dangerous) 959 (info, _("GP relative relocation used when GP not defined"), 960 input_bfd, input_section, 961 int_rel.r_vaddr - input_section->vma); 962 /* Only give the error once per link. */ 963 gp = 4; 964 _bfd_set_gp_value (output_bfd, gp); 965 gp_undefined = false; 966 } 967 if (! int_rel.r_extern) 968 { 969 /* This is a relocation against a section. The current 970 addend in the instruction is the difference between 971 INPUT_SECTION->vma and the GP value of INPUT_BFD. We 972 must change this to be the difference between the 973 final definition (which will end up in RELOCATION) 974 and the GP value of OUTPUT_BFD (which is in GP). */ 975 addend = ecoff_data (input_bfd)->gp - gp; 976 } 977 else if (! bfd_link_relocatable (info) 978 || h->root.type == bfd_link_hash_defined 979 || h->root.type == bfd_link_hash_defweak) 980 { 981 /* This is a relocation against a defined symbol. The 982 current addend in the instruction is simply the 983 desired offset into the symbol (normally zero). We 984 are going to change this into a relocation against a 985 defined symbol, so we want the instruction to hold 986 the difference between the final definition of the 987 symbol (which will end up in RELOCATION) and the GP 988 value of OUTPUT_BFD (which is in GP). */ 989 addend = - gp; 990 } 991 else 992 { 993 /* This is a relocation against an undefined or common 994 symbol. The current addend in the instruction is 995 simply the desired offset into the symbol (normally 996 zero). We are generating relocatable output, and we 997 aren't going to define this symbol, so we just leave 998 the instruction alone. */ 999 addend = 0; 1000 } 1001 } 1002 1003 if (bfd_link_relocatable (info)) 1004 { 1005 /* We are generating relocatable output, and must convert 1006 the existing reloc. */ 1007 if (int_rel.r_extern) 1008 { 1009 if ((h->root.type == bfd_link_hash_defined 1010 || h->root.type == bfd_link_hash_defweak) 1011 && ! bfd_is_abs_section (h->root.u.def.section)) 1012 { 1013 const char *name; 1014 1015 /* This symbol is defined in the output. Convert 1016 the reloc from being against the symbol to being 1017 against the section. */ 1018 1019 /* Clear the r_extern bit. */ 1020 int_rel.r_extern = 0; 1021 1022 /* Compute a new r_symndx value. */ 1023 s = h->root.u.def.section; 1024 name = bfd_section_name (s->output_section); 1025 1026 int_rel.r_symndx = -1; 1027 switch (name[1]) 1028 { 1029 case 'b': 1030 if (strcmp (name, ".bss") == 0) 1031 int_rel.r_symndx = RELOC_SECTION_BSS; 1032 break; 1033 case 'd': 1034 if (strcmp (name, ".data") == 0) 1035 int_rel.r_symndx = RELOC_SECTION_DATA; 1036 break; 1037 case 'f': 1038 if (strcmp (name, ".fini") == 0) 1039 int_rel.r_symndx = RELOC_SECTION_FINI; 1040 break; 1041 case 'i': 1042 if (strcmp (name, ".init") == 0) 1043 int_rel.r_symndx = RELOC_SECTION_INIT; 1044 break; 1045 case 'l': 1046 if (strcmp (name, ".lit8") == 0) 1047 int_rel.r_symndx = RELOC_SECTION_LIT8; 1048 else if (strcmp (name, ".lit4") == 0) 1049 int_rel.r_symndx = RELOC_SECTION_LIT4; 1050 break; 1051 case 'r': 1052 if (strcmp (name, ".rdata") == 0) 1053 int_rel.r_symndx = RELOC_SECTION_RDATA; 1054 break; 1055 case 's': 1056 if (strcmp (name, ".sdata") == 0) 1057 int_rel.r_symndx = RELOC_SECTION_SDATA; 1058 else if (strcmp (name, ".sbss") == 0) 1059 int_rel.r_symndx = RELOC_SECTION_SBSS; 1060 break; 1061 case 't': 1062 if (strcmp (name, ".text") == 0) 1063 int_rel.r_symndx = RELOC_SECTION_TEXT; 1064 break; 1065 } 1066 1067 if (int_rel.r_symndx == -1) 1068 abort (); 1069 1070 /* Add the section VMA and the symbol value. */ 1071 relocation = (h->root.u.def.value 1072 + s->output_section->vma 1073 + s->output_offset); 1074 1075 /* For a PC relative relocation, the object file 1076 currently holds just the addend. We must adjust 1077 by the address to get the right value. */ 1078 if (howto->pc_relative) 1079 relocation -= int_rel.r_vaddr - input_section->vma; 1080 1081 h = NULL; 1082 } 1083 else 1084 { 1085 /* Change the symndx value to the right one for the 1086 output BFD. */ 1087 int_rel.r_symndx = h->indx; 1088 if (int_rel.r_symndx == -1) 1089 { 1090 /* This symbol is not being written out. */ 1091 (*info->callbacks->unattached_reloc) 1092 (info, h->root.root.string, input_bfd, input_section, 1093 int_rel.r_vaddr - input_section->vma); 1094 int_rel.r_symndx = 0; 1095 } 1096 relocation = 0; 1097 } 1098 } 1099 else 1100 { 1101 /* This is a relocation against a section. Adjust the 1102 value by the amount the section moved. */ 1103 relocation = (s->output_section->vma 1104 + s->output_offset 1105 - s->vma); 1106 } 1107 1108 relocation += addend; 1109 addend = 0; 1110 1111 /* Adjust a PC relative relocation by removing the reference 1112 to the original address in the section and including the 1113 reference to the new address. */ 1114 if (howto->pc_relative) 1115 relocation -= (input_section->output_section->vma 1116 + input_section->output_offset 1117 - input_section->vma); 1118 1119 /* Adjust the contents. */ 1120 if (relocation == 0) 1121 r = bfd_reloc_ok; 1122 else 1123 { 1124 if (int_rel.r_type != MIPS_R_REFHI) 1125 r = _bfd_relocate_contents (howto, input_bfd, relocation, 1126 (contents 1127 + int_rel.r_vaddr 1128 - input_section->vma)); 1129 else 1130 { 1131 mips_relocate_hi (&int_rel, 1132 use_lo ? &lo_int_rel : NULL, 1133 input_bfd, input_section, contents, 1134 relocation); 1135 r = bfd_reloc_ok; 1136 } 1137 } 1138 1139 /* Adjust the reloc address. */ 1140 int_rel.r_vaddr += (input_section->output_section->vma 1141 + input_section->output_offset 1142 - input_section->vma); 1143 1144 /* Save the changed reloc information. */ 1145 mips_ecoff_swap_reloc_out (input_bfd, &int_rel, ext_rel); 1146 } 1147 else 1148 { 1149 /* We are producing a final executable. */ 1150 if (int_rel.r_extern) 1151 { 1152 /* This is a reloc against a symbol. */ 1153 if (h->root.type == bfd_link_hash_defined 1154 || h->root.type == bfd_link_hash_defweak) 1155 { 1156 asection *hsec; 1157 1158 hsec = h->root.u.def.section; 1159 relocation = (h->root.u.def.value 1160 + hsec->output_section->vma 1161 + hsec->output_offset); 1162 } 1163 else 1164 { 1165 (*info->callbacks->undefined_symbol) 1166 (info, h->root.root.string, input_bfd, input_section, 1167 int_rel.r_vaddr - input_section->vma, true); 1168 relocation = 0; 1169 } 1170 } 1171 else 1172 { 1173 /* This is a reloc against a section. */ 1174 relocation = (s->output_section->vma 1175 + s->output_offset 1176 - s->vma); 1177 1178 /* A PC relative reloc is already correct in the object 1179 file. Make it look like a pcrel_offset relocation by 1180 adding in the start address. */ 1181 if (howto->pc_relative) 1182 relocation += int_rel.r_vaddr; 1183 } 1184 1185 if (int_rel.r_type != MIPS_R_REFHI) 1186 r = _bfd_final_link_relocate (howto, 1187 input_bfd, 1188 input_section, 1189 contents, 1190 (int_rel.r_vaddr 1191 - input_section->vma), 1192 relocation, 1193 addend); 1194 else 1195 { 1196 mips_relocate_hi (&int_rel, 1197 use_lo ? &lo_int_rel : NULL, 1198 input_bfd, input_section, contents, 1199 relocation); 1200 r = bfd_reloc_ok; 1201 } 1202 } 1203 1204 /* MIPS_R_JMPADDR requires peculiar overflow detection. The 1205 instruction provides a 28 bit address (the two lower bits are 1206 implicit zeroes) which is combined with the upper four bits 1207 of the instruction address. */ 1208 if (r == bfd_reloc_ok 1209 && int_rel.r_type == MIPS_R_JMPADDR 1210 && (((relocation 1211 + addend 1212 + (int_rel.r_extern ? 0 : s->vma)) 1213 & 0xf0000000) 1214 != ((input_section->output_section->vma 1215 + input_section->output_offset 1216 + (int_rel.r_vaddr - input_section->vma)) 1217 & 0xf0000000))) 1218 r = bfd_reloc_overflow; 1219 1220 if (r != bfd_reloc_ok) 1221 { 1222 switch (r) 1223 { 1224 default: 1225 case bfd_reloc_outofrange: 1226 abort (); 1227 case bfd_reloc_overflow: 1228 { 1229 const char *name; 1230 1231 if (int_rel.r_extern) 1232 name = NULL; 1233 else 1234 name = bfd_section_name (s); 1235 (*info->callbacks->reloc_overflow) 1236 (info, (h ? &h->root : NULL), name, howto->name, 1237 (bfd_vma) 0, input_bfd, input_section, 1238 int_rel.r_vaddr - input_section->vma); 1239 } 1240 break; 1241 } 1242 } 1243 } 1244 1245 return true; 1246} 1247 1248static void 1249mips_ecoff_swap_coff_aux_in (bfd *abfd ATTRIBUTE_UNUSED, 1250 void *ext1 ATTRIBUTE_UNUSED, 1251 int type ATTRIBUTE_UNUSED, 1252 int in_class ATTRIBUTE_UNUSED, 1253 int indx ATTRIBUTE_UNUSED, 1254 int numaux ATTRIBUTE_UNUSED, 1255 void *in1 ATTRIBUTE_UNUSED) 1256{ 1257} 1258 1259static void 1260mips_ecoff_swap_coff_sym_in (bfd *abfd ATTRIBUTE_UNUSED, 1261 void *ext1 ATTRIBUTE_UNUSED, 1262 void *in1 ATTRIBUTE_UNUSED) 1263{ 1264} 1265 1266static void 1267mips_ecoff_swap_coff_lineno_in (bfd *abfd ATTRIBUTE_UNUSED, 1268 void *ext1 ATTRIBUTE_UNUSED, 1269 void *in1 ATTRIBUTE_UNUSED) 1270{ 1271} 1272 1273static unsigned int 1274mips_ecoff_swap_coff_aux_out (bfd *abfd ATTRIBUTE_UNUSED, 1275 void *inp ATTRIBUTE_UNUSED, 1276 int type ATTRIBUTE_UNUSED, 1277 int in_class ATTRIBUTE_UNUSED, 1278 int indx ATTRIBUTE_UNUSED, 1279 int numaux ATTRIBUTE_UNUSED, 1280 void *extp ATTRIBUTE_UNUSED) 1281{ 1282 return 0; 1283} 1284 1285static unsigned int 1286mips_ecoff_swap_coff_sym_out (bfd *abfd ATTRIBUTE_UNUSED, 1287 void *inp ATTRIBUTE_UNUSED, 1288 void *extp ATTRIBUTE_UNUSED) 1289{ 1290 return 0; 1291} 1292 1293static unsigned int 1294mips_ecoff_swap_coff_lineno_out (bfd *abfd ATTRIBUTE_UNUSED, 1295 void *inp ATTRIBUTE_UNUSED, 1296 void *extp ATTRIBUTE_UNUSED) 1297{ 1298 return 0; 1299} 1300 1301static unsigned int 1302mips_ecoff_swap_coff_reloc_out (bfd *abfd ATTRIBUTE_UNUSED, 1303 void *inp ATTRIBUTE_UNUSED, 1304 void *extp ATTRIBUTE_UNUSED) 1305{ 1306 return 0; 1307} 1308 1309/* This is the ECOFF backend structure. The backend field of the 1310 target vector points to this. */ 1311 1312static const struct ecoff_backend_data mips_ecoff_backend_data = 1313{ 1314 /* COFF backend structure. */ 1315 { 1316 mips_ecoff_swap_coff_aux_in, mips_ecoff_swap_coff_sym_in, 1317 mips_ecoff_swap_coff_lineno_in, mips_ecoff_swap_coff_aux_out, 1318 mips_ecoff_swap_coff_sym_out, mips_ecoff_swap_coff_lineno_out, 1319 mips_ecoff_swap_coff_reloc_out, 1320 mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out, 1321 mips_ecoff_swap_scnhdr_out, 1322 FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, true, 1323 ECOFF_NO_LONG_SECTION_NAMES, 4, false, 2, 32768, 1324 mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in, 1325 mips_ecoff_swap_scnhdr_in, NULL, 1326 mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, 1327 _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags, 1328 _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table, 1329 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1330 NULL, NULL, NULL 1331 }, 1332 /* Supported architecture. */ 1333 bfd_arch_mips, 1334 /* Initial portion of armap string. */ 1335 "__________", 1336 /* The page boundary used to align sections in a demand-paged 1337 executable file. E.g., 0x1000. */ 1338 0x1000, 1339 /* TRUE if the .rdata section is part of the text segment, as on the 1340 Alpha. FALSE if .rdata is part of the data segment, as on the 1341 MIPS. */ 1342 false, 1343 /* Bitsize of constructor entries. */ 1344 32, 1345 /* Reloc to use for constructor entries. */ 1346 &mips_howto_table[MIPS_R_REFWORD], 1347 { 1348 /* Symbol table magic number. */ 1349 magicSym, 1350 /* Alignment of debugging information. E.g., 4. */ 1351 4, 1352 /* Sizes of external symbolic information. */ 1353 sizeof (struct hdr_ext), 1354 sizeof (struct dnr_ext), 1355 sizeof (struct pdr_ext), 1356 sizeof (struct sym_ext), 1357 sizeof (struct opt_ext), 1358 sizeof (struct fdr_ext), 1359 sizeof (struct rfd_ext), 1360 sizeof (struct ext_ext), 1361 /* Functions to swap in external symbolic data. */ 1362 ecoff_swap_hdr_in, 1363 ecoff_swap_dnr_in, 1364 ecoff_swap_pdr_in, 1365 ecoff_swap_sym_in, 1366 ecoff_swap_opt_in, 1367 ecoff_swap_fdr_in, 1368 ecoff_swap_rfd_in, 1369 ecoff_swap_ext_in, 1370 _bfd_ecoff_swap_tir_in, 1371 _bfd_ecoff_swap_rndx_in, 1372 /* Functions to swap out external symbolic data. */ 1373 ecoff_swap_hdr_out, 1374 ecoff_swap_dnr_out, 1375 ecoff_swap_pdr_out, 1376 ecoff_swap_sym_out, 1377 ecoff_swap_opt_out, 1378 ecoff_swap_fdr_out, 1379 ecoff_swap_rfd_out, 1380 ecoff_swap_ext_out, 1381 _bfd_ecoff_swap_tir_out, 1382 _bfd_ecoff_swap_rndx_out, 1383 /* Function to read in symbolic data. */ 1384 _bfd_ecoff_slurp_symbolic_info 1385 }, 1386 /* External reloc size. */ 1387 RELSZ, 1388 /* Reloc swapping functions. */ 1389 mips_ecoff_swap_reloc_in, 1390 mips_ecoff_swap_reloc_out, 1391 /* Backend reloc tweaking. */ 1392 mips_adjust_reloc_in, 1393 mips_adjust_reloc_out, 1394 /* Relocate section contents while linking. */ 1395 mips_relocate_section, 1396 /* Do final adjustments to filehdr and aouthdr. */ 1397 NULL, 1398 /* Read an element from an archive at a given file position. */ 1399 _bfd_get_elt_at_filepos 1400}; 1401 1402/* Looking up a reloc type is MIPS specific. */ 1403#define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup 1404#define _bfd_ecoff_bfd_reloc_name_lookup mips_bfd_reloc_name_lookup 1405 1406/* Getting relocated section contents is generic. */ 1407#define _bfd_ecoff_bfd_get_relocated_section_contents \ 1408 bfd_generic_get_relocated_section_contents 1409 1410/* Handling file windows is generic. */ 1411#define _bfd_ecoff_get_section_contents_in_window \ 1412 _bfd_generic_get_section_contents_in_window 1413 1414/* Relaxing sections is MIPS specific. */ 1415#define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section 1416 1417/* GC of sections is not done. */ 1418#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections 1419 1420/* Input section flags is not implemented. */ 1421#define _bfd_ecoff_bfd_lookup_section_flags bfd_generic_lookup_section_flags 1422 1423/* Merging of sections is not done. */ 1424#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections 1425 1426#define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section 1427#define _bfd_ecoff_bfd_group_name bfd_generic_group_name 1428#define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group 1429#define _bfd_ecoff_section_already_linked \ 1430 _bfd_coff_section_already_linked 1431#define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol 1432#define _bfd_ecoff_bfd_link_hide_symbol _bfd_generic_link_hide_symbol 1433#define _bfd_ecoff_bfd_define_start_stop bfd_generic_define_start_stop 1434#define _bfd_ecoff_set_reloc _bfd_generic_set_reloc 1435 1436extern const bfd_target mips_ecoff_be_vec; 1437 1438const bfd_target mips_ecoff_le_vec = 1439{ 1440 "ecoff-littlemips", /* name */ 1441 bfd_target_ecoff_flavour, 1442 BFD_ENDIAN_LITTLE, /* data byte order is little */ 1443 BFD_ENDIAN_LITTLE, /* header byte order is little */ 1444 1445 (HAS_RELOC | EXEC_P /* object flags */ 1446 | HAS_LINENO | HAS_DEBUG 1447 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 1448 1449 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE 1450 | SEC_DATA | SEC_SMALL_DATA), 1451 0, /* leading underscore */ 1452 ' ', /* ar_pad_char */ 1453 15, /* ar_max_namelen */ 1454 0, /* match priority. */ 1455 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ 1456 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1457 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1458 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ 1459 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1460 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1461 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ 1462 1463 { /* bfd_check_format */ 1464 _bfd_dummy_target, 1465 coff_object_p, 1466 bfd_generic_archive_p, 1467 _bfd_dummy_target 1468 }, 1469 { /* bfd_set_format */ 1470 _bfd_bool_bfd_false_error, 1471 _bfd_ecoff_mkobject, 1472 _bfd_generic_mkarchive, 1473 _bfd_bool_bfd_false_error 1474 }, 1475 { /* bfd_write_contents */ 1476 _bfd_bool_bfd_false_error, 1477 _bfd_ecoff_write_object_contents, 1478 _bfd_write_archive_contents, 1479 _bfd_bool_bfd_false_error 1480 }, 1481 1482 BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), 1483 BFD_JUMP_TABLE_COPY (_bfd_ecoff), 1484 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1485 BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff), 1486 BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff), 1487 BFD_JUMP_TABLE_RELOCS (_bfd_ecoff), 1488 BFD_JUMP_TABLE_WRITE (_bfd_ecoff), 1489 BFD_JUMP_TABLE_LINK (_bfd_ecoff), 1490 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1491 1492 &mips_ecoff_be_vec, 1493 1494 &mips_ecoff_backend_data 1495}; 1496 1497const bfd_target mips_ecoff_be_vec = 1498{ 1499 "ecoff-bigmips", /* name */ 1500 bfd_target_ecoff_flavour, 1501 BFD_ENDIAN_BIG, /* data byte order is big */ 1502 BFD_ENDIAN_BIG, /* header byte order is big */ 1503 1504 (HAS_RELOC | EXEC_P /* object flags */ 1505 | HAS_LINENO | HAS_DEBUG 1506 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 1507 1508 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE 1509 | SEC_DATA | SEC_SMALL_DATA), 1510 0, /* leading underscore */ 1511 ' ', /* ar_pad_char */ 1512 15, /* ar_max_namelen */ 1513 0, /* match priority. */ 1514 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ 1515 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1516 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1517 bfd_getb16, bfd_getb_signed_16, bfd_putb16, 1518 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1519 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1520 bfd_getb16, bfd_getb_signed_16, bfd_putb16, 1521 1522 { /* bfd_check_format */ 1523 _bfd_dummy_target, 1524 coff_object_p, 1525 bfd_generic_archive_p, 1526 _bfd_dummy_target 1527 }, 1528 { /* bfd_set_format */ 1529 _bfd_bool_bfd_false_error, 1530 _bfd_ecoff_mkobject, 1531 _bfd_generic_mkarchive, 1532 _bfd_bool_bfd_false_error 1533 }, 1534 { /* bfd_write_contents */ 1535 _bfd_bool_bfd_false_error, 1536 _bfd_ecoff_write_object_contents, 1537 _bfd_write_archive_contents, 1538 _bfd_bool_bfd_false_error 1539 }, 1540 1541 BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), 1542 BFD_JUMP_TABLE_COPY (_bfd_ecoff), 1543 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1544 BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff), 1545 BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff), 1546 BFD_JUMP_TABLE_RELOCS (_bfd_ecoff), 1547 BFD_JUMP_TABLE_WRITE (_bfd_ecoff), 1548 BFD_JUMP_TABLE_LINK (_bfd_ecoff), 1549 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1550 1551 &mips_ecoff_le_vec, 1552 1553 &mips_ecoff_backend_data 1554}; 1555 1556const bfd_target mips_ecoff_bele_vec = 1557{ 1558 "ecoff-biglittlemips", /* name */ 1559 bfd_target_ecoff_flavour, 1560 BFD_ENDIAN_LITTLE, /* data byte order is little */ 1561 BFD_ENDIAN_BIG, /* header byte order is big */ 1562 1563 (HAS_RELOC | EXEC_P /* object flags */ 1564 | HAS_LINENO | HAS_DEBUG 1565 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 1566 1567 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE 1568 | SEC_DATA | SEC_SMALL_DATA), 1569 0, /* leading underscore */ 1570 ' ', /* ar_pad_char */ 1571 15, /* ar_max_namelen */ 1572 0, /* match priority. */ 1573 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ 1574 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1575 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1576 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ 1577 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1578 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1579 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ 1580 1581 { /* bfd_check_format */ 1582 _bfd_dummy_target, 1583 coff_object_p, 1584 bfd_generic_archive_p, 1585 _bfd_dummy_target 1586 }, 1587 { /* bfd_set_format */ 1588 _bfd_bool_bfd_false_error, 1589 _bfd_ecoff_mkobject, 1590 _bfd_generic_mkarchive, 1591 _bfd_bool_bfd_false_error 1592 }, 1593 { /* bfd_write_contents */ 1594 _bfd_bool_bfd_false_error, 1595 _bfd_ecoff_write_object_contents, 1596 _bfd_write_archive_contents, 1597 _bfd_bool_bfd_false_error 1598 }, 1599 1600 BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), 1601 BFD_JUMP_TABLE_COPY (_bfd_ecoff), 1602 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1603 BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff), 1604 BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff), 1605 BFD_JUMP_TABLE_RELOCS (_bfd_ecoff), 1606 BFD_JUMP_TABLE_WRITE (_bfd_ecoff), 1607 BFD_JUMP_TABLE_LINK (_bfd_ecoff), 1608 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1609 1610 NULL, 1611 1612 &mips_ecoff_backend_data 1613}; 1614