home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / binutils-2.7-src.tgz / tar.out / fsf / binutils / bfd / coff-mips.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  82KB  |  2,597 lines

  1. /* BFD back-end for MIPS Extended-Coff files.
  2.    Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
  3.    Original version by Per Bothner.
  4.    Full support added by Ian Lance Taylor, ian@cygnus.com.
  5.  
  6. This file is part of BFD, the Binary File Descriptor library.
  7.  
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12.  
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with this program; if not, write to the Free Software
  20. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  21.  
  22. #include "bfd.h"
  23. #include "sysdep.h"
  24. #include "bfdlink.h"
  25. #include "libbfd.h"
  26. #include "coff/internal.h"
  27. #include "coff/sym.h"
  28. #include "coff/symconst.h"
  29. #include "coff/ecoff.h"
  30. #include "coff/mips.h"
  31. #include "libcoff.h"
  32. #include "libecoff.h"
  33.  
  34. /* Prototypes for static functions.  */
  35.  
  36. static boolean mips_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));
  37. static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
  38.                           struct internal_reloc *));
  39. static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
  40.                            const struct internal_reloc *,
  41.                            PTR));
  42. static void mips_adjust_reloc_in PARAMS ((bfd *,
  43.                       const struct internal_reloc *,
  44.                       arelent *));
  45. static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *,
  46.                        struct internal_reloc *));
  47. static bfd_reloc_status_type mips_generic_reloc PARAMS ((bfd *abfd,
  48.                              arelent *reloc,
  49.                              asymbol *symbol,
  50.                              PTR data,
  51.                              asection *section,
  52.                              bfd *output_bfd,
  53.                              char **error));
  54. static bfd_reloc_status_type mips_refhi_reloc PARAMS ((bfd *abfd,
  55.                                arelent *reloc,
  56.                                asymbol *symbol,
  57.                                PTR data,
  58.                                asection *section,
  59.                                bfd *output_bfd,
  60.                                char **error));
  61. static bfd_reloc_status_type mips_reflo_reloc PARAMS ((bfd *abfd,
  62.                                arelent *reloc,
  63.                                asymbol *symbol,
  64.                                PTR data,
  65.                                asection *section,
  66.                                bfd *output_bfd,
  67.                                char **error));
  68. static bfd_reloc_status_type mips_gprel_reloc PARAMS ((bfd *abfd,
  69.                                arelent *reloc,
  70.                                asymbol *symbol,
  71.                                PTR data,
  72.                                asection *section,
  73.                                bfd *output_bfd,
  74.                                char **error));
  75. static bfd_reloc_status_type mips_relhi_reloc PARAMS ((bfd *abfd,
  76.                                arelent *reloc,
  77.                                asymbol *symbol,
  78.                                PTR data,
  79.                                asection *section,
  80.                                bfd *output_bfd,
  81.                                char **error));
  82. static bfd_reloc_status_type mips_rello_reloc PARAMS ((bfd *abfd,
  83.                                arelent *reloc,
  84.                                asymbol *symbol,
  85.                                PTR data,
  86.                                asection *section,
  87.                                bfd *output_bfd,
  88.                                char **error));
  89. static bfd_reloc_status_type mips_switch_reloc PARAMS ((bfd *abfd,
  90.                             arelent *reloc,
  91.                             asymbol *symbol,
  92.                             PTR data,
  93.                             asection *section,
  94.                             bfd *output_bfd,
  95.                             char **error));
  96. static void mips_relocate_hi PARAMS ((struct internal_reloc *refhi,
  97.                       struct internal_reloc *reflo,
  98.                       bfd *input_bfd,
  99.                       asection *input_section,
  100.                       bfd_byte *contents,
  101.                       size_t adjust,
  102.                       bfd_vma relocation,
  103.                       boolean pcrel));
  104. static boolean mips_relocate_section PARAMS ((bfd *, struct bfd_link_info *,
  105.                           bfd *, asection *,
  106.                           bfd_byte *, PTR));
  107. static boolean mips_read_relocs PARAMS ((bfd *, asection *));
  108. static boolean mips_relax_section PARAMS ((bfd *, asection *,
  109.                        struct bfd_link_info *,
  110.                        boolean *));
  111. static boolean mips_relax_pcrel16 PARAMS ((struct bfd_link_info *, bfd *,
  112.                        asection *,
  113.                        struct ecoff_link_hash_entry *,
  114.                        bfd_byte *, bfd_vma));
  115.  
  116. /* ECOFF has COFF sections, but the debugging information is stored in
  117.    a completely different format.  ECOFF targets use some of the
  118.    swapping routines from coffswap.h, and some of the generic COFF
  119.    routines in coffgen.c, but, unlike the real COFF targets, do not
  120.    use coffcode.h itself.
  121.  
  122.    Get the generic COFF swapping routines, except for the reloc,
  123.    symbol, and lineno ones.  Give them ECOFF names.  */
  124. #define MIPSECOFF
  125. #define NO_COFF_RELOCS
  126. #define NO_COFF_SYMBOLS
  127. #define NO_COFF_LINENOS
  128. #define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
  129. #define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
  130. #define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
  131. #define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
  132. #define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
  133. #define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
  134. #include "coffswap.h"
  135.  
  136. /* Get the ECOFF swapping routines.  */
  137. #define ECOFF_32
  138. #include "ecoffswap.h"
  139.  
  140. /* How to process the various relocs types.  */
  141.  
  142. static reloc_howto_type mips_howto_table[] =
  143. {
  144.   /* Reloc type 0 is ignored.  The reloc reading code ensures that
  145.      this is a reference to the .abs section, which will cause
  146.      bfd_perform_relocation to do nothing.  */
  147.   HOWTO (MIPS_R_IGNORE,    /* type */
  148.      0,            /* rightshift */
  149.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  150.      8,            /* bitsize */
  151.      false,            /* pc_relative */
  152.      0,            /* bitpos */
  153.      complain_overflow_dont, /* complain_on_overflow */
  154.      0,            /* special_function */
  155.      "IGNORE",        /* name */
  156.      false,            /* partial_inplace */
  157.      0,            /* src_mask */
  158.      0,            /* dst_mask */
  159.      false),        /* pcrel_offset */
  160.  
  161.   /* A 16 bit reference to a symbol, normally from a data section.  */
  162.   HOWTO (MIPS_R_REFHALF,    /* type */
  163.      0,            /* rightshift */
  164.      1,            /* size (0 = byte, 1 = short, 2 = long) */
  165.      16,            /* bitsize */
  166.      false,            /* pc_relative */
  167.      0,            /* bitpos */
  168.      complain_overflow_bitfield, /* complain_on_overflow */
  169.      mips_generic_reloc,    /* special_function */
  170.      "REFHALF",        /* name */
  171.      true,            /* partial_inplace */
  172.      0xffff,        /* src_mask */
  173.      0xffff,        /* dst_mask */
  174.      false),        /* pcrel_offset */
  175.  
  176.   /* A 32 bit reference to a symbol, normally from a data section.  */
  177.   HOWTO (MIPS_R_REFWORD,    /* type */
  178.      0,            /* rightshift */
  179.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  180.      32,            /* bitsize */
  181.      false,            /* pc_relative */
  182.      0,            /* bitpos */
  183.      complain_overflow_bitfield, /* complain_on_overflow */
  184.      mips_generic_reloc,    /* special_function */
  185.      "REFWORD",        /* name */
  186.      true,            /* partial_inplace */
  187.      0xffffffff,        /* src_mask */
  188.      0xffffffff,        /* dst_mask */
  189.      false),        /* pcrel_offset */
  190.  
  191.   /* A 26 bit absolute jump address.  */
  192.   HOWTO (MIPS_R_JMPADDR,    /* type */
  193.      2,            /* rightshift */
  194.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  195.      26,            /* bitsize */
  196.      false,            /* pc_relative */
  197.      0,            /* bitpos */
  198.      complain_overflow_dont, /* complain_on_overflow */
  199.                  /* This needs complex overflow
  200.                    detection, because the upper four
  201.                    bits must match the PC.  */
  202.      mips_generic_reloc,    /* special_function */
  203.      "JMPADDR",        /* name */
  204.      true,            /* partial_inplace */
  205.      0x3ffffff,        /* src_mask */
  206.      0x3ffffff,        /* dst_mask */
  207.      false),        /* pcrel_offset */
  208.  
  209.   /* The high 16 bits of a symbol value.  Handled by the function
  210.      mips_refhi_reloc.  */
  211.   HOWTO (MIPS_R_REFHI,        /* type */
  212.      16,            /* rightshift */
  213.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  214.      16,            /* bitsize */
  215.      false,            /* pc_relative */
  216.      0,            /* bitpos */
  217.      complain_overflow_bitfield, /* complain_on_overflow */
  218.      mips_refhi_reloc,    /* special_function */
  219.      "REFHI",        /* name */
  220.      true,            /* partial_inplace */
  221.      0xffff,        /* src_mask */
  222.      0xffff,        /* dst_mask */
  223.      false),        /* pcrel_offset */
  224.  
  225.   /* The low 16 bits of a symbol value.  */
  226.   HOWTO (MIPS_R_REFLO,        /* type */
  227.      0,            /* rightshift */
  228.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  229.      16,            /* bitsize */
  230.      false,            /* pc_relative */
  231.      0,            /* bitpos */
  232.      complain_overflow_dont, /* complain_on_overflow */
  233.      mips_reflo_reloc,    /* special_function */
  234.      "REFLO",        /* name */
  235.      true,            /* partial_inplace */
  236.      0xffff,        /* src_mask */
  237.      0xffff,        /* dst_mask */
  238.      false),        /* pcrel_offset */
  239.  
  240.   /* A reference to an offset from the gp register.  Handled by the
  241.      function mips_gprel_reloc.  */
  242.   HOWTO (MIPS_R_GPREL,        /* type */
  243.      0,            /* rightshift */
  244.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  245.      16,            /* bitsize */
  246.      false,            /* pc_relative */
  247.      0,            /* bitpos */
  248.      complain_overflow_signed, /* complain_on_overflow */
  249.      mips_gprel_reloc,    /* special_function */
  250.      "GPREL",        /* name */
  251.      true,            /* partial_inplace */
  252.      0xffff,        /* src_mask */
  253.      0xffff,        /* dst_mask */
  254.      false),        /* pcrel_offset */
  255.  
  256.   /* A reference to a literal using an offset from the gp register.
  257.      Handled by the function mips_gprel_reloc.  */
  258.   HOWTO (MIPS_R_LITERAL,    /* type */
  259.      0,            /* rightshift */
  260.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  261.      16,            /* bitsize */
  262.      false,            /* pc_relative */
  263.      0,            /* bitpos */
  264.      complain_overflow_signed, /* complain_on_overflow */
  265.      mips_gprel_reloc,    /* special_function */
  266.      "LITERAL",        /* name */
  267.      true,            /* partial_inplace */
  268.      0xffff,        /* src_mask */
  269.      0xffff,        /* dst_mask */
  270.      false),        /* pcrel_offset */
  271.  
  272.   { 8 },
  273.   { 9 },
  274.   { 10 },
  275.   { 11 },
  276.  
  277.   /* This reloc is a Cygnus extension used when generating position
  278.      independent code for embedded systems.  It represents a 16 bit PC
  279.      relative reloc rightshifted twice as used in the MIPS branch
  280.      instructions.  */
  281.   HOWTO (MIPS_R_PCREL16,    /* type */
  282.      2,            /* rightshift */
  283.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  284.      16,            /* bitsize */
  285.      true,            /* pc_relative */
  286.      0,            /* bitpos */
  287.      complain_overflow_signed, /* complain_on_overflow */
  288.      mips_generic_reloc,    /* special_function */
  289.      "PCREL16",        /* name */
  290.      true,            /* partial_inplace */
  291.      0xffff,        /* src_mask */
  292.      0xffff,        /* dst_mask */
  293.      true),            /* pcrel_offset */
  294.  
  295.   /* This reloc is a Cygnus extension used when generating position
  296.      independent code for embedded systems.  It represents the high 16
  297.      bits of a PC relative reloc.  The next reloc must be
  298.      MIPS_R_RELLO, and the addend is formed from the addends of the
  299.      two instructions, just as in MIPS_R_REFHI and MIPS_R_REFLO.  The
  300.      final value is actually PC relative to the location of the
  301.      MIPS_R_RELLO reloc, not the MIPS_R_RELHI reloc.  */
  302.   HOWTO (MIPS_R_RELHI,        /* type */
  303.      16,            /* rightshift */
  304.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  305.      16,            /* bitsize */
  306.      true,            /* pc_relative */
  307.      0,            /* bitpos */
  308.      complain_overflow_bitfield, /* complain_on_overflow */
  309.      mips_relhi_reloc,    /* special_function */
  310.      "RELHI",        /* name */
  311.      true,            /* partial_inplace */
  312.      0xffff,        /* src_mask */
  313.      0xffff,        /* dst_mask */
  314.      true),            /* pcrel_offset */
  315.  
  316.   /* This reloc is a Cygnus extension used when generating position
  317.      independent code for embedded systems.  It represents the low 16
  318.      bits of a PC relative reloc.  */
  319.   HOWTO (MIPS_R_RELLO,        /* type */
  320.      0,            /* rightshift */
  321.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  322.      16,            /* bitsize */
  323.      true,            /* pc_relative */
  324.      0,            /* bitpos */
  325.      complain_overflow_dont, /* complain_on_overflow */
  326.      mips_rello_reloc,    /* special_function */
  327.      "RELLO",        /* name */
  328.      true,            /* partial_inplace */
  329.      0xffff,        /* src_mask */
  330.      0xffff,        /* dst_mask */
  331.      true),            /* pcrel_offset */
  332.  
  333.   { 15 },
  334.   { 16 },
  335.   { 17 },
  336.   { 18 },
  337.   { 19 },
  338.   { 20 },
  339.   { 21 },
  340.  
  341.   /* This reloc is a Cygnus extension used when generating position
  342.      independent code for embedded systems.  It represents an entry in
  343.      a switch table, which is the difference between two symbols in
  344.      the .text section.  The symndx is actually the offset from the
  345.      reloc address to the subtrahend.  See include/coff/mips.h for
  346.      more details.  */
  347.   HOWTO (MIPS_R_SWITCH,        /* type */
  348.      0,            /* rightshift */
  349.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  350.      32,            /* bitsize */
  351.      true,            /* pc_relative */
  352.      0,            /* bitpos */
  353.      complain_overflow_dont, /* complain_on_overflow */
  354.      mips_switch_reloc,    /* special_function */
  355.      "SWITCH",        /* name */
  356.      true,            /* partial_inplace */
  357.      0xffffffff,        /* src_mask */
  358.      0xffffffff,        /* dst_mask */
  359.      true)            /* pcrel_offset */
  360. };
  361.  
  362. #define MIPS_HOWTO_COUNT \
  363.   (sizeof mips_howto_table / sizeof mips_howto_table[0])
  364.  
  365. /* When the linker is doing relaxing, it may change a external PCREL16
  366.    reloc.  This typically represents an instruction like
  367.        bal foo
  368.    We change it to
  369.        .set  noreorder
  370.        bal   $L1
  371.        lui   $at,%hi(foo - $L1)
  372.      $L1:
  373.        addiu $at,%lo(foo - $L1)
  374.        addu  $at,$at,$31
  375.        jalr  $at
  376.    PCREL16_EXPANSION_ADJUSTMENT is the number of bytes this changes the
  377.    instruction by.  */
  378.  
  379. #define PCREL16_EXPANSION_ADJUSTMENT (4 * 4)
  380.  
  381. /* See whether the magic number matches.  */
  382.  
  383. static boolean
  384. mips_ecoff_bad_format_hook (abfd, filehdr)
  385.      bfd *abfd;
  386.      PTR filehdr;
  387. {
  388.   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
  389.  
  390.   switch (internal_f->f_magic)
  391.     {
  392.     case MIPS_MAGIC_1:
  393.       /* I don't know what endianness this implies.  */
  394.       return true;
  395.  
  396.     case MIPS_MAGIC_BIG:
  397.     case MIPS_MAGIC_BIG2:
  398.     case MIPS_MAGIC_BIG3:
  399.       return bfd_big_endian (abfd);
  400.  
  401.     case MIPS_MAGIC_LITTLE:
  402.     case MIPS_MAGIC_LITTLE2:
  403.     case MIPS_MAGIC_LITTLE3:
  404.       return bfd_little_endian (abfd);
  405.  
  406.     default:
  407.       return false;
  408.     }
  409. }
  410.  
  411. /* Reloc handling.  MIPS ECOFF relocs are packed into 8 bytes in
  412.    external form.  They use a bit which indicates whether the symbol
  413.    is external.  */
  414.  
  415. /* Swap a reloc in.  */
  416.  
  417. static void
  418. mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
  419.      bfd *abfd;
  420.      PTR ext_ptr;
  421.      struct internal_reloc *intern;
  422. {
  423.   const RELOC *ext = (RELOC *) ext_ptr;
  424.  
  425.   intern->r_vaddr = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_vaddr);
  426.   if (bfd_header_big_endian (abfd))
  427.     {
  428.       intern->r_symndx = (((int) ext->r_bits[0]
  429.                << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
  430.               | ((int) ext->r_bits[1]
  431.                  << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
  432.               | ((int) ext->r_bits[2]
  433.                  << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
  434.       intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
  435.             >> RELOC_BITS3_TYPE_SH_BIG);
  436.       intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
  437.     }
  438.   else
  439.     {
  440.       intern->r_symndx = (((int) ext->r_bits[0]
  441.                << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
  442.               | ((int) ext->r_bits[1]
  443.                  << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
  444.               | ((int) ext->r_bits[2]
  445.                  << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
  446.       intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
  447.              >> RELOC_BITS3_TYPE_SH_LITTLE)
  448.             | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
  449.                << RELOC_BITS3_TYPEHI_SH_LITTLE));
  450.       intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
  451.     }
  452.  
  453.   /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
  454.      MIPS_R_RELLO reloc, r_symndx is actually the offset from the
  455.      reloc address to the base of the difference (see
  456.      include/coff/mips.h for more details).  We copy symndx into the
  457.      r_offset field so as not to confuse ecoff_slurp_reloc_table in
  458.      ecoff.c.  In adjust_reloc_in we then copy r_offset into the reloc
  459.      addend.  */
  460.   if (intern->r_type == MIPS_R_SWITCH
  461.       || (! intern->r_extern
  462.       && (intern->r_type == MIPS_R_RELLO
  463.           || intern->r_type == MIPS_R_RELHI)))
  464.     {
  465.       BFD_ASSERT (! intern->r_extern);
  466.       intern->r_offset = intern->r_symndx;
  467.       if (intern->r_offset & 0x800000)
  468.     intern->r_offset -= 0x1000000;
  469.       intern->r_symndx = RELOC_SECTION_TEXT;
  470.     }
  471. }
  472.  
  473. /* Swap a reloc out.  */
  474.  
  475. static void
  476. mips_ecoff_swap_reloc_out (abfd, intern, dst)
  477.      bfd *abfd;
  478.      const struct internal_reloc *intern;
  479.      PTR dst;
  480. {
  481.   RELOC *ext = (RELOC *) dst;
  482.   long r_symndx;
  483.  
  484.   BFD_ASSERT (intern->r_extern
  485.           || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
  486.  
  487.   /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELLO or
  488.      MIPS_R_RELHI reloc, we actually want to write the contents of
  489.      r_offset out as the symbol index.  This undoes the change made by
  490.      mips_ecoff_swap_reloc_in.  */
  491.   if (intern->r_type != MIPS_R_SWITCH
  492.       && (intern->r_extern
  493.       || (intern->r_type != MIPS_R_RELHI
  494.           && intern->r_type != MIPS_R_RELLO)))
  495.     r_symndx = intern->r_symndx;
  496.   else
  497.     {
  498.       BFD_ASSERT (intern->r_symndx == RELOC_SECTION_TEXT);
  499.       r_symndx = intern->r_offset & 0xffffff;
  500.     }
  501.  
  502.   bfd_h_put_32 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr);
  503.   if (bfd_header_big_endian (abfd))
  504.     {
  505.       ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
  506.       ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
  507.       ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
  508.       ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
  509.              & RELOC_BITS3_TYPE_BIG)
  510.             | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
  511.     }
  512.   else
  513.     {
  514.       ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
  515.       ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
  516.       ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
  517.       ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
  518.              & RELOC_BITS3_TYPE_LITTLE)
  519.             | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
  520.                 & RELOC_BITS3_TYPEHI_LITTLE))
  521.             | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
  522.     }
  523. }
  524.  
  525. /* Finish canonicalizing a reloc.  Part of this is generic to all
  526.    ECOFF targets, and that part is in ecoff.c.  The rest is done in
  527.    this backend routine.  It must fill in the howto field.  */
  528.  
  529. static void
  530. mips_adjust_reloc_in (abfd, intern, rptr)
  531.      bfd *abfd;
  532.      const struct internal_reloc *intern;
  533.      arelent *rptr;
  534. {
  535.   if (intern->r_type > MIPS_R_SWITCH)
  536.     abort ();
  537.  
  538.   if (! intern->r_extern
  539.       && (intern->r_type == MIPS_R_GPREL
  540.       || intern->r_type == MIPS_R_LITERAL))
  541.     rptr->addend += ecoff_data (abfd)->gp;
  542.  
  543.   /* If the type is MIPS_R_IGNORE, make sure this is a reference to
  544.      the absolute section so that the reloc is ignored.  */
  545.   if (intern->r_type == MIPS_R_IGNORE)
  546.     rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
  547.  
  548.   /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
  549.      MIPS_R_RELLO reloc, we want the addend field of the BFD relocto
  550.      hold the value which was originally in the symndx field of the
  551.      internal MIPS ECOFF reloc.  This value was copied into
  552.      intern->r_offset by mips_swap_reloc_in, and here we copy it into
  553.      the addend field.  */
  554.   if (intern->r_type == MIPS_R_SWITCH
  555.       || (! intern->r_extern
  556.       && (intern->r_type == MIPS_R_RELHI
  557.           || intern->r_type == MIPS_R_RELLO)))
  558.     rptr->addend = intern->r_offset;
  559.  
  560.   rptr->howto = &mips_howto_table[intern->r_type];
  561. }
  562.  
  563. /* Make any adjustments needed to a reloc before writing it out.  None
  564.    are needed for MIPS.  */
  565.  
  566. static void
  567. mips_adjust_reloc_out (abfd, rel, intern)
  568.      bfd *abfd;
  569.      const arelent *rel;
  570.      struct internal_reloc *intern;
  571. {
  572.   /* For a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
  573.      MIPS_R_RELLO reloc, we must copy rel->addend into
  574.      intern->r_offset.  This will then be written out as the symbol
  575.      index by mips_ecoff_swap_reloc_out.  This operation parallels the
  576.      action of mips_adjust_reloc_in.  */
  577.   if (intern->r_type == MIPS_R_SWITCH
  578.       || (! intern->r_extern
  579.       && (intern->r_type == MIPS_R_RELHI
  580.           || intern->r_type == MIPS_R_RELLO)))
  581.     intern->r_offset = rel->addend;
  582. }
  583.  
  584. /* ECOFF relocs are either against external symbols, or against
  585.    sections.  If we are producing relocateable output, and the reloc
  586.    is against an external symbol, and nothing has given us any
  587.    additional addend, the resulting reloc will also be against the
  588.    same symbol.  In such a case, we don't want to change anything
  589.    about the way the reloc is handled, since it will all be done at
  590.    final link time.  Rather than put special case code into
  591.    bfd_perform_relocation, all the reloc types use this howto
  592.    function.  It just short circuits the reloc if producing
  593.    relocateable output against an external symbol.  */
  594.  
  595. static bfd_reloc_status_type
  596. mips_generic_reloc (abfd,
  597.             reloc_entry,
  598.             symbol,
  599.             data,
  600.             input_section,
  601.             output_bfd,
  602.             error_message)
  603.      bfd *abfd;
  604.      arelent *reloc_entry;
  605.      asymbol *symbol;
  606.      PTR data;
  607.      asection *input_section;
  608.      bfd *output_bfd;
  609.      char **error_message;
  610. {
  611.   if (output_bfd != (bfd *) NULL
  612.       && (symbol->flags & BSF_SECTION_SYM) == 0
  613.       && reloc_entry->addend == 0)
  614.     {
  615.       reloc_entry->address += input_section->output_offset;
  616.       return bfd_reloc_ok;
  617.     }
  618.  
  619.   return bfd_reloc_continue;
  620. }
  621.  
  622. /* Do a REFHI relocation.  This has to be done in combination with a
  623.    REFLO reloc, because there is a carry from the REFLO to the REFHI.
  624.    Here we just save the information we need; we do the actual
  625.    relocation when we see the REFLO.  MIPS ECOFF requires that the
  626.    REFLO immediately follow the REFHI, so this ought to work.  */
  627.  
  628. static bfd_byte *mips_refhi_addr;
  629. static bfd_vma mips_refhi_addend;
  630.  
  631. static bfd_reloc_status_type
  632. mips_refhi_reloc (abfd,
  633.           reloc_entry,
  634.           symbol,
  635.           data,
  636.           input_section,
  637.           output_bfd,
  638.           error_message)
  639.      bfd *abfd;
  640.      arelent *reloc_entry;
  641.      asymbol *symbol;
  642.      PTR data;
  643.      asection *input_section;
  644.      bfd *output_bfd;
  645.      char **error_message;
  646. {
  647.   bfd_reloc_status_type ret;
  648.   bfd_vma relocation;
  649.  
  650.   /* If we're relocating, and this an external symbol, we don't want
  651.      to change anything.  */
  652.   if (output_bfd != (bfd *) NULL
  653.       && (symbol->flags & BSF_SECTION_SYM) == 0
  654.       && reloc_entry->addend == 0)
  655.     {
  656.       reloc_entry->address += input_section->output_offset;
  657.       return bfd_reloc_ok;
  658.     }
  659.  
  660.   ret = bfd_reloc_ok;
  661.   if (bfd_is_und_section (symbol->section)
  662.       && output_bfd == (bfd *) NULL)
  663.     ret = bfd_reloc_undefined;
  664.  
  665.   if (bfd_is_com_section (symbol->section))
  666.     relocation = 0;
  667.   else
  668.     relocation = symbol->value;
  669.  
  670.   relocation += symbol->section->output_section->vma;
  671.   relocation += symbol->section->output_offset;
  672.   relocation += reloc_entry->addend;
  673.  
  674.   if (reloc_entry->address > input_section->_cooked_size)
  675.     return bfd_reloc_outofrange;
  676.  
  677.   /* Save the information, and let REFLO do the actual relocation.  */
  678.   mips_refhi_addr = (bfd_byte *) data + reloc_entry->address;
  679.   mips_refhi_addend = relocation;
  680.  
  681.   if (output_bfd != (bfd *) NULL)
  682.     reloc_entry->address += input_section->output_offset;
  683.  
  684.   return ret;
  685. }
  686.  
  687. /* Do a REFLO relocation.  This is a straightforward 16 bit inplace
  688.    relocation; this function exists in order to do the REFHI
  689.    relocation described above.  */
  690.  
  691. static bfd_reloc_status_type
  692. mips_reflo_reloc (abfd,
  693.           reloc_entry,
  694.           symbol,
  695.           data,
  696.           input_section,
  697.           output_bfd,
  698.           error_message)
  699.      bfd *abfd;
  700.      arelent *reloc_entry;
  701.      asymbol *symbol;
  702.      PTR data;
  703.      asection *input_section;
  704.      bfd *output_bfd;
  705.      char **error_message;
  706. {
  707.   if (mips_refhi_addr != (bfd_byte *) NULL)
  708.     {
  709.       unsigned long insn;
  710.       unsigned long val;
  711.       unsigned long vallo;
  712.  
  713.       /* Do the REFHI relocation.  Note that we actually don't need to
  714.      know anything about the REFLO itself, except where to find
  715.      the low 16 bits of the addend needed by the REFHI.  */
  716.       insn = bfd_get_32 (abfd, mips_refhi_addr);
  717.       vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
  718.            & 0xffff);
  719.       val = ((insn & 0xffff) << 16) + vallo;
  720.       val += mips_refhi_addend;
  721.  
  722.       /* The low order 16 bits are always treated as a signed value.
  723.      Therefore, a negative value in the low order bits requires an
  724.      adjustment in the high order bits.  We need to make this
  725.      adjustment in two ways: once for the bits we took from the
  726.      data, and once for the bits we are putting back in to the
  727.      data.  */
  728.       if ((vallo & 0x8000) != 0)
  729.     val -= 0x10000;
  730.       if ((val & 0x8000) != 0)
  731.     val += 0x10000;
  732.  
  733.       insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
  734.       bfd_put_32 (abfd, insn, mips_refhi_addr);
  735.  
  736.       mips_refhi_addr = (bfd_byte *) NULL;
  737.     }
  738.  
  739.   /* Now do the REFLO reloc in the usual way.  */
  740.   return mips_generic_reloc (abfd, reloc_entry, symbol, data,
  741.                   input_section, output_bfd, error_message);
  742. }
  743.  
  744. /* Do a GPREL relocation.  This is a 16 bit value which must become
  745.    the offset from the gp register.  */
  746.  
  747. static bfd_reloc_status_type
  748. mips_gprel_reloc (abfd,
  749.           reloc_entry,
  750.           symbol,
  751.           data,
  752.           input_section,
  753.           output_bfd,
  754.           error_message)
  755.      bfd *abfd;
  756.      arelent *reloc_entry;
  757.      asymbol *symbol;
  758.      PTR data;
  759.      asection *input_section;
  760.      bfd *output_bfd;
  761.      char **error_message;
  762. {
  763.   boolean relocateable;
  764.   bfd_vma gp;
  765.   bfd_vma relocation;
  766.   unsigned long val;
  767.   unsigned long insn;
  768.  
  769.   /* If we're relocating, and this is an external symbol with no
  770.      addend, we don't want to change anything.  We will only have an
  771.      addend if this is a newly created reloc, not read from an ECOFF
  772.      file.  */
  773.   if (output_bfd != (bfd *) NULL
  774.       && (symbol->flags & BSF_SECTION_SYM) == 0
  775.       && reloc_entry->addend == 0)
  776.     {
  777.       reloc_entry->address += input_section->output_offset;
  778.       return bfd_reloc_ok;
  779.     }
  780.  
  781.   if (output_bfd != (bfd *) NULL)
  782.     relocateable = true;
  783.   else
  784.     {
  785.       relocateable = false;
  786.       output_bfd = symbol->section->output_section->owner;
  787.     }
  788.  
  789.   if (bfd_is_und_section (symbol->section)
  790.       && relocateable == false)
  791.     return bfd_reloc_undefined;
  792.  
  793.   /* We have to figure out the gp value, so that we can adjust the
  794.      symbol value correctly.  We look up the symbol _gp in the output
  795.      BFD.  If we can't find it, we're stuck.  We cache it in the ECOFF
  796.      target data.  We don't need to adjust the symbol value for an
  797.      external symbol if we are producing relocateable output.  */
  798.   gp = _bfd_get_gp_value (output_bfd);
  799.   if (gp == 0
  800.       && (relocateable == false
  801.       || (symbol->flags & BSF_SECTION_SYM) != 0))
  802.     {
  803.       if (relocateable != false)
  804.     {
  805.       /* Make up a value.  */
  806.       gp = symbol->section->output_section->vma + 0x4000;
  807.       _bfd_set_gp_value (output_bfd, gp);
  808.     }
  809.       else
  810.     {
  811.       unsigned int count;
  812.       asymbol **sym;
  813.       unsigned int i;
  814.  
  815.       count = bfd_get_symcount (output_bfd);
  816.       sym = bfd_get_outsymbols (output_bfd);
  817.  
  818.       if (sym == (asymbol **) NULL)
  819.         i = count;
  820.       else
  821.         {
  822.           for (i = 0; i < count; i++, sym++)
  823.         {
  824.           register CONST char *name;
  825.  
  826.           name = bfd_asymbol_name (*sym);
  827.           if (*name == '_' && strcmp (name, "_gp") == 0)
  828.             {
  829.               gp = bfd_asymbol_value (*sym);
  830.               _bfd_set_gp_value (output_bfd, gp);
  831.               break;
  832.             }
  833.         }
  834.         }
  835.  
  836.       if (i >= count)
  837.         {
  838.           /* Only get the error once.  */
  839.           gp = 4;
  840.           _bfd_set_gp_value (output_bfd, gp);
  841.           *error_message =
  842.         (char *) "GP relative relocation when _gp not defined";
  843.           return bfd_reloc_dangerous;
  844.         }
  845.     }
  846.     }
  847.  
  848.   if (bfd_is_com_section (symbol->section))
  849.     relocation = 0;
  850.   else
  851.     relocation = symbol->value;
  852.  
  853.   relocation += symbol->section->output_section->vma;
  854.   relocation += symbol->section->output_offset;
  855.  
  856.   if (reloc_entry->address > input_section->_cooked_size)
  857.     return bfd_reloc_outofrange;
  858.  
  859.   insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
  860.  
  861.   /* Set val to the offset into the section or symbol.  */
  862.   val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
  863.   if (val & 0x8000)
  864.     val -= 0x10000;
  865.  
  866.   /* Adjust val for the final section location and GP value.  If we
  867.      are producing relocateable output, we don't want to do this for
  868.      an external symbol.  */
  869.   if (relocateable == false
  870.       || (symbol->flags & BSF_SECTION_SYM) != 0)
  871.     val += relocation - gp;
  872.  
  873.   insn = (insn &~ 0xffff) | (val & 0xffff);
  874.   bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
  875.  
  876.   if (relocateable != false)
  877.     reloc_entry->address += input_section->output_offset;
  878.  
  879.   /* Make sure it fit in 16 bits.  */
  880.   if (val >= 0x8000 && val < 0xffff8000)
  881.     return bfd_reloc_overflow;
  882.  
  883.   return bfd_reloc_ok;
  884. }
  885.  
  886. /* Do a RELHI relocation.  We do this in conjunction with a RELLO
  887.    reloc, just as REFHI and REFLO are done together.  RELHI and RELLO
  888.    are Cygnus extensions used when generating position independent
  889.    code for embedded systems.  */
  890.  
  891. static bfd_byte *mips_relhi_addr;
  892. static bfd_vma mips_relhi_addend;
  893.  
  894. static bfd_reloc_status_type
  895. mips_relhi_reloc (abfd,
  896.           reloc_entry,
  897.           symbol,
  898.           data,
  899.           input_section,
  900.           output_bfd,
  901.           error_message)
  902.      bfd *abfd;
  903.      arelent *reloc_entry;
  904.      asymbol *symbol;
  905.      PTR data;
  906.      asection *input_section;
  907.      bfd *output_bfd;
  908.      char **error_message;
  909. {
  910.   bfd_reloc_status_type ret;
  911.   bfd_vma relocation;
  912.  
  913.   /* If this is a reloc against a section symbol, then it is correct
  914.      in the object file.  The only time we want to change this case is
  915.      when we are relaxing, and that is handled entirely by
  916.      mips_relocate_section and never calls this function.  */
  917.   if ((symbol->flags & BSF_SECTION_SYM) != 0)
  918.     {
  919.       if (output_bfd != (bfd *) NULL)
  920.     reloc_entry->address += input_section->output_offset;
  921.       return bfd_reloc_ok;
  922.     }
  923.  
  924.   /* This is an external symbol.  If we're relocating, we don't want
  925.      to change anything.  */
  926.   if (output_bfd != (bfd *) NULL)
  927.     {
  928.       reloc_entry->address += input_section->output_offset;
  929.       return bfd_reloc_ok;
  930.     }
  931.  
  932.   ret = bfd_reloc_ok;
  933.   if (bfd_is_und_section (symbol->section)
  934.       && output_bfd == (bfd *) NULL)
  935.     ret = bfd_reloc_undefined;
  936.  
  937.   if (bfd_is_com_section (symbol->section))
  938.     relocation = 0;
  939.   else
  940.     relocation = symbol->value;
  941.  
  942.   relocation += symbol->section->output_section->vma;
  943.   relocation += symbol->section->output_offset;
  944.   relocation += reloc_entry->addend;
  945.  
  946.   if (reloc_entry->address > input_section->_cooked_size)
  947.     return bfd_reloc_outofrange;
  948.  
  949.   /* Save the information, and let RELLO do the actual relocation.  */
  950.   mips_relhi_addr = (bfd_byte *) data + reloc_entry->address;
  951.   mips_relhi_addend = relocation;
  952.  
  953.   if (output_bfd != (bfd *) NULL)
  954.     reloc_entry->address += input_section->output_offset;
  955.  
  956.   return ret;
  957. }
  958.  
  959. /* Do a RELLO relocation.  This is a straightforward 16 bit PC
  960.    relative relocation; this function exists in order to do the RELHI
  961.    relocation described above.  */
  962.  
  963. static bfd_reloc_status_type
  964. mips_rello_reloc (abfd,
  965.           reloc_entry,
  966.           symbol,
  967.           data,
  968.           input_section,
  969.           output_bfd,
  970.           error_message)
  971.      bfd *abfd;
  972.      arelent *reloc_entry;
  973.      asymbol *symbol;
  974.      PTR data;
  975.      asection *input_section;
  976.      bfd *output_bfd;
  977.      char **error_message;
  978. {
  979.   if (mips_relhi_addr != (bfd_byte *) NULL)
  980.     {
  981.       unsigned long insn;
  982.       unsigned long val;
  983.       unsigned long vallo;
  984.  
  985.       /* Do the RELHI relocation.  Note that we actually don't need to
  986.      know anything about the RELLO itself, except where to find
  987.      the low 16 bits of the addend needed by the RELHI.  */
  988.       insn = bfd_get_32 (abfd, mips_relhi_addr);
  989.       vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
  990.            & 0xffff);
  991.       val = ((insn & 0xffff) << 16) + vallo;
  992.       val += mips_relhi_addend;
  993.  
  994.       /* If the symbol is defined, make val PC relative.  If the
  995.      symbol is not defined we don't want to do this, because we
  996.      don't want the value in the object file to incorporate the
  997.      address of the reloc.  */
  998.       if (! bfd_is_und_section (bfd_get_section (symbol))
  999.       && ! bfd_is_com_section (bfd_get_section (symbol)))
  1000.     val -= (input_section->output_section->vma
  1001.         + input_section->output_offset
  1002.         + reloc_entry->address);
  1003.  
  1004.       /* The low order 16 bits are always treated as a signed value.
  1005.      Therefore, a negative value in the low order bits requires an
  1006.      adjustment in the high order bits.  We need to make this
  1007.      adjustment in two ways: once for the bits we took from the
  1008.      data, and once for the bits we are putting back in to the
  1009.      data.  */
  1010.       if ((vallo & 0x8000) != 0)
  1011.     val -= 0x10000;
  1012.       if ((val & 0x8000) != 0)
  1013.     val += 0x10000;
  1014.  
  1015.       insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
  1016.       bfd_put_32 (abfd, insn, mips_relhi_addr);
  1017.  
  1018.       mips_relhi_addr = (bfd_byte *) NULL;
  1019.     }
  1020.  
  1021.   /* If this is a reloc against a section symbol, then it is correct
  1022.      in the object file.  The only time we want to change this case is
  1023.      when we are relaxing, and that is handled entirely by
  1024.      mips_relocate_section and never calls this function.  */
  1025.   if ((symbol->flags & BSF_SECTION_SYM) != 0)
  1026.     {
  1027.       if (output_bfd != (bfd *) NULL)
  1028.     reloc_entry->address += input_section->output_offset;
  1029.       return bfd_reloc_ok;
  1030.     }
  1031.  
  1032.   /* bfd_perform_relocation does not handle pcrel_offset relocations
  1033.      correctly when generating a relocateable file, so handle them
  1034.      directly here.  */
  1035.   if (output_bfd != (bfd *) NULL)
  1036.     {
  1037.       reloc_entry->address += input_section->output_offset;
  1038.       return bfd_reloc_ok;
  1039.     }
  1040.  
  1041.   /* Now do the RELLO reloc in the usual way.  */
  1042.   return mips_generic_reloc (abfd, reloc_entry, symbol, data,
  1043.                   input_section, output_bfd, error_message);
  1044. }
  1045.  
  1046. /* This is the special function for the MIPS_R_SWITCH reloc.  This
  1047.    special reloc is normally correct in the object file, and only
  1048.    requires special handling when relaxing.  We don't want
  1049.    bfd_perform_relocation to tamper with it at all.  */
  1050.  
  1051. /*ARGSUSED*/
  1052. static bfd_reloc_status_type
  1053. mips_switch_reloc (abfd,
  1054.            reloc_entry,
  1055.            symbol,
  1056.            data,
  1057.            input_section,
  1058.            output_bfd,
  1059.            error_message)
  1060.      bfd *abfd;
  1061.      arelent *reloc_entry;
  1062.      asymbol *symbol;
  1063.      PTR data;
  1064.      asection *input_section;
  1065.      bfd *output_bfd;
  1066.      char **error_message;
  1067. {
  1068.   return bfd_reloc_ok;
  1069. }
  1070.  
  1071. /* Get the howto structure for a generic reloc type.  */
  1072.  
  1073. static reloc_howto_type *
  1074. mips_bfd_reloc_type_lookup (abfd, code)
  1075.      bfd *abfd;
  1076.      bfd_reloc_code_real_type code;
  1077. {
  1078.   int mips_type;
  1079.  
  1080.   switch (code)
  1081.     {
  1082.     case BFD_RELOC_16:
  1083.       mips_type = MIPS_R_REFHALF;
  1084.       break;
  1085.     case BFD_RELOC_32:
  1086.     case BFD_RELOC_CTOR:
  1087.       mips_type = MIPS_R_REFWORD;
  1088.       break;
  1089.     case BFD_RELOC_MIPS_JMP:
  1090.       mips_type = MIPS_R_JMPADDR;
  1091.       break;
  1092.     case BFD_RELOC_HI16_S:
  1093.       mips_type = MIPS_R_REFHI;
  1094.       break;
  1095.     case BFD_RELOC_LO16:
  1096.       mips_type = MIPS_R_REFLO;
  1097.       break;
  1098.     case BFD_RELOC_MIPS_GPREL:
  1099.       mips_type = MIPS_R_GPREL;
  1100.       break;
  1101.     case BFD_RELOC_MIPS_LITERAL:
  1102.       mips_type = MIPS_R_LITERAL;
  1103.       break;
  1104.     case BFD_RELOC_16_PCREL_S2:
  1105.       mips_type = MIPS_R_PCREL16;
  1106.       break;
  1107.     case BFD_RELOC_PCREL_HI16_S:
  1108.       mips_type = MIPS_R_RELHI;
  1109.       break;
  1110.     case BFD_RELOC_PCREL_LO16:
  1111.       mips_type = MIPS_R_RELLO;
  1112.       break;
  1113.     case BFD_RELOC_GPREL32:
  1114.       mips_type = MIPS_R_SWITCH;
  1115.       break;
  1116.     default:
  1117.       return (reloc_howto_type *) NULL;
  1118.     }
  1119.  
  1120.   return &mips_howto_table[mips_type];
  1121. }
  1122.  
  1123. /* A helper routine for mips_relocate_section which handles the REFHI
  1124.    and RELHI relocations.  The REFHI relocation must be followed by a
  1125.    REFLO relocation (and RELHI by a RELLO), and the addend used is
  1126.    formed from the addends of both instructions.  */
  1127.  
  1128. static void
  1129. mips_relocate_hi (refhi, reflo, input_bfd, input_section, contents, adjust,
  1130.           relocation, pcrel)
  1131.      struct internal_reloc *refhi;
  1132.      struct internal_reloc *reflo;
  1133.      bfd *input_bfd;
  1134.      asection *input_section;
  1135.      bfd_byte *contents;
  1136.      size_t adjust;
  1137.      bfd_vma relocation;
  1138.      boolean pcrel;
  1139. {
  1140.   unsigned long insn;
  1141.   unsigned long val;
  1142.   unsigned long vallo;
  1143.  
  1144.   insn = bfd_get_32 (input_bfd,
  1145.              contents + adjust + refhi->r_vaddr - input_section->vma);
  1146.   vallo = (bfd_get_32 (input_bfd,
  1147.                contents + adjust + reflo->r_vaddr - input_section->vma)
  1148.        & 0xffff);
  1149.   val = ((insn & 0xffff) << 16) + vallo;
  1150.   val += relocation;
  1151.  
  1152.   /* The low order 16 bits are always treated as a signed value.
  1153.      Therefore, a negative value in the low order bits requires an
  1154.      adjustment in the high order bits.  We need to make this
  1155.      adjustment in two ways: once for the bits we took from the data,
  1156.      and once for the bits we are putting back in to the data.  */
  1157.   if ((vallo & 0x8000) != 0)
  1158.     val -= 0x10000;
  1159.  
  1160.   if (pcrel)
  1161.     val -= (input_section->output_section->vma
  1162.         + input_section->output_offset
  1163.         + (reflo->r_vaddr - input_section->vma + adjust));
  1164.  
  1165.   if ((val & 0x8000) != 0)
  1166.     val += 0x10000;
  1167.  
  1168.   insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
  1169.   bfd_put_32 (input_bfd, (bfd_vma) insn,
  1170.           contents + adjust + refhi->r_vaddr - input_section->vma);
  1171. }
  1172.  
  1173. /* Relocate a section while linking a MIPS ECOFF file.  */
  1174.  
  1175. static boolean
  1176. mips_relocate_section (output_bfd, info, input_bfd, input_section,
  1177.                contents, external_relocs)
  1178.      bfd *output_bfd;
  1179.      struct bfd_link_info *info;
  1180.      bfd *input_bfd;
  1181.      asection *input_section;
  1182.      bfd_byte *contents;
  1183.      PTR external_relocs;
  1184. {
  1185.   asection **symndx_to_section;
  1186.   struct ecoff_link_hash_entry **sym_hashes;
  1187.   bfd_vma gp;
  1188.   boolean gp_undefined;
  1189.   size_t adjust;
  1190.   long *offsets;
  1191.   struct external_reloc *ext_rel;
  1192.   struct external_reloc *ext_rel_end;
  1193.   unsigned int i;
  1194.   boolean got_lo;
  1195.   struct internal_reloc lo_int_rel;
  1196.  
  1197.   BFD_ASSERT (input_bfd->xvec->header_byteorder
  1198.           == output_bfd->xvec->header_byteorder);
  1199.  
  1200.   /* We keep a table mapping the symndx found in an internal reloc to
  1201.      the appropriate section.  This is faster than looking up the
  1202.      section by name each time.  */
  1203.   symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
  1204.   if (symndx_to_section == (asection **) NULL)
  1205.     {
  1206.       symndx_to_section = ((asection **)
  1207.                bfd_alloc (input_bfd,
  1208.                       (NUM_RELOC_SECTIONS
  1209.                        * sizeof (asection *))));
  1210.       if (!symndx_to_section)
  1211.     return false;
  1212.  
  1213.       symndx_to_section[RELOC_SECTION_NONE] = NULL;
  1214.       symndx_to_section[RELOC_SECTION_TEXT] =
  1215.     bfd_get_section_by_name (input_bfd, ".text");
  1216.       symndx_to_section[RELOC_SECTION_RDATA] =
  1217.     bfd_get_section_by_name (input_bfd, ".rdata");
  1218.       symndx_to_section[RELOC_SECTION_DATA] =
  1219.     bfd_get_section_by_name (input_bfd, ".data");
  1220.       symndx_to_section[RELOC_SECTION_SDATA] =
  1221.     bfd_get_section_by_name (input_bfd, ".sdata");
  1222.       symndx_to_section[RELOC_SECTION_SBSS] =
  1223.     bfd_get_section_by_name (input_bfd, ".sbss");
  1224.       symndx_to_section[RELOC_SECTION_BSS] =
  1225.     bfd_get_section_by_name (input_bfd, ".bss");
  1226.       symndx_to_section[RELOC_SECTION_INIT] =
  1227.     bfd_get_section_by_name (input_bfd, ".init");
  1228.       symndx_to_section[RELOC_SECTION_LIT8] =
  1229.     bfd_get_section_by_name (input_bfd, ".lit8");
  1230.       symndx_to_section[RELOC_SECTION_LIT4] =
  1231.     bfd_get_section_by_name (input_bfd, ".lit4");
  1232.       symndx_to_section[RELOC_SECTION_XDATA] = NULL;
  1233.       symndx_to_section[RELOC_SECTION_PDATA] = NULL;
  1234.       symndx_to_section[RELOC_SECTION_FINI] =
  1235.     bfd_get_section_by_name (input_bfd, ".fini");
  1236.       symndx_to_section[RELOC_SECTION_LITA] = NULL;
  1237.       symndx_to_section[RELOC_SECTION_ABS] = NULL;
  1238.  
  1239.       ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
  1240.     }
  1241.  
  1242.   sym_hashes = ecoff_data (input_bfd)->sym_hashes;
  1243.  
  1244.   gp = _bfd_get_gp_value (output_bfd);
  1245.   if (gp == 0)
  1246.     gp_undefined = true;
  1247.   else
  1248.     gp_undefined = false;
  1249.  
  1250.   got_lo = false;
  1251.  
  1252.   adjust = 0;
  1253.  
  1254.   if (ecoff_section_data (input_bfd, input_section) == NULL)
  1255.     offsets = NULL;
  1256.   else
  1257.     offsets = ecoff_section_data (input_bfd, input_section)->offsets;
  1258.  
  1259.   ext_rel = (struct external_reloc *) external_relocs;
  1260.   ext_rel_end = ext_rel + input_section->reloc_count;
  1261.   for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
  1262.     {
  1263.       struct internal_reloc int_rel;
  1264.       bfd_vma addend;
  1265.       reloc_howto_type *howto;
  1266.       struct ecoff_link_hash_entry *h = NULL;
  1267.       asection *s = NULL;
  1268.       bfd_vma relocation;
  1269.       bfd_reloc_status_type r;
  1270.  
  1271.       if (! got_lo)
  1272.     mips_ecoff_swap_reloc_in (input_bfd, (PTR) ext_rel, &int_rel);
  1273.       else
  1274.     {
  1275.       int_rel = lo_int_rel;
  1276.       got_lo = false;
  1277.     }
  1278.  
  1279.       BFD_ASSERT (int_rel.r_type
  1280.           < sizeof mips_howto_table / sizeof mips_howto_table[0]);
  1281.  
  1282.       /* The REFHI and RELHI relocs requires special handling.  they
  1283.      must be followed by a REFLO or RELLO reloc, respectively, and
  1284.      the addend is formed from both relocs.  */
  1285.       if (int_rel.r_type == MIPS_R_REFHI
  1286.       || int_rel.r_type == MIPS_R_RELHI)
  1287.     {
  1288.       BFD_ASSERT ((ext_rel + 1) < ext_rel_end);
  1289.       mips_ecoff_swap_reloc_in (input_bfd, (PTR) (ext_rel + 1),
  1290.                     &lo_int_rel);
  1291.       BFD_ASSERT ((lo_int_rel.r_type
  1292.                == (int_rel.r_type == MIPS_R_REFHI
  1293.                ? MIPS_R_REFLO
  1294.                : MIPS_R_RELLO))
  1295.               && int_rel.r_extern == lo_int_rel.r_extern
  1296.               && int_rel.r_symndx == lo_int_rel.r_symndx);
  1297.       got_lo = true;
  1298.     }
  1299.  
  1300.       howto = &mips_howto_table[int_rel.r_type];
  1301.  
  1302.       /* The SWITCH reloc must be handled specially.  This reloc is
  1303.      marks the location of a difference between two portions of an
  1304.      object file.  The symbol index does not reference a symbol,
  1305.      but is actually the offset from the reloc to the subtrahend
  1306.      of the difference.  This reloc is correct in the object file,
  1307.      and needs no further adjustment, unless we are relaxing.  If
  1308.      we are relaxing, we may have to add in an offset.  Since no
  1309.      symbols are involved in this reloc, we handle it completely
  1310.      here.  */
  1311.       if (int_rel.r_type == MIPS_R_SWITCH)
  1312.     {
  1313.       if (offsets != NULL
  1314.           && offsets[i] != 0)
  1315.         {
  1316.           r = _bfd_relocate_contents (howto, input_bfd,
  1317.                       (bfd_vma) offsets[i],
  1318.                       (contents
  1319.                        + adjust
  1320.                        + int_rel.r_vaddr
  1321.                        - input_section->vma));
  1322.           BFD_ASSERT (r == bfd_reloc_ok);
  1323.         }
  1324.  
  1325.       continue;
  1326.     }
  1327.  
  1328.       if (int_rel.r_extern)
  1329.     {
  1330.       h = sym_hashes[int_rel.r_symndx];
  1331.       /* If h is NULL, that means that there is a reloc against an
  1332.          external symbol which we thought was just a debugging
  1333.          symbol.  This should not happen.  */
  1334.       if (h == (struct ecoff_link_hash_entry *) NULL)
  1335.         abort ();
  1336.     }
  1337.       else
  1338.     {
  1339.       if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
  1340.         s = NULL;
  1341.       else
  1342.         s = symndx_to_section[int_rel.r_symndx];
  1343.  
  1344.       if (s == (asection *) NULL)
  1345.         abort ();
  1346.     }
  1347.  
  1348.       /* The GPREL reloc uses an addend: the difference in the GP
  1349.      values.  */
  1350.       if (int_rel.r_type != MIPS_R_GPREL
  1351.       && int_rel.r_type != MIPS_R_LITERAL)
  1352.     addend = 0;
  1353.       else
  1354.     {
  1355.       if (gp_undefined)
  1356.         {
  1357.           if (! ((*info->callbacks->reloc_dangerous)
  1358.              (info, "GP relative relocation when GP not defined",
  1359.               input_bfd, input_section,
  1360.               int_rel.r_vaddr - input_section->vma)))
  1361.         return false;
  1362.           /* Only give the error once per link.  */
  1363.           gp = 4;
  1364.           _bfd_set_gp_value (output_bfd, gp);
  1365.           gp_undefined = false;
  1366.         }
  1367.       if (! int_rel.r_extern)
  1368.         {
  1369.           /* This is a relocation against a section.  The current
  1370.          addend in the instruction is the difference between
  1371.          INPUT_SECTION->vma and the GP value of INPUT_BFD.  We
  1372.          must change this to be the difference between the
  1373.          final definition (which will end up in RELOCATION)
  1374.          and the GP value of OUTPUT_BFD (which is in GP).  */
  1375.           addend = ecoff_data (input_bfd)->gp - gp;
  1376.         }
  1377.       else if (! info->relocateable
  1378.            || h->root.type == bfd_link_hash_defined
  1379.            || h->root.type == bfd_link_hash_defweak)
  1380.         {
  1381.           /* This is a relocation against a defined symbol.  The
  1382.          current addend in the instruction is simply the
  1383.          desired offset into the symbol (normally zero).  We
  1384.          are going to change this into a relocation against a
  1385.          defined symbol, so we want the instruction to hold
  1386.          the difference between the final definition of the
  1387.          symbol (which will end up in RELOCATION) and the GP
  1388.          value of OUTPUT_BFD (which is in GP).  */
  1389.           addend = - gp;
  1390.         }
  1391.       else
  1392.         {
  1393.           /* This is a relocation against an undefined or common
  1394.          symbol.  The current addend in the instruction is
  1395.          simply the desired offset into the symbol (normally
  1396.          zero).  We are generating relocateable output, and we
  1397.          aren't going to define this symbol, so we just leave
  1398.          the instruction alone.  */
  1399.           addend = 0;
  1400.         }
  1401.     }
  1402.  
  1403.       /* If we are relaxing, mips_relax_section may have set
  1404.      offsets[i] to some value.  A value of 1 means we must expand
  1405.      a PC relative branch into a multi-instruction of sequence,
  1406.      and any other value is an addend.  */
  1407.       if (offsets != NULL
  1408.       && offsets[i] != 0)
  1409.     {
  1410.       BFD_ASSERT (! info->relocateable);
  1411.       BFD_ASSERT (int_rel.r_type == MIPS_R_PCREL16
  1412.               || int_rel.r_type == MIPS_R_RELHI
  1413.               || int_rel.r_type == MIPS_R_RELLO);
  1414.       if (offsets[i] != 1)
  1415.         addend += offsets[i];
  1416.       else
  1417.         {
  1418.           bfd_byte *here;
  1419.  
  1420.           BFD_ASSERT (int_rel.r_extern
  1421.               && int_rel.r_type == MIPS_R_PCREL16);
  1422.  
  1423.           /* Move the rest of the instructions up.  */
  1424.           here = (contents
  1425.               + adjust
  1426.               + int_rel.r_vaddr
  1427.               - input_section->vma);
  1428.           memmove (here + PCREL16_EXPANSION_ADJUSTMENT, here,
  1429.                (size_t) (input_section->_raw_size
  1430.                  - (int_rel.r_vaddr - input_section->vma)));
  1431.                
  1432.           /* Generate the new instructions.  */
  1433.           if (! mips_relax_pcrel16 (info, input_bfd, input_section,
  1434.                     h, here,
  1435.                     (input_section->output_section->vma
  1436.                      + input_section->output_offset
  1437.                      + (int_rel.r_vaddr
  1438.                         - input_section->vma)
  1439.                      + adjust)))
  1440.         return false;
  1441.  
  1442.           /* We must adjust everything else up a notch.  */
  1443.           adjust += PCREL16_EXPANSION_ADJUSTMENT;
  1444.  
  1445.           /* mips_relax_pcrel16 handles all the details of this
  1446.          relocation.  */
  1447.           continue;
  1448.         }
  1449.     }
  1450.  
  1451.       /* If we are relaxing, and this is a reloc against the .text
  1452.      segment, we may need to adjust it if some branches have been
  1453.      expanded.  The reloc types which are likely to occur in the
  1454.      .text section are handled efficiently by mips_relax_section,
  1455.      and thus do not need to be handled here.  */
  1456.       if (ecoff_data (input_bfd)->debug_info.adjust != NULL
  1457.       && ! int_rel.r_extern
  1458.       && int_rel.r_symndx == RELOC_SECTION_TEXT
  1459.       && (strcmp (bfd_get_section_name (input_bfd, input_section),
  1460.               ".text") != 0
  1461.           || (int_rel.r_type != MIPS_R_PCREL16
  1462.           && int_rel.r_type != MIPS_R_SWITCH
  1463.           && int_rel.r_type != MIPS_R_RELHI
  1464.           && int_rel.r_type != MIPS_R_RELLO)))
  1465.     {
  1466.       bfd_vma adr;
  1467.       struct ecoff_value_adjust *a;
  1468.  
  1469.       /* We need to get the addend so that we know whether we need
  1470.          to adjust the address.  */
  1471.       BFD_ASSERT (int_rel.r_type == MIPS_R_REFWORD);
  1472.  
  1473.       adr = bfd_get_32 (input_bfd,
  1474.                 (contents
  1475.                  + adjust
  1476.                  + int_rel.r_vaddr
  1477.                  - input_section->vma));
  1478.  
  1479.       for (a = ecoff_data (input_bfd)->debug_info.adjust;
  1480.            a != (struct ecoff_value_adjust *) NULL;
  1481.            a = a->next)
  1482.         {
  1483.           if (adr >= a->start && adr < a->end)
  1484.         addend += a->adjust;
  1485.         }
  1486.     }
  1487.  
  1488.       if (info->relocateable)
  1489.     {
  1490.       /* We are generating relocateable output, and must convert
  1491.          the existing reloc.  */
  1492.       if (int_rel.r_extern)
  1493.         {
  1494.           if ((h->root.type == bfd_link_hash_defined
  1495.            || h->root.type == bfd_link_hash_defweak)
  1496.           && ! bfd_is_abs_section (h->root.u.def.section))
  1497.         {
  1498.           const char *name;
  1499.  
  1500.           /* This symbol is defined in the output.  Convert
  1501.              the reloc from being against the symbol to being
  1502.              against the section.  */
  1503.  
  1504.           /* Clear the r_extern bit.  */
  1505.           int_rel.r_extern = 0;
  1506.  
  1507.           /* Compute a new r_symndx value.  */
  1508.           s = h->root.u.def.section;
  1509.           name = bfd_get_section_name (output_bfd,
  1510.                            s->output_section);
  1511.  
  1512.           int_rel.r_symndx = -1;
  1513.           switch (name[1])
  1514.             {
  1515.             case 'b':
  1516.               if (strcmp (name, ".bss") == 0)
  1517.             int_rel.r_symndx = RELOC_SECTION_BSS;
  1518.               break;
  1519.             case 'd':
  1520.               if (strcmp (name, ".data") == 0)
  1521.             int_rel.r_symndx = RELOC_SECTION_DATA;
  1522.               break;
  1523.             case 'f':
  1524.               if (strcmp (name, ".fini") == 0)
  1525.             int_rel.r_symndx = RELOC_SECTION_FINI;
  1526.               break;
  1527.             case 'i':
  1528.               if (strcmp (name, ".init") == 0)
  1529.             int_rel.r_symndx = RELOC_SECTION_INIT;
  1530.               break;
  1531.             case 'l':
  1532.               if (strcmp (name, ".lit8") == 0)
  1533.             int_rel.r_symndx = RELOC_SECTION_LIT8;
  1534.               else if (strcmp (name, ".lit4") == 0)
  1535.             int_rel.r_symndx = RELOC_SECTION_LIT4;
  1536.               break;
  1537.             case 'r':
  1538.               if (strcmp (name, ".rdata") == 0)
  1539.             int_rel.r_symndx = RELOC_SECTION_RDATA;
  1540.               break;
  1541.             case 's':
  1542.               if (strcmp (name, ".sdata") == 0)
  1543.             int_rel.r_symndx = RELOC_SECTION_SDATA;
  1544.               else if (strcmp (name, ".sbss") == 0)
  1545.             int_rel.r_symndx = RELOC_SECTION_SBSS;
  1546.               break;
  1547.             case 't':
  1548.               if (strcmp (name, ".text") == 0)
  1549.             int_rel.r_symndx = RELOC_SECTION_TEXT;
  1550.               break;
  1551.             }
  1552.               
  1553.           if (int_rel.r_symndx == -1)
  1554.             abort ();
  1555.  
  1556.           /* Add the section VMA and the symbol value.  */
  1557.           relocation = (h->root.u.def.value
  1558.                 + s->output_section->vma
  1559.                 + s->output_offset);
  1560.  
  1561.           /* For a PC relative relocation, the object file
  1562.              currently holds just the addend.  We must adjust
  1563.              by the address to get the right value.  */
  1564.           if (howto->pc_relative)
  1565.             {
  1566.               relocation -= int_rel.r_vaddr - input_section->vma;
  1567.  
  1568.               /* If we are converting a RELHI or RELLO reloc
  1569.              from being against an external symbol to
  1570.              being against a section, we must put a
  1571.              special value into the r_offset field.  This
  1572.              value is the old addend.  The r_offset for
  1573.              both the RELOHI and RELLO relocs are the
  1574.              same, and we set both when we see RELHI.  */
  1575.               if (int_rel.r_type == MIPS_R_RELHI)
  1576.             {
  1577.               long addhi, addlo;
  1578.  
  1579.               addhi = bfd_get_32 (input_bfd,
  1580.                           (contents
  1581.                            + adjust
  1582.                            + int_rel.r_vaddr
  1583.                            - input_section->vma));
  1584.               addhi &= 0xffff;
  1585.               if (addhi & 0x8000)
  1586.                 addhi -= 0x10000;
  1587.               addhi <<= 16;
  1588.  
  1589.               addlo = bfd_get_32 (input_bfd,
  1590.                           (contents
  1591.                            + adjust
  1592.                            + lo_int_rel.r_vaddr
  1593.                            - input_section->vma));
  1594.               addlo &= 0xffff;
  1595.               if (addlo & 0x8000)
  1596.                 addlo -= 0x10000;
  1597.  
  1598.               int_rel.r_offset = addhi + addlo;
  1599.               lo_int_rel.r_offset = int_rel.r_offset;
  1600.             }
  1601.             }
  1602.  
  1603.           h = NULL;
  1604.         }
  1605.           else
  1606.         {
  1607.           /* Change the symndx value to the right one for the
  1608.              output BFD.  */
  1609.           int_rel.r_symndx = h->indx;
  1610.           if (int_rel.r_symndx == -1)
  1611.             {
  1612.               /* This symbol is not being written out.  */
  1613.               if (! ((*info->callbacks->unattached_reloc)
  1614.                  (info, h->root.root.string, input_bfd,
  1615.                   input_section,
  1616.                   int_rel.r_vaddr - input_section->vma)))
  1617.             return false;
  1618.               int_rel.r_symndx = 0;
  1619.             }
  1620.           relocation = 0;
  1621.         }
  1622.         }
  1623.       else
  1624.         {
  1625.           /* This is a relocation against a section.  Adjust the
  1626.          value by the amount the section moved.  */
  1627.           relocation = (s->output_section->vma
  1628.                 + s->output_offset
  1629.                 - s->vma);
  1630.         }
  1631.  
  1632.       relocation += addend;
  1633.       addend = 0;
  1634.  
  1635.       /* Adjust a PC relative relocation by removing the reference
  1636.          to the original address in the section and including the
  1637.          reference to the new address.  However, external RELHI
  1638.          and RELLO relocs are PC relative, but don't include any
  1639.          reference to the address.  The addend is merely an
  1640.          addend.  */
  1641.       if (howto->pc_relative
  1642.           && (! int_rel.r_extern
  1643.           || (int_rel.r_type != MIPS_R_RELHI
  1644.               && int_rel.r_type != MIPS_R_RELLO)))
  1645.         relocation -= (input_section->output_section->vma
  1646.                + input_section->output_offset
  1647.                - input_section->vma);
  1648.  
  1649.       /* Adjust the contents.  */
  1650.       if (relocation == 0)
  1651.         r = bfd_reloc_ok;
  1652.       else
  1653.         {
  1654.           if (int_rel.r_type != MIPS_R_REFHI
  1655.           && int_rel.r_type != MIPS_R_RELHI)
  1656.         r = _bfd_relocate_contents (howto, input_bfd, relocation,
  1657.                         (contents
  1658.                          + adjust
  1659.                          + int_rel.r_vaddr
  1660.                          - input_section->vma));
  1661.           else
  1662.         {
  1663.           mips_relocate_hi (&int_rel, &lo_int_rel,
  1664.                     input_bfd, input_section, contents,
  1665.                     adjust, relocation,
  1666.                     int_rel.r_type == MIPS_R_RELHI);
  1667.           r = bfd_reloc_ok;
  1668.         }
  1669.         }
  1670.  
  1671.       /* Adjust the reloc address.  */
  1672.       int_rel.r_vaddr += (input_section->output_section->vma
  1673.                   + input_section->output_offset
  1674.                   - input_section->vma);
  1675.  
  1676.       /* Save the changed reloc information.  */
  1677.       mips_ecoff_swap_reloc_out (input_bfd, &int_rel, (PTR) ext_rel);
  1678.     }
  1679.       else
  1680.     {
  1681.       /* We are producing a final executable.  */
  1682.       if (int_rel.r_extern)
  1683.         {
  1684.           /* This is a reloc against a symbol.  */
  1685.           if (h->root.type == bfd_link_hash_defined
  1686.           || h->root.type == bfd_link_hash_defweak)
  1687.         {
  1688.           asection *hsec;
  1689.  
  1690.           hsec = h->root.u.def.section;
  1691.           relocation = (h->root.u.def.value
  1692.                 + hsec->output_section->vma
  1693.                 + hsec->output_offset);
  1694.         }
  1695.           else
  1696.         {
  1697.           if (! ((*info->callbacks->undefined_symbol)
  1698.              (info, h->root.root.string, input_bfd,
  1699.               input_section,
  1700.               int_rel.r_vaddr - input_section->vma)))
  1701.             return false;
  1702.           relocation = 0;
  1703.         }
  1704.         }
  1705.       else
  1706.         {
  1707.           /* This is a reloc against a section.  */
  1708.           relocation = (s->output_section->vma
  1709.                 + s->output_offset
  1710.                 - s->vma);
  1711.  
  1712.           /* A PC relative reloc is already correct in the object
  1713.          file.  Make it look like a pcrel_offset relocation by
  1714.          adding in the start address.  */
  1715.           if (howto->pc_relative)
  1716.         {
  1717.           if (int_rel.r_type != MIPS_R_RELHI)
  1718.             relocation += int_rel.r_vaddr + adjust;
  1719.           else
  1720.             relocation += lo_int_rel.r_vaddr + adjust;
  1721.         }
  1722.         }
  1723.  
  1724.       if (int_rel.r_type != MIPS_R_REFHI
  1725.           && int_rel.r_type != MIPS_R_RELHI)
  1726.         r = _bfd_final_link_relocate (howto,
  1727.                       input_bfd,
  1728.                       input_section,
  1729.                       contents,
  1730.                       (int_rel.r_vaddr
  1731.                        - input_section->vma
  1732.                        + adjust),
  1733.                       relocation,
  1734.                       addend);
  1735.       else
  1736.         {
  1737.           mips_relocate_hi (&int_rel, &lo_int_rel, input_bfd,
  1738.                 input_section, contents, adjust,
  1739.                 relocation,
  1740.                 int_rel.r_type == MIPS_R_RELHI);
  1741.           r = bfd_reloc_ok;
  1742.         }
  1743.     }
  1744.  
  1745.       /* MIPS_R_JMPADDR requires peculiar overflow detection.  The
  1746.      instruction provides a 28 bit address (the two lower bits are
  1747.      implicit zeroes) which is combined with the upper four bits
  1748.      of the instruction address.  */
  1749.       if (r == bfd_reloc_ok
  1750.       && int_rel.r_type == MIPS_R_JMPADDR
  1751.       && (((relocation
  1752.         + addend
  1753.         + (int_rel.r_extern ? 0 : s->vma))
  1754.            & 0xf0000000)
  1755.           != ((input_section->output_section->vma
  1756.            + input_section->output_offset
  1757.            + (int_rel.r_vaddr - input_section->vma)
  1758.            + adjust)
  1759.           & 0xf0000000)))
  1760.     r = bfd_reloc_overflow;
  1761.  
  1762.       if (r != bfd_reloc_ok)
  1763.     {
  1764.       switch (r)
  1765.         {
  1766.         default:
  1767.         case bfd_reloc_outofrange:
  1768.           abort ();
  1769.         case bfd_reloc_overflow:
  1770.           {
  1771.         const char *name;
  1772.  
  1773.         if (int_rel.r_extern)
  1774.           name = h->root.root.string;
  1775.         else
  1776.           name = bfd_section_name (input_bfd, s);
  1777.         if (! ((*info->callbacks->reloc_overflow)
  1778.                (info, name, howto->name, (bfd_vma) 0,
  1779.             input_bfd, input_section,
  1780.             int_rel.r_vaddr - input_section->vma)))
  1781.           return false;
  1782.           }
  1783.           break;
  1784.         }
  1785.     }
  1786.     }
  1787.  
  1788.   return true;
  1789. }
  1790.  
  1791. /* Read in the relocs for a section.  */
  1792.  
  1793. static boolean
  1794. mips_read_relocs (abfd, sec)
  1795.      bfd *abfd;
  1796.      asection *sec;
  1797. {
  1798.   struct ecoff_section_tdata *section_tdata;
  1799.  
  1800.   section_tdata = ecoff_section_data (abfd, sec);
  1801.   if (section_tdata == (struct ecoff_section_tdata *) NULL)
  1802.     {
  1803.       sec->used_by_bfd =
  1804.     (PTR) bfd_alloc_by_size_t (abfd, sizeof (struct ecoff_section_tdata));
  1805.       if (sec->used_by_bfd == NULL)
  1806.     return false;
  1807.  
  1808.       section_tdata = ecoff_section_data (abfd, sec);
  1809.       section_tdata->external_relocs = NULL;
  1810.       section_tdata->contents = NULL;
  1811.       section_tdata->offsets = NULL;
  1812.     }
  1813.  
  1814.   if (section_tdata->external_relocs == NULL)
  1815.     {
  1816.       bfd_size_type external_relocs_size;
  1817.  
  1818.       external_relocs_size = (ecoff_backend (abfd)->external_reloc_size
  1819.                   * sec->reloc_count);
  1820.  
  1821.       section_tdata->external_relocs =
  1822.     (PTR) bfd_alloc (abfd, external_relocs_size);
  1823.       if (section_tdata->external_relocs == NULL && external_relocs_size != 0)
  1824.     return false;
  1825.  
  1826.       if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
  1827.       || (bfd_read (section_tdata->external_relocs, 1,
  1828.             external_relocs_size, abfd)
  1829.           != external_relocs_size))
  1830.     return false;
  1831.     }
  1832.  
  1833.   return true;
  1834. }
  1835.  
  1836. /* Relax a section when linking a MIPS ECOFF file.  This is used for
  1837.    embedded PIC code, which always uses PC relative branches which
  1838.    only have an 18 bit range on MIPS.  If a branch is not in range, we
  1839.    generate a long instruction sequence to compensate.  Each time we
  1840.    find a branch to expand, we have to check all the others again to
  1841.    make sure they are still in range.  This is slow, but it only has
  1842.    to be done when -relax is passed to the linker.
  1843.  
  1844.    This routine figures out which branches need to expand; the actual
  1845.    expansion is done in mips_relocate_section when the section
  1846.    contents are relocated.  The information is stored in the offsets
  1847.    field of the ecoff_section_tdata structure.  An offset of 1 means
  1848.    that the branch must be expanded into a multi-instruction PC
  1849.    relative branch (such an offset will only occur for a PC relative
  1850.    branch to an external symbol).  Any other offset must be a multiple
  1851.    of four, and is the amount to change the branch by (such an offset
  1852.    will only occur for a PC relative branch within the same section).
  1853.  
  1854.    We do not modify the section relocs or contents themselves so that
  1855.    if memory usage becomes an issue we can discard them and read them
  1856.    again.  The only information we must save in memory between this
  1857.    routine and the mips_relocate_section routine is the table of
  1858.    offsets.  */
  1859.  
  1860. static boolean
  1861. mips_relax_section (abfd, sec, info, again)
  1862.      bfd *abfd;
  1863.      asection *sec;
  1864.      struct bfd_link_info *info;
  1865.      boolean *again;
  1866. {
  1867.   struct ecoff_section_tdata *section_tdata;
  1868.   bfd_byte *contents = NULL;
  1869.   long *offsets;
  1870.   struct external_reloc *ext_rel;
  1871.   struct external_reloc *ext_rel_end;
  1872.   unsigned int i;
  1873.  
  1874.   /* Assume we are not going to need another pass.  */
  1875.   *again = false;
  1876.  
  1877.   /* If we are not generating an ECOFF file, this is much too
  1878.      confusing to deal with.  */
  1879.   if (info->hash->creator->flavour != bfd_get_flavour (abfd))
  1880.     return true;
  1881.  
  1882.   /* If there are no relocs, there is nothing to do.  */
  1883.   if (sec->reloc_count == 0)
  1884.     return true;
  1885.  
  1886.   /* We are only interested in PC relative relocs, and why would there
  1887.      ever be one from anything but the .text section?  */
  1888.   if (strcmp (bfd_get_section_name (abfd, sec), ".text") != 0)
  1889.     return true;
  1890.  
  1891.   /* Read in the relocs, if we haven't already got them.  */
  1892.   section_tdata = ecoff_section_data (abfd, sec);
  1893.   if (section_tdata == (struct ecoff_section_tdata *) NULL
  1894.       || section_tdata->external_relocs == NULL)
  1895.     {
  1896.       if (! mips_read_relocs (abfd, sec))
  1897.     goto error_return;
  1898.       section_tdata = ecoff_section_data (abfd, sec);
  1899.     }
  1900.  
  1901.   if (sec->_cooked_size == 0)
  1902.     {
  1903.       /* We must initialize _cooked_size only the first time we are
  1904.      called.  */
  1905.       sec->_cooked_size = sec->_raw_size;
  1906.     }
  1907.  
  1908.   contents = section_tdata->contents;
  1909.   offsets = section_tdata->offsets;
  1910.  
  1911.   /* Look for any external PC relative relocs.  Internal PC relative
  1912.      relocs are already correct in the object file, so they certainly
  1913.      can not overflow.  */
  1914.   ext_rel = (struct external_reloc *) section_tdata->external_relocs;
  1915.   ext_rel_end = ext_rel + sec->reloc_count;
  1916.   for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
  1917.     {
  1918.       struct internal_reloc int_rel;
  1919.       struct ecoff_link_hash_entry *h;
  1920.       asection *hsec;
  1921.       bfd_signed_vma relocation;
  1922.       struct external_reloc *adj_ext_rel;
  1923.       unsigned int adj_i;
  1924.       unsigned long ext_count;
  1925.       struct ecoff_link_hash_entry **adj_h_ptr;
  1926.       struct ecoff_link_hash_entry **adj_h_ptr_end;
  1927.       struct ecoff_value_adjust *adjust;
  1928.  
  1929.       /* If we have already expanded this reloc, we certainly don't
  1930.      need to do it again.  */
  1931.       if (offsets != (long *) NULL && offsets[i] == 1)
  1932.     continue;
  1933.  
  1934.       /* Quickly check that this reloc is external PCREL16.  */
  1935.       if (bfd_header_big_endian (abfd))
  1936.     {
  1937.       if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_BIG) == 0
  1938.           || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_BIG)
  1939.            >> RELOC_BITS3_TYPE_SH_BIG)
  1940.           != MIPS_R_PCREL16))
  1941.         continue;
  1942.     }
  1943.       else
  1944.     {
  1945.       if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) == 0
  1946.           || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
  1947.            >> RELOC_BITS3_TYPE_SH_LITTLE)
  1948.           != MIPS_R_PCREL16))
  1949.         continue;
  1950.     }
  1951.  
  1952.       mips_ecoff_swap_reloc_in (abfd, (PTR) ext_rel, &int_rel);
  1953.  
  1954.       h = ecoff_data (abfd)->sym_hashes[int_rel.r_symndx];
  1955.       if (h == (struct ecoff_link_hash_entry *) NULL)
  1956.     abort ();
  1957.  
  1958.       if (h->root.type != bfd_link_hash_defined
  1959.       && h->root.type != bfd_link_hash_defweak)
  1960.     {
  1961.       /* Just ignore undefined symbols.  These will presumably
  1962.          generate an error later in the link.  */
  1963.       continue;
  1964.     }
  1965.  
  1966.       /* Get the value of the symbol.  */
  1967.       hsec = h->root.u.def.section;
  1968.       relocation = (h->root.u.def.value
  1969.             + hsec->output_section->vma
  1970.             + hsec->output_offset);
  1971.  
  1972.       /* Subtract out the current address.  */
  1973.       relocation -= (sec->output_section->vma
  1974.              + sec->output_offset
  1975.              + (int_rel.r_vaddr - sec->vma));
  1976.  
  1977.       /* The addend is stored in the object file.  In the normal case
  1978.      of ``bal symbol'', the addend will be -4.  It will only be
  1979.      different in the case of ``bal symbol+constant''.  To avoid
  1980.      always reading in the section contents, we don't check the
  1981.      addend in the object file (we could easily check the contents
  1982.      if we happen to have already read them in, but I fear that
  1983.      this could be confusing).  This means we will screw up if
  1984.      there is a branch to a symbol that is in range, but added to
  1985.      a constant which puts it out of range; in such a case the
  1986.      link will fail with a reloc overflow error.  Since the
  1987.      compiler will never generate such code, it should be easy
  1988.      enough to work around it by changing the assembly code in the
  1989.      source file.  */
  1990.       relocation -= 4;
  1991.  
  1992.       /* Now RELOCATION is the number we want to put in the object
  1993.      file.  See whether it fits.  */
  1994.       if (relocation >= -0x20000 && relocation < 0x20000)
  1995.     continue;
  1996.  
  1997.       /* Now that we know this reloc needs work, which will rarely
  1998.      happen, go ahead and grab the section contents.  */
  1999.       if (contents == (bfd_byte *) NULL)
  2000.     {
  2001.       if (info->keep_memory)
  2002.         contents = (bfd_byte *) bfd_alloc (abfd, sec->_raw_size);
  2003.       else
  2004.         contents = (bfd_byte *) bfd_malloc ((size_t) sec->_raw_size);
  2005.       if (contents == (bfd_byte *) NULL)
  2006.         goto error_return;
  2007.       if (! bfd_get_section_contents (abfd, sec, (PTR) contents,
  2008.                       (file_ptr) 0, sec->_raw_size))
  2009.         goto error_return;
  2010.       if (info->keep_memory)
  2011.         section_tdata->contents = contents;
  2012.     }
  2013.  
  2014.       /* We only support changing the bal instruction.  It would be
  2015.      possible to handle other PC relative branches, but some of
  2016.      them (the conditional branches) would require a different
  2017.      length instruction sequence which would complicate both this
  2018.      routine and mips_relax_pcrel16.  It could be written if
  2019.      somebody felt it were important.  Ignoring this reloc will
  2020.      presumably cause a reloc overflow error later on.  */
  2021.       if (bfd_get_32 (abfd, contents + int_rel.r_vaddr - sec->vma)
  2022.       != 0x0411ffff) /* bgezal $0,. == bal . */
  2023.     continue;
  2024.  
  2025.       /* Bother.  We need to expand this reloc, and we will need to
  2026.      make another relaxation pass since this change may put other
  2027.      relocs out of range.  We need to examine the local branches
  2028.      and we need to allocate memory to hold the offsets we must
  2029.      add to them.  We also need to adjust the values of all
  2030.      symbols in the object file following this location.  */
  2031.  
  2032.       sec->_cooked_size += PCREL16_EXPANSION_ADJUSTMENT;
  2033.       *again = true;
  2034.  
  2035.       if (offsets == (long *) NULL)
  2036.     {
  2037.       size_t size;
  2038.  
  2039.       size = sec->reloc_count * sizeof (long);
  2040.       offsets = (long *) bfd_alloc_by_size_t (abfd, size);
  2041.       if (offsets == (long *) NULL)
  2042.         goto error_return;
  2043.       memset (offsets, 0, size);
  2044.       section_tdata->offsets = offsets;
  2045.     }
  2046.  
  2047.       offsets[i] = 1;
  2048.  
  2049.       /* Now look for all PC relative references that cross this reloc
  2050.      and adjust their offsets.  */
  2051.       adj_ext_rel = (struct external_reloc *) section_tdata->external_relocs;
  2052.       for (adj_i = 0; adj_ext_rel < ext_rel_end; adj_ext_rel++, adj_i++)
  2053.     {
  2054.       struct internal_reloc adj_int_rel;
  2055.       bfd_vma start, stop;
  2056.       int change;
  2057.  
  2058.       mips_ecoff_swap_reloc_in (abfd, (PTR) adj_ext_rel, &adj_int_rel);
  2059.  
  2060.       if (adj_int_rel.r_type == MIPS_R_PCREL16)
  2061.         {
  2062.           unsigned long insn;
  2063.  
  2064.           /* We only care about local references.  External ones
  2065.          will be relocated correctly anyhow.  */
  2066.           if (adj_int_rel.r_extern)
  2067.         continue;
  2068.  
  2069.           /* We are only interested in a PC relative reloc within
  2070.          this section.  FIXME: Cross section PC relative
  2071.          relocs may not be handled correctly; does anybody
  2072.          care?  */
  2073.           if (adj_int_rel.r_symndx != RELOC_SECTION_TEXT)
  2074.         continue;
  2075.  
  2076.           start = adj_int_rel.r_vaddr;
  2077.  
  2078.           insn = bfd_get_32 (abfd,
  2079.                  contents + adj_int_rel.r_vaddr - sec->vma);
  2080.  
  2081.           stop = (insn & 0xffff) << 2;
  2082.           if ((stop & 0x20000) != 0)
  2083.         stop -= 0x40000;
  2084.           stop += adj_int_rel.r_vaddr + 4;
  2085.         }
  2086.       else if (adj_int_rel.r_type == MIPS_R_RELHI)
  2087.         {
  2088.           struct internal_reloc rello;
  2089.           long addhi, addlo;
  2090.  
  2091.           /* The next reloc must be MIPS_R_RELLO, and we handle
  2092.          them together.  */
  2093.           BFD_ASSERT (adj_ext_rel + 1 < ext_rel_end);
  2094.  
  2095.           mips_ecoff_swap_reloc_in (abfd, (PTR) (adj_ext_rel + 1), &rello);
  2096.  
  2097.           BFD_ASSERT (rello.r_type == MIPS_R_RELLO);
  2098.           
  2099.           addhi = bfd_get_32 (abfd,
  2100.                    contents + adj_int_rel.r_vaddr - sec->vma);
  2101.           addhi &= 0xffff;
  2102.           if (addhi & 0x8000)
  2103.         addhi -= 0x10000;
  2104.           addhi <<= 16;
  2105.  
  2106.           addlo = bfd_get_32 (abfd, contents + rello.r_vaddr - sec->vma);
  2107.           addlo &= 0xffff;
  2108.           if (addlo & 0x8000)
  2109.         addlo -= 0x10000;
  2110.  
  2111.           if (adj_int_rel.r_extern)
  2112.         {
  2113.           /* The value we want here is
  2114.                sym - RELLOaddr + addend
  2115.              which we can express as
  2116.                sym - (RELLOaddr - addend)
  2117.              Therefore if we are expanding the area between
  2118.              RELLOaddr and RELLOaddr - addend we must adjust
  2119.              the addend.  This is admittedly ambiguous, since
  2120.              we might mean (sym + addend) - RELLOaddr, but in
  2121.              practice we don't, and there is no way to handle
  2122.              that case correctly since at this point we have
  2123.              no idea whether any reloc is being expanded
  2124.              between sym and sym + addend.  */
  2125.           start = rello.r_vaddr - (addhi + addlo);
  2126.           stop = rello.r_vaddr;
  2127.         }
  2128.           else
  2129.         {
  2130.           /* An internal RELHI/RELLO pair represents the
  2131.              difference between two addresses, $LC0 - foo.
  2132.              The symndx value is actually the difference
  2133.              between the reloc address and $LC0.  This lets us
  2134.              compute $LC0, and, by considering the addend,
  2135.              foo.  If the reloc we are expanding falls between
  2136.              those two relocs, we must adjust the addend.  At
  2137.              this point, the symndx value is actually in the
  2138.              r_offset field, where it was put by
  2139.              mips_ecoff_swap_reloc_in.  */
  2140.           start = rello.r_vaddr - adj_int_rel.r_offset;
  2141.           stop = start + addhi + addlo;
  2142.         }
  2143.         }
  2144.       else if (adj_int_rel.r_type == MIPS_R_SWITCH)
  2145.         {
  2146.           /* A MIPS_R_SWITCH reloc represents a word of the form
  2147.            .word $L3-$LS12
  2148.          The value in the object file is correct, assuming the
  2149.          original value of $L3.  The symndx value is actually
  2150.          the difference between the reloc address and $LS12.
  2151.          This lets us compute the original value of $LS12 as
  2152.            vaddr - symndx
  2153.          and the original value of $L3 as
  2154.            vaddr - symndx + addend
  2155.          where addend is the value from the object file.  At
  2156.          this point, the symndx value is actually found in the
  2157.          r_offset field, since it was moved by
  2158.          mips_ecoff_swap_reloc_in.  */
  2159.           start = adj_int_rel.r_vaddr - adj_int_rel.r_offset;
  2160.           stop = start + bfd_get_32 (abfd,
  2161.                      (contents
  2162.                       + adj_int_rel.r_vaddr
  2163.                       - sec->vma));
  2164.         }
  2165.       else
  2166.         continue;
  2167.  
  2168.       /* If the range expressed by this reloc, which is the
  2169.          distance between START and STOP crosses the reloc we are
  2170.          expanding, we must adjust the offset.  The sign of the
  2171.          adjustment depends upon the direction in which the range
  2172.          crosses the reloc being expanded.  */
  2173.       if (start <= int_rel.r_vaddr && stop > int_rel.r_vaddr)
  2174.         change = PCREL16_EXPANSION_ADJUSTMENT;
  2175.       else if (start > int_rel.r_vaddr && stop <= int_rel.r_vaddr)
  2176.         change = - PCREL16_EXPANSION_ADJUSTMENT;
  2177.       else
  2178.         change = 0;
  2179.  
  2180.       offsets[adj_i] += change;
  2181.  
  2182.       if (adj_int_rel.r_type == MIPS_R_RELHI)
  2183.         {
  2184.           adj_ext_rel++;
  2185.           adj_i++;
  2186.           offsets[adj_i] += change;
  2187.         }
  2188.     }
  2189.  
  2190.       /* Find all symbols in this section defined by this object file
  2191.      and adjust their values.  Note that we decide whether to
  2192.      adjust the value based on the value stored in the ECOFF EXTR
  2193.      structure, because the value stored in the hash table may
  2194.      have been changed by an earlier expanded reloc and thus may
  2195.      no longer correctly indicate whether the symbol is before or
  2196.      after the expanded reloc.  */
  2197.       ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
  2198.       adj_h_ptr = ecoff_data (abfd)->sym_hashes;
  2199.       adj_h_ptr_end = adj_h_ptr + ext_count;
  2200.       for (; adj_h_ptr < adj_h_ptr_end; adj_h_ptr++)
  2201.     {
  2202.       struct ecoff_link_hash_entry *adj_h;
  2203.  
  2204.       adj_h = *adj_h_ptr;
  2205.       if (adj_h != (struct ecoff_link_hash_entry *) NULL
  2206.           && (adj_h->root.type == bfd_link_hash_defined
  2207.           || adj_h->root.type == bfd_link_hash_defweak)
  2208.           && adj_h->root.u.def.section == sec
  2209.           && adj_h->esym.asym.value > int_rel.r_vaddr)
  2210.         adj_h->root.u.def.value += PCREL16_EXPANSION_ADJUSTMENT;
  2211.     }
  2212.  
  2213.       /* Add an entry to the symbol value adjust list.  This is used
  2214.      by bfd_ecoff_debug_accumulate to adjust the values of
  2215.      internal symbols and FDR's.  */
  2216.       adjust = ((struct ecoff_value_adjust *)
  2217.         bfd_alloc (abfd, sizeof (struct ecoff_value_adjust)));
  2218.       if (adjust == (struct ecoff_value_adjust *) NULL)
  2219.     goto error_return;
  2220.  
  2221.       adjust->start = int_rel.r_vaddr;
  2222.       adjust->end = sec->vma + sec->_raw_size;
  2223.       adjust->adjust = PCREL16_EXPANSION_ADJUSTMENT;
  2224.  
  2225.       adjust->next = ecoff_data (abfd)->debug_info.adjust;
  2226.       ecoff_data (abfd)->debug_info.adjust = adjust;
  2227.     }
  2228.  
  2229.   if (contents != (bfd_byte *) NULL && ! info->keep_memory)
  2230.     free (contents);
  2231.  
  2232.   return true;
  2233.  
  2234.  error_return:
  2235.   if (contents != (bfd_byte *) NULL && ! info->keep_memory)
  2236.     free (contents);
  2237.   return false;
  2238. }
  2239.  
  2240. /* This routine is called from mips_relocate_section when a PC
  2241.    relative reloc must be expanded into the five instruction sequence.
  2242.    It handles all the details of the expansion, including resolving
  2243.    the reloc.  */
  2244.  
  2245. static boolean
  2246. mips_relax_pcrel16 (info, input_bfd, input_section, h, location, address)
  2247.      struct bfd_link_info *info;
  2248.      bfd *input_bfd;
  2249.      asection *input_section;
  2250.      struct ecoff_link_hash_entry *h;
  2251.      bfd_byte *location;
  2252.      bfd_vma address;
  2253. {
  2254.   bfd_vma relocation;
  2255.  
  2256.   /* 0x0411ffff is bgezal $0,. == bal .  */
  2257.   BFD_ASSERT (bfd_get_32 (input_bfd, location) == 0x0411ffff);
  2258.  
  2259.   /* We need to compute the distance between the symbol and the
  2260.      current address plus eight.  */
  2261.   relocation = (h->root.u.def.value
  2262.         + h->root.u.def.section->output_section->vma
  2263.         + h->root.u.def.section->output_offset);
  2264.   relocation -= address + 8;
  2265.  
  2266.   /* If the lower half is negative, increment the upper 16 half.  */
  2267.   if ((relocation & 0x8000) != 0)
  2268.     relocation += 0x10000;
  2269.  
  2270.   bfd_put_32 (input_bfd, 0x04110001, location); /* bal .+8 */
  2271.   bfd_put_32 (input_bfd,
  2272.           0x3c010000 | ((relocation >> 16) & 0xffff), /* lui $at,XX */
  2273.           location + 4);
  2274.   bfd_put_32 (input_bfd,
  2275.           0x24210000 | (relocation & 0xffff), /* addiu $at,$at,XX */
  2276.           location + 8);
  2277.   bfd_put_32 (input_bfd, 0x003f0821, location + 12); /* addu $at,$at,$ra */
  2278.   bfd_put_32 (input_bfd, 0x0020f809, location + 16); /* jalr $at */
  2279.  
  2280.   return true;
  2281. }
  2282.  
  2283. /* Given a .sdata section and a .rel.sdata in-memory section, store
  2284.    relocation information into the .rel.sdata section which can be
  2285.    used at runtime to relocate the section.  This is called by the
  2286.    linker when the --embedded-relocs switch is used.  This is called
  2287.    after the add_symbols entry point has been called for all the
  2288.    objects, and before the final_link entry point is called.  This
  2289.    function presumes that the object was compiled using
  2290.    -membedded-pic.  */
  2291.  
  2292. boolean
  2293. bfd_mips_ecoff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
  2294.      bfd *abfd;
  2295.      struct bfd_link_info *info;
  2296.      asection *datasec;
  2297.      asection *relsec;
  2298.      char **errmsg;
  2299. {
  2300.   struct ecoff_link_hash_entry **sym_hashes;
  2301.   struct ecoff_section_tdata *section_tdata;
  2302.   struct external_reloc *ext_rel;
  2303.   struct external_reloc *ext_rel_end;
  2304.   bfd_byte *p;
  2305.  
  2306.   BFD_ASSERT (! info->relocateable);
  2307.  
  2308.   *errmsg = NULL;
  2309.  
  2310.   if (datasec->reloc_count == 0)
  2311.     return true;
  2312.  
  2313.   sym_hashes = ecoff_data (abfd)->sym_hashes;
  2314.  
  2315.   if (! mips_read_relocs (abfd, datasec))
  2316.     return false;
  2317.  
  2318.   relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 4);
  2319.   if (relsec->contents == NULL)
  2320.     return false;
  2321.  
  2322.   p = relsec->contents;
  2323.  
  2324.   section_tdata = ecoff_section_data (abfd, datasec);
  2325.   ext_rel = (struct external_reloc *) section_tdata->external_relocs;
  2326.   ext_rel_end = ext_rel + datasec->reloc_count;
  2327.   for (; ext_rel < ext_rel_end; ext_rel++, p += 4)
  2328.     {
  2329.       struct internal_reloc int_rel;
  2330.       boolean text_relative;
  2331.  
  2332.       mips_ecoff_swap_reloc_in (abfd, (PTR) ext_rel, &int_rel);
  2333.  
  2334.       /* We are going to write a four byte word into the runtime reloc
  2335.      section.  The word will be the address in the data section
  2336.      which must be relocated.  This must be on a word boundary,
  2337.      which means the lower two bits must be zero.  We use the
  2338.      least significant bit to indicate how the value in the data
  2339.      section must be relocated.  A 0 means that the value is
  2340.      relative to the text section, while a 1 indicates that the
  2341.      value is relative to the data section.  Given that we are
  2342.      assuming the code was compiled using -membedded-pic, there
  2343.      should not be any other possibilities.  */
  2344.  
  2345.       /* We can only relocate REFWORD relocs at run time.  */
  2346.       if (int_rel.r_type != MIPS_R_REFWORD)
  2347.     {
  2348.       *errmsg = "unsupported reloc type";
  2349.       bfd_set_error (bfd_error_bad_value);
  2350.       return false;
  2351.     }
  2352.  
  2353.       if (int_rel.r_extern)
  2354.     {
  2355.       struct ecoff_link_hash_entry *h;
  2356.  
  2357.       h = sym_hashes[int_rel.r_symndx];
  2358.       /* If h is NULL, that means that there is a reloc against an
  2359.          external symbol which we thought was just a debugging
  2360.          symbol.  This should not happen.  */
  2361.       if (h == (struct ecoff_link_hash_entry *) NULL)
  2362.         abort ();
  2363.       if ((h->root.type == bfd_link_hash_defined
  2364.            || h->root.type == bfd_link_hash_defweak)
  2365.           && (h->root.u.def.section->flags & SEC_CODE) != 0)
  2366.         text_relative = true;
  2367.       else
  2368.         text_relative = false;
  2369.     }
  2370.       else
  2371.     {
  2372.       switch (int_rel.r_symndx)
  2373.         {
  2374.         case RELOC_SECTION_TEXT:
  2375.           text_relative = true;
  2376.           break;
  2377.         case RELOC_SECTION_SDATA:
  2378.         case RELOC_SECTION_SBSS:
  2379.         case RELOC_SECTION_LIT8:
  2380.           text_relative = false;
  2381.           break;
  2382.         default:
  2383.           /* No other sections should appear in -membedded-pic
  2384.                  code.  */
  2385.           *errmsg = "reloc against unsupported section";
  2386.           bfd_set_error (bfd_error_bad_value);
  2387.           return false;
  2388.         }
  2389.     }
  2390.  
  2391.       if ((int_rel.r_offset & 3) != 0)
  2392.     {
  2393.       *errmsg = "reloc not properly aligned";
  2394.       bfd_set_error (bfd_error_bad_value);
  2395.       return false;
  2396.     }
  2397.  
  2398.       bfd_put_32 (abfd,
  2399.           (int_rel.r_vaddr - datasec->vma + datasec->output_offset
  2400.            + (text_relative ? 0 : 1)),
  2401.           p);
  2402.     }
  2403.  
  2404.   return true;
  2405. }
  2406.  
  2407. /* This is the ECOFF backend structure.  The backend field of the
  2408.    target vector points to this.  */
  2409.  
  2410. static const struct ecoff_backend_data mips_ecoff_backend_data =
  2411. {
  2412.   /* COFF backend structure.  */
  2413.   {
  2414.     (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */
  2415.     (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
  2416.     (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
  2417.     (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/
  2418.     (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
  2419.     (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
  2420.     (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
  2421.     mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
  2422.     mips_ecoff_swap_scnhdr_out,
  2423.     FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, true, false,
  2424.     mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
  2425.     mips_ecoff_swap_scnhdr_in, NULL,
  2426.     mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
  2427.     _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
  2428.     _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
  2429.     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  2430.   },
  2431.   /* Supported architecture.  */
  2432.   bfd_arch_mips,
  2433.   /* Initial portion of armap string.  */
  2434.   "__________",
  2435.   /* The page boundary used to align sections in a demand-paged
  2436.      executable file.  E.g., 0x1000.  */
  2437.   0x1000,
  2438.   /* True if the .rdata section is part of the text segment, as on the
  2439.      Alpha.  False if .rdata is part of the data segment, as on the
  2440.      MIPS.  */
  2441.   false,
  2442.   /* Bitsize of constructor entries.  */
  2443.   32,
  2444.   /* Reloc to use for constructor entries.  */
  2445.   &mips_howto_table[MIPS_R_REFWORD],
  2446.   {
  2447.     /* Symbol table magic number.  */
  2448.     magicSym,
  2449.     /* Alignment of debugging information.  E.g., 4.  */
  2450.     4,
  2451.     /* Sizes of external symbolic information.  */
  2452.     sizeof (struct hdr_ext),
  2453.     sizeof (struct dnr_ext),
  2454.     sizeof (struct pdr_ext),
  2455.     sizeof (struct sym_ext),
  2456.     sizeof (struct opt_ext),
  2457.     sizeof (struct fdr_ext),
  2458.     sizeof (struct rfd_ext),
  2459.     sizeof (struct ext_ext),
  2460.     /* Functions to swap in external symbolic data.  */
  2461.     ecoff_swap_hdr_in,
  2462.     ecoff_swap_dnr_in,
  2463.     ecoff_swap_pdr_in,
  2464.     ecoff_swap_sym_in,
  2465.     ecoff_swap_opt_in,
  2466.     ecoff_swap_fdr_in,
  2467.     ecoff_swap_rfd_in,
  2468.     ecoff_swap_ext_in,
  2469.     _bfd_ecoff_swap_tir_in,
  2470.     _bfd_ecoff_swap_rndx_in,
  2471.     /* Functions to swap out external symbolic data.  */
  2472.     ecoff_swap_hdr_out,
  2473.     ecoff_swap_dnr_out,
  2474.     ecoff_swap_pdr_out,
  2475.     ecoff_swap_sym_out,
  2476.     ecoff_swap_opt_out,
  2477.     ecoff_swap_fdr_out,
  2478.     ecoff_swap_rfd_out,
  2479.     ecoff_swap_ext_out,
  2480.     _bfd_ecoff_swap_tir_out,
  2481.     _bfd_ecoff_swap_rndx_out,
  2482.     /* Function to read in symbolic data.  */
  2483.     _bfd_ecoff_slurp_symbolic_info
  2484.   },
  2485.   /* External reloc size.  */
  2486.   RELSZ,
  2487.   /* Reloc swapping functions.  */
  2488.   mips_ecoff_swap_reloc_in,
  2489.   mips_ecoff_swap_reloc_out,
  2490.   /* Backend reloc tweaking.  */
  2491.   mips_adjust_reloc_in,
  2492.   mips_adjust_reloc_out,
  2493.   /* Relocate section contents while linking.  */
  2494.   mips_relocate_section,
  2495.   /* Do final adjustments to filehdr and aouthdr.  */
  2496.   NULL,
  2497.   /* Read an element from an archive at a given file position.  */
  2498.   _bfd_get_elt_at_filepos
  2499. };
  2500.  
  2501. /* Looking up a reloc type is MIPS specific.  */
  2502. #define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
  2503.  
  2504. /* Getting relocated section contents is generic.  */
  2505. #define _bfd_ecoff_bfd_get_relocated_section_contents \
  2506.   bfd_generic_get_relocated_section_contents
  2507.  
  2508. /* Handling file windows is generic.  */
  2509. #define _bfd_ecoff_get_section_contents_in_window \
  2510.   _bfd_generic_get_section_contents_in_window
  2511.  
  2512. /* Relaxing sections is MIPS specific.  */
  2513. #define _bfd_ecoff_bfd_relax_section mips_relax_section
  2514.  
  2515. const bfd_target ecoff_little_vec =
  2516. {
  2517.   "ecoff-littlemips",        /* name */
  2518.   bfd_target_ecoff_flavour,
  2519.   BFD_ENDIAN_LITTLE,        /* data byte order is little */
  2520.   BFD_ENDIAN_LITTLE,        /* header byte order is little */
  2521.  
  2522.   (HAS_RELOC | EXEC_P |        /* object flags */
  2523.    HAS_LINENO | HAS_DEBUG |
  2524.    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
  2525.  
  2526.   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
  2527.   0,                /* leading underscore */
  2528.   ' ',                /* ar_pad_char */
  2529.   15,                /* ar_max_namelen */
  2530.   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
  2531.      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
  2532.      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
  2533.   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
  2534.      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
  2535.      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
  2536.  
  2537.   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
  2538.      _bfd_ecoff_archive_p, _bfd_dummy_target},
  2539.   {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
  2540.      _bfd_generic_mkarchive, bfd_false},
  2541.   {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
  2542.      _bfd_write_archive_contents, bfd_false},
  2543.  
  2544.      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
  2545.      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
  2546.      BFD_JUMP_TABLE_CORE (_bfd_nocore),
  2547.      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
  2548.      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
  2549.      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
  2550.      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
  2551.      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
  2552.      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
  2553.  
  2554.   (PTR) &mips_ecoff_backend_data
  2555. };
  2556.  
  2557. const bfd_target ecoff_big_vec =
  2558. {
  2559.   "ecoff-bigmips",        /* name */
  2560.   bfd_target_ecoff_flavour,
  2561.   BFD_ENDIAN_BIG,        /* data byte order is big */
  2562.   BFD_ENDIAN_BIG,        /* header byte order is big */
  2563.  
  2564.   (HAS_RELOC | EXEC_P |        /* object flags */
  2565.    HAS_LINENO | HAS_DEBUG |
  2566.    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
  2567.  
  2568.   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
  2569.   0,                /* leading underscore */
  2570.   ' ',                /* ar_pad_char */
  2571.   15,                /* ar_max_namelen */
  2572.   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
  2573.      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
  2574.      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
  2575.   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
  2576.      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
  2577.      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
  2578.  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
  2579.     _bfd_ecoff_archive_p, _bfd_dummy_target},
  2580.  {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
  2581.     _bfd_generic_mkarchive, bfd_false},
  2582.  {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
  2583.     _bfd_write_archive_contents, bfd_false},
  2584.  
  2585.      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
  2586.      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
  2587.      BFD_JUMP_TABLE_CORE (_bfd_nocore),
  2588.      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
  2589.      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
  2590.      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
  2591.      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
  2592.      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
  2593.      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
  2594.  
  2595.   (PTR) &mips_ecoff_backend_data
  2596. };
  2597.