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