Back to index

cell-binutils  2.17cvs20070401
coff-mips.c
Go to the documentation of this file.
00001 /* BFD back-end for MIPS Extended-Coff files.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
00003    2000, 2001, 2002, 2003, 2004, 2007
00004    Free Software Foundation, Inc.
00005    Original version by Per Bothner.
00006    Full support added by Ian Lance Taylor, ian@cygnus.com.
00007 
00008 This file is part of BFD, the Binary File Descriptor library.
00009 
00010 This program is free software; you can redistribute it and/or modify
00011 it under the terms of the GNU General Public License as published by
00012 the Free Software Foundation; either version 2 of the License, or
00013 (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00023 
00024 #include "bfd.h"
00025 #include "sysdep.h"
00026 #include "bfdlink.h"
00027 #include "libbfd.h"
00028 #include "coff/internal.h"
00029 #include "coff/sym.h"
00030 #include "coff/symconst.h"
00031 #include "coff/ecoff.h"
00032 #include "coff/mips.h"
00033 #include "libcoff.h"
00034 #include "libecoff.h"
00035 
00036 /* Prototypes for static functions.  */
00037 
00038 static bfd_boolean mips_ecoff_bad_format_hook
00039   PARAMS ((bfd *abfd, PTR filehdr));
00040 static void mips_ecoff_swap_reloc_in
00041   PARAMS ((bfd *, PTR, struct internal_reloc *));
00042 static void mips_ecoff_swap_reloc_out
00043   PARAMS ((bfd *, const struct internal_reloc *, PTR));
00044 static void mips_adjust_reloc_in
00045   PARAMS ((bfd *, const struct internal_reloc *, arelent *));
00046 static void mips_adjust_reloc_out
00047   PARAMS ((bfd *, const arelent *, struct internal_reloc *));
00048 static bfd_reloc_status_type mips_generic_reloc
00049   PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
00050           asection *section, bfd *output_bfd, char **error));
00051 static bfd_reloc_status_type mips_refhi_reloc
00052   PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
00053           asection *section, bfd *output_bfd, char **error));
00054 static bfd_reloc_status_type mips_reflo_reloc
00055   PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
00056           asection *section, bfd *output_bfd, char **error));
00057 static bfd_reloc_status_type mips_gprel_reloc
00058   PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
00059           asection *section, bfd *output_bfd, char **error));
00060 static void mips_relocate_hi
00061   PARAMS ((struct internal_reloc *refhi, struct internal_reloc *reflo,
00062           bfd *input_bfd, asection *input_section, bfd_byte *contents,
00063           bfd_vma relocation));
00064 static bfd_boolean mips_relocate_section
00065   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR));
00066 static reloc_howto_type *mips_bfd_reloc_type_lookup
00067   PARAMS ((bfd *, bfd_reloc_code_real_type));
00068 
00069 /* ECOFF has COFF sections, but the debugging information is stored in
00070    a completely different format.  ECOFF targets use some of the
00071    swapping routines from coffswap.h, and some of the generic COFF
00072    routines in coffgen.c, but, unlike the real COFF targets, do not
00073    use coffcode.h itself.
00074 
00075    Get the generic COFF swapping routines, except for the reloc,
00076    symbol, and lineno ones.  Give them ECOFF names.  */
00077 #define MIPSECOFF
00078 #define NO_COFF_RELOCS
00079 #define NO_COFF_SYMBOLS
00080 #define NO_COFF_LINENOS
00081 #define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
00082 #define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
00083 #define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
00084 #define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
00085 #define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
00086 #define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
00087 #include "coffswap.h"
00088 
00089 /* Get the ECOFF swapping routines.  */
00090 #define ECOFF_32
00091 #include "ecoffswap.h"
00092 
00093 /* How to process the various relocs types.  */
00094 
00095 static reloc_howto_type mips_howto_table[] =
00096 {
00097   /* Reloc type 0 is ignored.  The reloc reading code ensures that
00098      this is a reference to the .abs section, which will cause
00099      bfd_perform_relocation to do nothing.  */
00100   HOWTO (MIPS_R_IGNORE,     /* type */
00101         0,                  /* rightshift */
00102         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00103         8,                  /* bitsize */
00104         FALSE,                     /* pc_relative */
00105         0,                  /* bitpos */
00106         complain_overflow_dont, /* complain_on_overflow */
00107         0,                  /* special_function */
00108         "IGNORE",           /* name */
00109         FALSE,                     /* partial_inplace */
00110         0,                  /* src_mask */
00111         0,                  /* dst_mask */
00112         FALSE),             /* pcrel_offset */
00113 
00114   /* A 16 bit reference to a symbol, normally from a data section.  */
00115   HOWTO (MIPS_R_REFHALF,    /* type */
00116         0,                  /* rightshift */
00117         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00118         16,                 /* bitsize */
00119         FALSE,                     /* pc_relative */
00120         0,                  /* bitpos */
00121         complain_overflow_bitfield, /* complain_on_overflow */
00122         mips_generic_reloc, /* special_function */
00123         "REFHALF",          /* name */
00124         TRUE,               /* partial_inplace */
00125         0xffff,             /* src_mask */
00126         0xffff,             /* dst_mask */
00127         FALSE),             /* pcrel_offset */
00128 
00129   /* A 32 bit reference to a symbol, normally from a data section.  */
00130   HOWTO (MIPS_R_REFWORD,    /* type */
00131         0,                  /* rightshift */
00132         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00133         32,                 /* bitsize */
00134         FALSE,                     /* pc_relative */
00135         0,                  /* bitpos */
00136         complain_overflow_bitfield, /* complain_on_overflow */
00137         mips_generic_reloc, /* special_function */
00138         "REFWORD",          /* name */
00139         TRUE,               /* partial_inplace */
00140         0xffffffff,         /* src_mask */
00141         0xffffffff,         /* dst_mask */
00142         FALSE),             /* pcrel_offset */
00143 
00144   /* A 26 bit absolute jump address.  */
00145   HOWTO (MIPS_R_JMPADDR,    /* type */
00146         2,                  /* rightshift */
00147         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00148         26,                 /* bitsize */
00149         FALSE,                     /* pc_relative */
00150         0,                  /* bitpos */
00151         complain_overflow_dont, /* complain_on_overflow */
00152                             /* This needs complex overflow
00153                                detection, because the upper four
00154                                bits must match the PC.  */
00155         mips_generic_reloc, /* special_function */
00156         "JMPADDR",          /* name */
00157         TRUE,               /* partial_inplace */
00158         0x3ffffff,          /* src_mask */
00159         0x3ffffff,          /* dst_mask */
00160         FALSE),             /* pcrel_offset */
00161 
00162   /* The high 16 bits of a symbol value.  Handled by the function
00163      mips_refhi_reloc.  */
00164   HOWTO (MIPS_R_REFHI,             /* type */
00165         16,                 /* rightshift */
00166         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00167         16,                 /* bitsize */
00168         FALSE,                     /* pc_relative */
00169         0,                  /* bitpos */
00170         complain_overflow_bitfield, /* complain_on_overflow */
00171         mips_refhi_reloc,   /* special_function */
00172         "REFHI",            /* name */
00173         TRUE,               /* partial_inplace */
00174         0xffff,             /* src_mask */
00175         0xffff,             /* dst_mask */
00176         FALSE),             /* pcrel_offset */
00177 
00178   /* The low 16 bits of a symbol value.  */
00179   HOWTO (MIPS_R_REFLO,             /* type */
00180         0,                  /* rightshift */
00181         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00182         16,                 /* bitsize */
00183         FALSE,                     /* pc_relative */
00184         0,                  /* bitpos */
00185         complain_overflow_dont, /* complain_on_overflow */
00186         mips_reflo_reloc,   /* special_function */
00187         "REFLO",            /* name */
00188         TRUE,               /* partial_inplace */
00189         0xffff,             /* src_mask */
00190         0xffff,             /* dst_mask */
00191         FALSE),             /* pcrel_offset */
00192 
00193   /* A reference to an offset from the gp register.  Handled by the
00194      function mips_gprel_reloc.  */
00195   HOWTO (MIPS_R_GPREL,             /* type */
00196         0,                  /* rightshift */
00197         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00198         16,                 /* bitsize */
00199         FALSE,                     /* pc_relative */
00200         0,                  /* bitpos */
00201         complain_overflow_signed, /* complain_on_overflow */
00202         mips_gprel_reloc,   /* special_function */
00203         "GPREL",            /* name */
00204         TRUE,               /* partial_inplace */
00205         0xffff,             /* src_mask */
00206         0xffff,             /* dst_mask */
00207         FALSE),             /* pcrel_offset */
00208 
00209   /* A reference to a literal using an offset from the gp register.
00210      Handled by the function mips_gprel_reloc.  */
00211   HOWTO (MIPS_R_LITERAL,    /* type */
00212         0,                  /* rightshift */
00213         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00214         16,                 /* bitsize */
00215         FALSE,                     /* pc_relative */
00216         0,                  /* bitpos */
00217         complain_overflow_signed, /* complain_on_overflow */
00218         mips_gprel_reloc,   /* special_function */
00219         "LITERAL",          /* name */
00220         TRUE,               /* partial_inplace */
00221         0xffff,             /* src_mask */
00222         0xffff,             /* dst_mask */
00223         FALSE),             /* pcrel_offset */
00224 
00225   EMPTY_HOWTO (8),
00226   EMPTY_HOWTO (9),
00227   EMPTY_HOWTO (10),
00228   EMPTY_HOWTO (11),
00229 
00230   /* FIXME: This relocation is used (internally only) to represent branches
00231      when assembling.  It should never appear in output files, and
00232      be removed.  (It used to be used for embedded-PIC support.)  */
00233   HOWTO (MIPS_R_PCREL16,    /* type */
00234         2,                  /* rightshift */
00235         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00236         16,                 /* bitsize */
00237         TRUE,               /* pc_relative */
00238         0,                  /* bitpos */
00239         complain_overflow_signed, /* complain_on_overflow */
00240         mips_generic_reloc, /* special_function */
00241         "PCREL16",          /* name */
00242         TRUE,               /* partial_inplace */
00243         0xffff,             /* src_mask */
00244         0xffff,             /* dst_mask */
00245         TRUE),                     /* pcrel_offset */
00246 };
00247 
00248 #define MIPS_HOWTO_COUNT \
00249   (sizeof mips_howto_table / sizeof mips_howto_table[0])
00250 
00251 /* See whether the magic number matches.  */
00252 
00253 static bfd_boolean
00254 mips_ecoff_bad_format_hook (abfd, filehdr)
00255      bfd *abfd;
00256      PTR filehdr;
00257 {
00258   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
00259 
00260   switch (internal_f->f_magic)
00261     {
00262     case MIPS_MAGIC_1:
00263       /* I don't know what endianness this implies.  */
00264       return TRUE;
00265 
00266     case MIPS_MAGIC_BIG:
00267     case MIPS_MAGIC_BIG2:
00268     case MIPS_MAGIC_BIG3:
00269       return bfd_big_endian (abfd);
00270 
00271     case MIPS_MAGIC_LITTLE:
00272     case MIPS_MAGIC_LITTLE2:
00273     case MIPS_MAGIC_LITTLE3:
00274       return bfd_little_endian (abfd);
00275 
00276     default:
00277       return FALSE;
00278     }
00279 }
00280 
00281 /* Reloc handling.  MIPS ECOFF relocs are packed into 8 bytes in
00282    external form.  They use a bit which indicates whether the symbol
00283    is external.  */
00284 
00285 /* Swap a reloc in.  */
00286 
00287 static void
00288 mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
00289      bfd *abfd;
00290      PTR ext_ptr;
00291      struct internal_reloc *intern;
00292 {
00293   const RELOC *ext = (RELOC *) ext_ptr;
00294 
00295   intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr);
00296   if (bfd_header_big_endian (abfd))
00297     {
00298       intern->r_symndx = (((int) ext->r_bits[0]
00299                         << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
00300                        | ((int) ext->r_bits[1]
00301                           << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
00302                        | ((int) ext->r_bits[2]
00303                           << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
00304       intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
00305                      >> RELOC_BITS3_TYPE_SH_BIG);
00306       intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
00307     }
00308   else
00309     {
00310       intern->r_symndx = (((int) ext->r_bits[0]
00311                         << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
00312                        | ((int) ext->r_bits[1]
00313                           << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
00314                        | ((int) ext->r_bits[2]
00315                           << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
00316       intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
00317                       >> RELOC_BITS3_TYPE_SH_LITTLE)
00318                      | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
00319                         << RELOC_BITS3_TYPEHI_SH_LITTLE));
00320       intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
00321     }
00322 }
00323 
00324 /* Swap a reloc out.  */
00325 
00326 static void
00327 mips_ecoff_swap_reloc_out (abfd, intern, dst)
00328      bfd *abfd;
00329      const struct internal_reloc *intern;
00330      PTR dst;
00331 {
00332   RELOC *ext = (RELOC *) dst;
00333   long r_symndx;
00334 
00335   BFD_ASSERT (intern->r_extern
00336              || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
00337 
00338   r_symndx = intern->r_symndx;
00339 
00340   H_PUT_32 (abfd, intern->r_vaddr, ext->r_vaddr);
00341   if (bfd_header_big_endian (abfd))
00342     {
00343       ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
00344       ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
00345       ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
00346       ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
00347                       & RELOC_BITS3_TYPE_BIG)
00348                      | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
00349     }
00350   else
00351     {
00352       ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
00353       ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
00354       ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
00355       ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
00356                       & RELOC_BITS3_TYPE_LITTLE)
00357                      | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
00358                          & RELOC_BITS3_TYPEHI_LITTLE))
00359                      | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
00360     }
00361 }
00362 
00363 /* Finish canonicalizing a reloc.  Part of this is generic to all
00364    ECOFF targets, and that part is in ecoff.c.  The rest is done in
00365    this backend routine.  It must fill in the howto field.  */
00366 
00367 static void
00368 mips_adjust_reloc_in (abfd, intern, rptr)
00369      bfd *abfd;
00370      const struct internal_reloc *intern;
00371      arelent *rptr;
00372 {
00373   if (intern->r_type > MIPS_R_PCREL16)
00374     abort ();
00375 
00376   if (! intern->r_extern
00377       && (intern->r_type == MIPS_R_GPREL
00378          || intern->r_type == MIPS_R_LITERAL))
00379     rptr->addend += ecoff_data (abfd)->gp;
00380 
00381   /* If the type is MIPS_R_IGNORE, make sure this is a reference to
00382      the absolute section so that the reloc is ignored.  */
00383   if (intern->r_type == MIPS_R_IGNORE)
00384     rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
00385 
00386   rptr->howto = &mips_howto_table[intern->r_type];
00387 }
00388 
00389 /* Make any adjustments needed to a reloc before writing it out.  None
00390    are needed for MIPS.  */
00391 
00392 static void
00393 mips_adjust_reloc_out (abfd, rel, intern)
00394      bfd *abfd ATTRIBUTE_UNUSED;
00395      const arelent *rel ATTRIBUTE_UNUSED;
00396      struct internal_reloc *intern ATTRIBUTE_UNUSED;
00397 {
00398 }
00399 
00400 /* ECOFF relocs are either against external symbols, or against
00401    sections.  If we are producing relocatable output, and the reloc
00402    is against an external symbol, and nothing has given us any
00403    additional addend, the resulting reloc will also be against the
00404    same symbol.  In such a case, we don't want to change anything
00405    about the way the reloc is handled, since it will all be done at
00406    final link time.  Rather than put special case code into
00407    bfd_perform_relocation, all the reloc types use this howto
00408    function.  It just short circuits the reloc if producing
00409    relocatable output against an external symbol.  */
00410 
00411 static bfd_reloc_status_type
00412 mips_generic_reloc (abfd,
00413                   reloc_entry,
00414                   symbol,
00415                   data,
00416                   input_section,
00417                   output_bfd,
00418                   error_message)
00419      bfd *abfd ATTRIBUTE_UNUSED;
00420      arelent *reloc_entry;
00421      asymbol *symbol;
00422      PTR data ATTRIBUTE_UNUSED;
00423      asection *input_section;
00424      bfd *output_bfd;
00425      char **error_message ATTRIBUTE_UNUSED;
00426 {
00427   if (output_bfd != (bfd *) NULL
00428       && (symbol->flags & BSF_SECTION_SYM) == 0
00429       && reloc_entry->addend == 0)
00430     {
00431       reloc_entry->address += input_section->output_offset;
00432       return bfd_reloc_ok;
00433     }
00434 
00435   return bfd_reloc_continue;
00436 }
00437 
00438 /* Do a REFHI relocation.  This has to be done in combination with a
00439    REFLO reloc, because there is a carry from the REFLO to the REFHI.
00440    Here we just save the information we need; we do the actual
00441    relocation when we see the REFLO.  MIPS ECOFF requires that the
00442    REFLO immediately follow the REFHI.  As a GNU extension, we permit
00443    an arbitrary number of HI relocs to be associated with a single LO
00444    reloc.  This extension permits gcc to output the HI and LO relocs
00445    itself.  */
00446 
00447 struct mips_hi
00448 {
00449   struct mips_hi *next;
00450   bfd_byte *addr;
00451   bfd_vma addend;
00452 };
00453 
00454 /* FIXME: This should not be a static variable.  */
00455 
00456 static struct mips_hi *mips_refhi_list;
00457 
00458 static bfd_reloc_status_type
00459 mips_refhi_reloc (abfd,
00460                 reloc_entry,
00461                 symbol,
00462                 data,
00463                 input_section,
00464                 output_bfd,
00465                 error_message)
00466      bfd *abfd ATTRIBUTE_UNUSED;
00467      arelent *reloc_entry;
00468      asymbol *symbol;
00469      PTR data;
00470      asection *input_section;
00471      bfd *output_bfd;
00472      char **error_message ATTRIBUTE_UNUSED;
00473 {
00474   bfd_reloc_status_type ret;
00475   bfd_vma relocation;
00476   struct mips_hi *n;
00477 
00478   /* If we're relocating, and this an external symbol, we don't want
00479      to change anything.  */
00480   if (output_bfd != (bfd *) NULL
00481       && (symbol->flags & BSF_SECTION_SYM) == 0
00482       && reloc_entry->addend == 0)
00483     {
00484       reloc_entry->address += input_section->output_offset;
00485       return bfd_reloc_ok;
00486     }
00487 
00488   ret = bfd_reloc_ok;
00489   if (bfd_is_und_section (symbol->section)
00490       && output_bfd == (bfd *) NULL)
00491     ret = bfd_reloc_undefined;
00492 
00493   if (bfd_is_com_section (symbol->section))
00494     relocation = 0;
00495   else
00496     relocation = symbol->value;
00497 
00498   relocation += symbol->section->output_section->vma;
00499   relocation += symbol->section->output_offset;
00500   relocation += reloc_entry->addend;
00501 
00502   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
00503     return bfd_reloc_outofrange;
00504 
00505   /* Save the information, and let REFLO do the actual relocation.  */
00506   n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
00507   if (n == NULL)
00508     return bfd_reloc_outofrange;
00509   n->addr = (bfd_byte *) data + reloc_entry->address;
00510   n->addend = relocation;
00511   n->next = mips_refhi_list;
00512   mips_refhi_list = n;
00513 
00514   if (output_bfd != (bfd *) NULL)
00515     reloc_entry->address += input_section->output_offset;
00516 
00517   return ret;
00518 }
00519 
00520 /* Do a REFLO relocation.  This is a straightforward 16 bit inplace
00521    relocation; this function exists in order to do the REFHI
00522    relocation described above.  */
00523 
00524 static bfd_reloc_status_type
00525 mips_reflo_reloc (abfd,
00526                 reloc_entry,
00527                 symbol,
00528                 data,
00529                 input_section,
00530                 output_bfd,
00531                 error_message)
00532      bfd *abfd;
00533      arelent *reloc_entry;
00534      asymbol *symbol;
00535      PTR data;
00536      asection *input_section;
00537      bfd *output_bfd;
00538      char **error_message;
00539 {
00540   if (mips_refhi_list != NULL)
00541     {
00542       struct mips_hi *l;
00543 
00544       l = mips_refhi_list;
00545       while (l != NULL)
00546        {
00547          unsigned long insn;
00548          unsigned long val;
00549          unsigned long vallo;
00550          struct mips_hi *next;
00551 
00552          /* Do the REFHI relocation.  Note that we actually don't
00553             need to know anything about the REFLO itself, except
00554             where to find the low 16 bits of the addend needed by the
00555             REFHI.  */
00556          insn = bfd_get_32 (abfd, l->addr);
00557          vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
00558                  & 0xffff);
00559          val = ((insn & 0xffff) << 16) + vallo;
00560          val += l->addend;
00561 
00562          /* The low order 16 bits are always treated as a signed
00563             value.  Therefore, a negative value in the low order bits
00564             requires an adjustment in the high order bits.  We need
00565             to make this adjustment in two ways: once for the bits we
00566             took from the data, and once for the bits we are putting
00567             back in to the data.  */
00568          if ((vallo & 0x8000) != 0)
00569            val -= 0x10000;
00570          if ((val & 0x8000) != 0)
00571            val += 0x10000;
00572 
00573          insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
00574          bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
00575 
00576          next = l->next;
00577          free (l);
00578          l = next;
00579        }
00580 
00581       mips_refhi_list = NULL;
00582     }
00583 
00584   /* Now do the REFLO reloc in the usual way.  */
00585   return mips_generic_reloc (abfd, reloc_entry, symbol, data,
00586                            input_section, output_bfd, error_message);
00587 }
00588 
00589 /* Do a GPREL relocation.  This is a 16 bit value which must become
00590    the offset from the gp register.  */
00591 
00592 static bfd_reloc_status_type
00593 mips_gprel_reloc (abfd,
00594                 reloc_entry,
00595                 symbol,
00596                 data,
00597                 input_section,
00598                 output_bfd,
00599                 error_message)
00600      bfd *abfd;
00601      arelent *reloc_entry;
00602      asymbol *symbol;
00603      PTR data;
00604      asection *input_section;
00605      bfd *output_bfd;
00606      char **error_message;
00607 {
00608   bfd_boolean relocatable;
00609   bfd_vma gp;
00610   bfd_vma relocation;
00611   unsigned long val;
00612   unsigned long insn;
00613 
00614   /* If we're relocating, and this is an external symbol with no
00615      addend, we don't want to change anything.  We will only have an
00616      addend if this is a newly created reloc, not read from an ECOFF
00617      file.  */
00618   if (output_bfd != (bfd *) NULL
00619       && (symbol->flags & BSF_SECTION_SYM) == 0
00620       && reloc_entry->addend == 0)
00621     {
00622       reloc_entry->address += input_section->output_offset;
00623       return bfd_reloc_ok;
00624     }
00625 
00626   if (output_bfd != (bfd *) NULL)
00627     relocatable = TRUE;
00628   else
00629     {
00630       relocatable = FALSE;
00631       output_bfd = symbol->section->output_section->owner;
00632     }
00633 
00634   if (bfd_is_und_section (symbol->section) && ! relocatable)
00635     return bfd_reloc_undefined;
00636 
00637   /* We have to figure out the gp value, so that we can adjust the
00638      symbol value correctly.  We look up the symbol _gp in the output
00639      BFD.  If we can't find it, we're stuck.  We cache it in the ECOFF
00640      target data.  We don't need to adjust the symbol value for an
00641      external symbol if we are producing relocatable output.  */
00642   gp = _bfd_get_gp_value (output_bfd);
00643   if (gp == 0
00644       && (! relocatable
00645          || (symbol->flags & BSF_SECTION_SYM) != 0))
00646     {
00647       if (relocatable)
00648        {
00649          /* Make up a value.  */
00650          gp = symbol->section->output_section->vma + 0x4000;
00651          _bfd_set_gp_value (output_bfd, gp);
00652        }
00653       else
00654        {
00655          unsigned int count;
00656          asymbol **sym;
00657          unsigned int i;
00658 
00659          count = bfd_get_symcount (output_bfd);
00660          sym = bfd_get_outsymbols (output_bfd);
00661 
00662          if (sym == (asymbol **) NULL)
00663            i = count;
00664          else
00665            {
00666              for (i = 0; i < count; i++, sym++)
00667               {
00668                 register const char *name;
00669 
00670                 name = bfd_asymbol_name (*sym);
00671                 if (*name == '_' && strcmp (name, "_gp") == 0)
00672                   {
00673                     gp = bfd_asymbol_value (*sym);
00674                     _bfd_set_gp_value (output_bfd, gp);
00675                     break;
00676                   }
00677               }
00678            }
00679 
00680          if (i >= count)
00681            {
00682              /* Only get the error once.  */
00683              gp = 4;
00684              _bfd_set_gp_value (output_bfd, gp);
00685              *error_message =
00686               (char *) _("GP relative relocation when _gp not defined");
00687              return bfd_reloc_dangerous;
00688            }
00689        }
00690     }
00691 
00692   if (bfd_is_com_section (symbol->section))
00693     relocation = 0;
00694   else
00695     relocation = symbol->value;
00696 
00697   relocation += symbol->section->output_section->vma;
00698   relocation += symbol->section->output_offset;
00699 
00700   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
00701     return bfd_reloc_outofrange;
00702 
00703   insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
00704 
00705   /* Set val to the offset into the section or symbol.  */
00706   val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
00707   if (val & 0x8000)
00708     val -= 0x10000;
00709 
00710   /* Adjust val for the final section location and GP value.  If we
00711      are producing relocatable output, we don't want to do this for
00712      an external symbol.  */
00713   if (! relocatable
00714       || (symbol->flags & BSF_SECTION_SYM) != 0)
00715     val += relocation - gp;
00716 
00717   insn = (insn &~ (unsigned) 0xffff) | (val & 0xffff);
00718   bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + reloc_entry->address);
00719 
00720   if (relocatable)
00721     reloc_entry->address += input_section->output_offset;
00722 
00723   /* Make sure it fit in 16 bits.  */
00724   if ((long) val >= 0x8000 || (long) val < -0x8000)
00725     return bfd_reloc_overflow;
00726 
00727   return bfd_reloc_ok;
00728 }
00729 
00730 /* Get the howto structure for a generic reloc type.  */
00731 
00732 static reloc_howto_type *
00733 mips_bfd_reloc_type_lookup (abfd, code)
00734      bfd *abfd ATTRIBUTE_UNUSED;
00735      bfd_reloc_code_real_type code;
00736 {
00737   int mips_type;
00738 
00739   switch (code)
00740     {
00741     case BFD_RELOC_16:
00742       mips_type = MIPS_R_REFHALF;
00743       break;
00744     case BFD_RELOC_32:
00745     case BFD_RELOC_CTOR:
00746       mips_type = MIPS_R_REFWORD;
00747       break;
00748     case BFD_RELOC_MIPS_JMP:
00749       mips_type = MIPS_R_JMPADDR;
00750       break;
00751     case BFD_RELOC_HI16_S:
00752       mips_type = MIPS_R_REFHI;
00753       break;
00754     case BFD_RELOC_LO16:
00755       mips_type = MIPS_R_REFLO;
00756       break;
00757     case BFD_RELOC_GPREL16:
00758       mips_type = MIPS_R_GPREL;
00759       break;
00760     case BFD_RELOC_MIPS_LITERAL:
00761       mips_type = MIPS_R_LITERAL;
00762       break;
00763     case BFD_RELOC_16_PCREL_S2:
00764       mips_type = MIPS_R_PCREL16;
00765       break;
00766     default:
00767       return (reloc_howto_type *) NULL;
00768     }
00769 
00770   return &mips_howto_table[mips_type];
00771 }
00772 
00773 static reloc_howto_type *
00774 mips_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00775                          const char *r_name)
00776 {
00777   unsigned int i;
00778 
00779   for (i = 0;
00780        i < sizeof (mips_howto_table) / sizeof (mips_howto_table[0]);
00781        i++)
00782     if (mips_howto_table[i].name != NULL
00783        && strcasecmp (mips_howto_table[i].name, r_name) == 0)
00784       return &mips_howto_table[i];
00785 
00786   return NULL;
00787 }
00788 
00789 /* A helper routine for mips_relocate_section which handles the REFHI
00790    relocations.  The REFHI relocation must be followed by a REFLO
00791    relocation, and the addend used is formed from the addends of both
00792    instructions.  */
00793 
00794 static void
00795 mips_relocate_hi (refhi, reflo, input_bfd, input_section, contents,
00796                 relocation)
00797      struct internal_reloc *refhi;
00798      struct internal_reloc *reflo;
00799      bfd *input_bfd;
00800      asection *input_section;
00801      bfd_byte *contents;
00802      bfd_vma relocation;
00803 {
00804   unsigned long insn;
00805   unsigned long val;
00806   unsigned long vallo;
00807 
00808   if (refhi == NULL)
00809     return;
00810 
00811   insn = bfd_get_32 (input_bfd,
00812                    contents + refhi->r_vaddr - input_section->vma);
00813   if (reflo == NULL)
00814     vallo = 0;
00815   else
00816     vallo = (bfd_get_32 (input_bfd,
00817                       contents + reflo->r_vaddr - input_section->vma)
00818             & 0xffff);
00819 
00820   val = ((insn & 0xffff) << 16) + vallo;
00821   val += relocation;
00822 
00823   /* The low order 16 bits are always treated as a signed value.
00824      Therefore, a negative value in the low order bits requires an
00825      adjustment in the high order bits.  We need to make this
00826      adjustment in two ways: once for the bits we took from the data,
00827      and once for the bits we are putting back in to the data.  */
00828   if ((vallo & 0x8000) != 0)
00829     val -= 0x10000;
00830 
00831   if ((val & 0x8000) != 0)
00832     val += 0x10000;
00833 
00834   insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
00835   bfd_put_32 (input_bfd, (bfd_vma) insn,
00836              contents + refhi->r_vaddr - input_section->vma);
00837 }
00838 
00839 /* Relocate a section while linking a MIPS ECOFF file.  */
00840 
00841 static bfd_boolean
00842 mips_relocate_section (output_bfd, info, input_bfd, input_section,
00843                      contents, external_relocs)
00844      bfd *output_bfd;
00845      struct bfd_link_info *info;
00846      bfd *input_bfd;
00847      asection *input_section;
00848      bfd_byte *contents;
00849      PTR external_relocs;
00850 {
00851   asection **symndx_to_section;
00852   struct ecoff_link_hash_entry **sym_hashes;
00853   bfd_vma gp;
00854   bfd_boolean gp_undefined;
00855   struct external_reloc *ext_rel;
00856   struct external_reloc *ext_rel_end;
00857   unsigned int i;
00858   bfd_boolean got_lo;
00859   struct internal_reloc lo_int_rel;
00860   bfd_size_type amt;
00861 
00862   BFD_ASSERT (input_bfd->xvec->byteorder
00863              == output_bfd->xvec->byteorder);
00864 
00865   /* We keep a table mapping the symndx found in an internal reloc to
00866      the appropriate section.  This is faster than looking up the
00867      section by name each time.  */
00868   symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
00869   if (symndx_to_section == (asection **) NULL)
00870     {
00871       amt = NUM_RELOC_SECTIONS * sizeof (asection *);
00872       symndx_to_section = (asection **) bfd_alloc (input_bfd, amt);
00873       if (!symndx_to_section)
00874        return FALSE;
00875 
00876       symndx_to_section[RELOC_SECTION_NONE] = NULL;
00877       symndx_to_section[RELOC_SECTION_TEXT] =
00878        bfd_get_section_by_name (input_bfd, ".text");
00879       symndx_to_section[RELOC_SECTION_RDATA] =
00880        bfd_get_section_by_name (input_bfd, ".rdata");
00881       symndx_to_section[RELOC_SECTION_DATA] =
00882        bfd_get_section_by_name (input_bfd, ".data");
00883       symndx_to_section[RELOC_SECTION_SDATA] =
00884        bfd_get_section_by_name (input_bfd, ".sdata");
00885       symndx_to_section[RELOC_SECTION_SBSS] =
00886        bfd_get_section_by_name (input_bfd, ".sbss");
00887       symndx_to_section[RELOC_SECTION_BSS] =
00888        bfd_get_section_by_name (input_bfd, ".bss");
00889       symndx_to_section[RELOC_SECTION_INIT] =
00890        bfd_get_section_by_name (input_bfd, ".init");
00891       symndx_to_section[RELOC_SECTION_LIT8] =
00892        bfd_get_section_by_name (input_bfd, ".lit8");
00893       symndx_to_section[RELOC_SECTION_LIT4] =
00894        bfd_get_section_by_name (input_bfd, ".lit4");
00895       symndx_to_section[RELOC_SECTION_XDATA] = NULL;
00896       symndx_to_section[RELOC_SECTION_PDATA] = NULL;
00897       symndx_to_section[RELOC_SECTION_FINI] =
00898        bfd_get_section_by_name (input_bfd, ".fini");
00899       symndx_to_section[RELOC_SECTION_LITA] = NULL;
00900       symndx_to_section[RELOC_SECTION_ABS] = NULL;
00901 
00902       ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
00903     }
00904 
00905   sym_hashes = ecoff_data (input_bfd)->sym_hashes;
00906 
00907   gp = _bfd_get_gp_value (output_bfd);
00908   if (gp == 0)
00909     gp_undefined = TRUE;
00910   else
00911     gp_undefined = FALSE;
00912 
00913   got_lo = FALSE;
00914 
00915   ext_rel = (struct external_reloc *) external_relocs;
00916   ext_rel_end = ext_rel + input_section->reloc_count;
00917   for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
00918     {
00919       struct internal_reloc int_rel;
00920       bfd_boolean use_lo = FALSE;
00921       bfd_vma addend;
00922       reloc_howto_type *howto;
00923       struct ecoff_link_hash_entry *h = NULL;
00924       asection *s = NULL;
00925       bfd_vma relocation;
00926       bfd_reloc_status_type r;
00927 
00928       if (! got_lo)
00929        mips_ecoff_swap_reloc_in (input_bfd, (PTR) ext_rel, &int_rel);
00930       else
00931        {
00932          int_rel = lo_int_rel;
00933          got_lo = FALSE;
00934        }
00935 
00936       BFD_ASSERT (int_rel.r_type
00937                 < sizeof mips_howto_table / sizeof mips_howto_table[0]);
00938 
00939       /* The REFHI reloc requires special handling.  It must be followed
00940         by a REFLO reloc, and the addend is formed from both relocs.  */
00941       if (int_rel.r_type == MIPS_R_REFHI)
00942        {
00943          struct external_reloc *lo_ext_rel;
00944 
00945          /* As a GNU extension, permit an arbitrary number of REFHI
00946              relocs before the REFLO reloc.  This permits gcc to emit
00947             the HI and LO relocs itself.  */
00948          for (lo_ext_rel = ext_rel + 1;
00949               lo_ext_rel < ext_rel_end;
00950               lo_ext_rel++)
00951            {
00952              mips_ecoff_swap_reloc_in (input_bfd, (PTR) lo_ext_rel,
00953                                    &lo_int_rel);
00954              if (lo_int_rel.r_type != int_rel.r_type)
00955               break;
00956            }
00957 
00958          if (lo_ext_rel < ext_rel_end
00959              && lo_int_rel.r_type == MIPS_R_REFLO
00960              && int_rel.r_extern == lo_int_rel.r_extern
00961              && int_rel.r_symndx == lo_int_rel.r_symndx)
00962            {
00963              use_lo = TRUE;
00964              if (lo_ext_rel == ext_rel + 1)
00965               got_lo = TRUE;
00966            }
00967        }
00968 
00969       howto = &mips_howto_table[int_rel.r_type];
00970 
00971       if (int_rel.r_extern)
00972        {
00973          h = sym_hashes[int_rel.r_symndx];
00974          /* If h is NULL, that means that there is a reloc against an
00975             external symbol which we thought was just a debugging
00976             symbol.  This should not happen.  */
00977          if (h == (struct ecoff_link_hash_entry *) NULL)
00978            abort ();
00979        }
00980       else
00981        {
00982          if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
00983            s = NULL;
00984          else
00985            s = symndx_to_section[int_rel.r_symndx];
00986 
00987          if (s == (asection *) NULL)
00988            abort ();
00989        }
00990 
00991       /* The GPREL reloc uses an addend: the difference in the GP
00992         values.  */
00993       if (int_rel.r_type != MIPS_R_GPREL
00994          && int_rel.r_type != MIPS_R_LITERAL)
00995        addend = 0;
00996       else
00997        {
00998          if (gp_undefined)
00999            {
01000              if (! ((*info->callbacks->reloc_dangerous)
01001                    (info, _("GP relative relocation used when GP not defined"),
01002                     input_bfd, input_section,
01003                     int_rel.r_vaddr - input_section->vma)))
01004               return FALSE;
01005              /* Only give the error once per link.  */
01006              gp = 4;
01007              _bfd_set_gp_value (output_bfd, gp);
01008              gp_undefined = FALSE;
01009            }
01010          if (! int_rel.r_extern)
01011            {
01012              /* This is a relocation against a section.  The current
01013                addend in the instruction is the difference between
01014                INPUT_SECTION->vma and the GP value of INPUT_BFD.  We
01015                must change this to be the difference between the
01016                final definition (which will end up in RELOCATION)
01017                and the GP value of OUTPUT_BFD (which is in GP).  */
01018              addend = ecoff_data (input_bfd)->gp - gp;
01019            }
01020          else if (! info->relocatable
01021                  || h->root.type == bfd_link_hash_defined
01022                  || h->root.type == bfd_link_hash_defweak)
01023            {
01024              /* This is a relocation against a defined symbol.  The
01025                current addend in the instruction is simply the
01026                desired offset into the symbol (normally zero).  We
01027                are going to change this into a relocation against a
01028                defined symbol, so we want the instruction to hold
01029                the difference between the final definition of the
01030                symbol (which will end up in RELOCATION) and the GP
01031                value of OUTPUT_BFD (which is in GP).  */
01032              addend = - gp;
01033            }
01034          else
01035            {
01036              /* This is a relocation against an undefined or common
01037                symbol.  The current addend in the instruction is
01038                simply the desired offset into the symbol (normally
01039                zero).  We are generating relocatable output, and we
01040                aren't going to define this symbol, so we just leave
01041                the instruction alone.  */
01042              addend = 0;
01043            }
01044        }
01045 
01046       if (info->relocatable)
01047        {
01048          /* We are generating relocatable output, and must convert
01049             the existing reloc.  */
01050          if (int_rel.r_extern)
01051            {
01052              if ((h->root.type == bfd_link_hash_defined
01053                  || h->root.type == bfd_link_hash_defweak)
01054                 && ! bfd_is_abs_section (h->root.u.def.section))
01055               {
01056                 const char *name;
01057 
01058                 /* This symbol is defined in the output.  Convert
01059                    the reloc from being against the symbol to being
01060                    against the section.  */
01061 
01062                 /* Clear the r_extern bit.  */
01063                 int_rel.r_extern = 0;
01064 
01065                 /* Compute a new r_symndx value.  */
01066                 s = h->root.u.def.section;
01067                 name = bfd_get_section_name (output_bfd,
01068                                           s->output_section);
01069 
01070                 int_rel.r_symndx = -1;
01071                 switch (name[1])
01072                   {
01073                   case 'b':
01074                     if (strcmp (name, ".bss") == 0)
01075                      int_rel.r_symndx = RELOC_SECTION_BSS;
01076                     break;
01077                   case 'd':
01078                     if (strcmp (name, ".data") == 0)
01079                      int_rel.r_symndx = RELOC_SECTION_DATA;
01080                     break;
01081                   case 'f':
01082                     if (strcmp (name, ".fini") == 0)
01083                      int_rel.r_symndx = RELOC_SECTION_FINI;
01084                     break;
01085                   case 'i':
01086                     if (strcmp (name, ".init") == 0)
01087                      int_rel.r_symndx = RELOC_SECTION_INIT;
01088                     break;
01089                   case 'l':
01090                     if (strcmp (name, ".lit8") == 0)
01091                      int_rel.r_symndx = RELOC_SECTION_LIT8;
01092                     else if (strcmp (name, ".lit4") == 0)
01093                      int_rel.r_symndx = RELOC_SECTION_LIT4;
01094                     break;
01095                   case 'r':
01096                     if (strcmp (name, ".rdata") == 0)
01097                      int_rel.r_symndx = RELOC_SECTION_RDATA;
01098                     break;
01099                   case 's':
01100                     if (strcmp (name, ".sdata") == 0)
01101                      int_rel.r_symndx = RELOC_SECTION_SDATA;
01102                     else if (strcmp (name, ".sbss") == 0)
01103                      int_rel.r_symndx = RELOC_SECTION_SBSS;
01104                     break;
01105                   case 't':
01106                     if (strcmp (name, ".text") == 0)
01107                      int_rel.r_symndx = RELOC_SECTION_TEXT;
01108                     break;
01109                   }
01110 
01111                 if (int_rel.r_symndx == -1)
01112                   abort ();
01113 
01114                 /* Add the section VMA and the symbol value.  */
01115                 relocation = (h->root.u.def.value
01116                             + s->output_section->vma
01117                             + s->output_offset);
01118 
01119                 /* For a PC relative relocation, the object file
01120                    currently holds just the addend.  We must adjust
01121                    by the address to get the right value.  */
01122                 if (howto->pc_relative)
01123                   relocation -= int_rel.r_vaddr - input_section->vma;
01124 
01125                 h = NULL;
01126               }
01127              else
01128               {
01129                 /* Change the symndx value to the right one for the
01130                    output BFD.  */
01131                 int_rel.r_symndx = h->indx;
01132                 if (int_rel.r_symndx == -1)
01133                   {
01134                     /* This symbol is not being written out.  */
01135                     if (! ((*info->callbacks->unattached_reloc)
01136                           (info, h->root.root.string, input_bfd,
01137                            input_section,
01138                            int_rel.r_vaddr - input_section->vma)))
01139                      return FALSE;
01140                     int_rel.r_symndx = 0;
01141                   }
01142                 relocation = 0;
01143               }
01144            }
01145          else
01146            {
01147              /* This is a relocation against a section.  Adjust the
01148                value by the amount the section moved.  */
01149              relocation = (s->output_section->vma
01150                          + s->output_offset
01151                          - s->vma);
01152            }
01153 
01154          relocation += addend;
01155          addend = 0;
01156 
01157          /* Adjust a PC relative relocation by removing the reference
01158             to the original address in the section and including the
01159             reference to the new address.  */
01160          if (howto->pc_relative)
01161            relocation -= (input_section->output_section->vma
01162                         + input_section->output_offset
01163                         - input_section->vma);
01164 
01165          /* Adjust the contents.  */
01166          if (relocation == 0)
01167            r = bfd_reloc_ok;
01168          else
01169            {
01170              if (int_rel.r_type != MIPS_R_REFHI)
01171               r = _bfd_relocate_contents (howto, input_bfd, relocation,
01172                                        (contents
01173                                         + int_rel.r_vaddr
01174                                         - input_section->vma));
01175              else
01176               {
01177                 mips_relocate_hi (&int_rel,
01178                                 use_lo ? &lo_int_rel : NULL,
01179                                 input_bfd, input_section, contents,
01180                                 relocation);
01181                 r = bfd_reloc_ok;
01182               }
01183            }
01184 
01185          /* Adjust the reloc address.  */
01186          int_rel.r_vaddr += (input_section->output_section->vma
01187                            + input_section->output_offset
01188                            - input_section->vma);
01189 
01190          /* Save the changed reloc information.  */
01191          mips_ecoff_swap_reloc_out (input_bfd, &int_rel, (PTR) ext_rel);
01192        }
01193       else
01194        {
01195          /* We are producing a final executable.  */
01196          if (int_rel.r_extern)
01197            {
01198              /* This is a reloc against a symbol.  */
01199              if (h->root.type == bfd_link_hash_defined
01200                 || h->root.type == bfd_link_hash_defweak)
01201               {
01202                 asection *hsec;
01203 
01204                 hsec = h->root.u.def.section;
01205                 relocation = (h->root.u.def.value
01206                             + hsec->output_section->vma
01207                             + hsec->output_offset);
01208               }
01209              else
01210               {
01211                 if (! ((*info->callbacks->undefined_symbol)
01212                       (info, h->root.root.string, input_bfd,
01213                        input_section,
01214                        int_rel.r_vaddr - input_section->vma, TRUE)))
01215                   return FALSE;
01216                 relocation = 0;
01217               }
01218            }
01219          else
01220            {
01221              /* This is a reloc against a section.  */
01222              relocation = (s->output_section->vma
01223                          + s->output_offset
01224                          - s->vma);
01225 
01226              /* A PC relative reloc is already correct in the object
01227                file.  Make it look like a pcrel_offset relocation by
01228                adding in the start address.  */
01229              if (howto->pc_relative)
01230               relocation += int_rel.r_vaddr;
01231            }
01232 
01233          if (int_rel.r_type != MIPS_R_REFHI)
01234            r = _bfd_final_link_relocate (howto,
01235                                      input_bfd,
01236                                      input_section,
01237                                      contents,
01238                                      (int_rel.r_vaddr
01239                                       - input_section->vma),
01240                                      relocation,
01241                                      addend);
01242          else
01243            {
01244              mips_relocate_hi (&int_rel,
01245                             use_lo ? &lo_int_rel : NULL,
01246                             input_bfd, input_section, contents,
01247                             relocation);
01248              r = bfd_reloc_ok;
01249            }
01250        }
01251 
01252       /* MIPS_R_JMPADDR requires peculiar overflow detection.  The
01253         instruction provides a 28 bit address (the two lower bits are
01254         implicit zeroes) which is combined with the upper four bits
01255         of the instruction address.  */
01256       if (r == bfd_reloc_ok
01257          && int_rel.r_type == MIPS_R_JMPADDR
01258          && (((relocation
01259               + addend
01260               + (int_rel.r_extern ? 0 : s->vma))
01261               & 0xf0000000)
01262              != ((input_section->output_section->vma
01263                  + input_section->output_offset
01264                  + (int_rel.r_vaddr - input_section->vma))
01265                 & 0xf0000000)))
01266        r = bfd_reloc_overflow;
01267 
01268       if (r != bfd_reloc_ok)
01269        {
01270          switch (r)
01271            {
01272            default:
01273            case bfd_reloc_outofrange:
01274              abort ();
01275            case bfd_reloc_overflow:
01276              {
01277               const char *name;
01278 
01279               if (int_rel.r_extern)
01280                 name = NULL;
01281               else
01282                 name = bfd_section_name (input_bfd, s);
01283               if (! ((*info->callbacks->reloc_overflow)
01284                      (info, (h ? &h->root : NULL), name, howto->name,
01285                      (bfd_vma) 0, input_bfd, input_section,
01286                      int_rel.r_vaddr - input_section->vma)))
01287                 return FALSE;
01288              }
01289              break;
01290            }
01291        }
01292     }
01293 
01294   return TRUE;
01295 }
01296 
01297 /* This is the ECOFF backend structure.  The backend field of the
01298    target vector points to this.  */
01299 
01300 static const struct ecoff_backend_data mips_ecoff_backend_data =
01301 {
01302   /* COFF backend structure.  */
01303   {
01304     (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */
01305     (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
01306     (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
01307     (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/
01308     (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
01309     (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
01310     (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
01311     mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
01312     mips_ecoff_swap_scnhdr_out,
01313     FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, FALSE, 4, FALSE, 2,
01314     mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
01315     mips_ecoff_swap_scnhdr_in, NULL,
01316     mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
01317     _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
01318     _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
01319     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
01320     NULL, NULL
01321   },
01322   /* Supported architecture.  */
01323   bfd_arch_mips,
01324   /* Initial portion of armap string.  */
01325   "__________",
01326   /* The page boundary used to align sections in a demand-paged
01327      executable file.  E.g., 0x1000.  */
01328   0x1000,
01329   /* TRUE if the .rdata section is part of the text segment, as on the
01330      Alpha.  FALSE if .rdata is part of the data segment, as on the
01331      MIPS.  */
01332   FALSE,
01333   /* Bitsize of constructor entries.  */
01334   32,
01335   /* Reloc to use for constructor entries.  */
01336   &mips_howto_table[MIPS_R_REFWORD],
01337   {
01338     /* Symbol table magic number.  */
01339     magicSym,
01340     /* Alignment of debugging information.  E.g., 4.  */
01341     4,
01342     /* Sizes of external symbolic information.  */
01343     sizeof (struct hdr_ext),
01344     sizeof (struct dnr_ext),
01345     sizeof (struct pdr_ext),
01346     sizeof (struct sym_ext),
01347     sizeof (struct opt_ext),
01348     sizeof (struct fdr_ext),
01349     sizeof (struct rfd_ext),
01350     sizeof (struct ext_ext),
01351     /* Functions to swap in external symbolic data.  */
01352     ecoff_swap_hdr_in,
01353     ecoff_swap_dnr_in,
01354     ecoff_swap_pdr_in,
01355     ecoff_swap_sym_in,
01356     ecoff_swap_opt_in,
01357     ecoff_swap_fdr_in,
01358     ecoff_swap_rfd_in,
01359     ecoff_swap_ext_in,
01360     _bfd_ecoff_swap_tir_in,
01361     _bfd_ecoff_swap_rndx_in,
01362     /* Functions to swap out external symbolic data.  */
01363     ecoff_swap_hdr_out,
01364     ecoff_swap_dnr_out,
01365     ecoff_swap_pdr_out,
01366     ecoff_swap_sym_out,
01367     ecoff_swap_opt_out,
01368     ecoff_swap_fdr_out,
01369     ecoff_swap_rfd_out,
01370     ecoff_swap_ext_out,
01371     _bfd_ecoff_swap_tir_out,
01372     _bfd_ecoff_swap_rndx_out,
01373     /* Function to read in symbolic data.  */
01374     _bfd_ecoff_slurp_symbolic_info
01375   },
01376   /* External reloc size.  */
01377   RELSZ,
01378   /* Reloc swapping functions.  */
01379   mips_ecoff_swap_reloc_in,
01380   mips_ecoff_swap_reloc_out,
01381   /* Backend reloc tweaking.  */
01382   mips_adjust_reloc_in,
01383   mips_adjust_reloc_out,
01384   /* Relocate section contents while linking.  */
01385   mips_relocate_section,
01386   /* Do final adjustments to filehdr and aouthdr.  */
01387   NULL,
01388   /* Read an element from an archive at a given file position.  */
01389   _bfd_get_elt_at_filepos
01390 };
01391 
01392 /* Looking up a reloc type is MIPS specific.  */
01393 #define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
01394 #define _bfd_ecoff_bfd_reloc_name_lookup mips_bfd_reloc_name_lookup
01395 
01396 /* Getting relocated section contents is generic.  */
01397 #define _bfd_ecoff_bfd_get_relocated_section_contents \
01398   bfd_generic_get_relocated_section_contents
01399 
01400 /* Handling file windows is generic.  */
01401 #define _bfd_ecoff_get_section_contents_in_window \
01402   _bfd_generic_get_section_contents_in_window
01403 
01404 /* Relaxing sections is MIPS specific.  */
01405 #define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
01406 
01407 /* GC of sections is not done.  */
01408 #define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
01409 
01410 /* Merging of sections is not done.  */
01411 #define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
01412 
01413 #define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
01414 #define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
01415 #define _bfd_ecoff_section_already_linked \
01416   _bfd_generic_section_already_linked
01417 
01418 extern const bfd_target ecoff_big_vec;
01419 
01420 const bfd_target ecoff_little_vec =
01421 {
01422   "ecoff-littlemips",              /* name */
01423   bfd_target_ecoff_flavour,
01424   BFD_ENDIAN_LITTLE,        /* data byte order is little */
01425   BFD_ENDIAN_LITTLE,        /* header byte order is little */
01426 
01427   (HAS_RELOC | EXEC_P |            /* object flags */
01428    HAS_LINENO | HAS_DEBUG |
01429    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
01430 
01431   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
01432   0,                        /* leading underscore */
01433   ' ',                      /* ar_pad_char */
01434   15,                       /* ar_max_namelen */
01435   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
01436      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
01437      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
01438   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
01439      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
01440      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
01441 
01442   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
01443      _bfd_ecoff_archive_p, _bfd_dummy_target},
01444   {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
01445      _bfd_generic_mkarchive, bfd_false},
01446   {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
01447      _bfd_write_archive_contents, bfd_false},
01448 
01449      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
01450      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
01451      BFD_JUMP_TABLE_CORE (_bfd_nocore),
01452      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
01453      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
01454      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
01455      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
01456      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
01457      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
01458 
01459   & ecoff_big_vec,
01460 
01461   (PTR) &mips_ecoff_backend_data
01462 };
01463 
01464 const bfd_target ecoff_big_vec =
01465 {
01466   "ecoff-bigmips",          /* name */
01467   bfd_target_ecoff_flavour,
01468   BFD_ENDIAN_BIG,           /* data byte order is big */
01469   BFD_ENDIAN_BIG,           /* header byte order is big */
01470 
01471   (HAS_RELOC | EXEC_P |            /* object flags */
01472    HAS_LINENO | HAS_DEBUG |
01473    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
01474 
01475   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
01476   0,                        /* leading underscore */
01477   ' ',                      /* ar_pad_char */
01478   15,                       /* ar_max_namelen */
01479   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01480      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01481      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01482   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01483      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01484      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01485  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
01486     _bfd_ecoff_archive_p, _bfd_dummy_target},
01487  {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
01488     _bfd_generic_mkarchive, bfd_false},
01489  {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
01490     _bfd_write_archive_contents, bfd_false},
01491 
01492      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
01493      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
01494      BFD_JUMP_TABLE_CORE (_bfd_nocore),
01495      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
01496      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
01497      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
01498      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
01499      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
01500      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
01501 
01502   & ecoff_little_vec,
01503 
01504   (PTR) &mips_ecoff_backend_data
01505 };
01506 
01507 const bfd_target ecoff_biglittle_vec =
01508 {
01509   "ecoff-biglittlemips",           /* name */
01510   bfd_target_ecoff_flavour,
01511   BFD_ENDIAN_LITTLE,        /* data byte order is little */
01512   BFD_ENDIAN_BIG,           /* header byte order is big */
01513 
01514   (HAS_RELOC | EXEC_P |            /* object flags */
01515    HAS_LINENO | HAS_DEBUG |
01516    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
01517 
01518   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
01519   0,                        /* leading underscore */
01520   ' ',                      /* ar_pad_char */
01521   15,                       /* ar_max_namelen */
01522   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
01523      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
01524      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
01525   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01526      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01527      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
01528 
01529   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
01530      _bfd_ecoff_archive_p, _bfd_dummy_target},
01531   {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
01532      _bfd_generic_mkarchive, bfd_false},
01533   {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
01534      _bfd_write_archive_contents, bfd_false},
01535 
01536      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
01537      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
01538      BFD_JUMP_TABLE_CORE (_bfd_nocore),
01539      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
01540      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
01541      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
01542      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
01543      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
01544      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
01545 
01546   NULL,
01547 
01548   (PTR) &mips_ecoff_backend_data
01549 };