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