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 / elf64-mips.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  58KB  |  1,932 lines

  1. /* MIPS-specific support for 64-bit ELF
  2.    Copyright 1996 Free Software Foundation, Inc.
  3.    Ian Lance Taylor, Cygnus Support
  4.  
  5. This file is part of BFD, the Binary File Descriptor library.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  20.  
  21. /* This file supports the 64-bit MIPS ELF ABI.
  22.  
  23.    The MIPS 64-bit ELF ABI uses an unusual reloc format.  This file
  24.    overrides the usual ELF reloc handling, and handles reading and
  25.    writing the relocations here.  */
  26.  
  27. #include "bfd.h"
  28. #include "sysdep.h"
  29. #include "libbfd.h"
  30. #include "bfdlink.h"
  31. #include "genlink.h"
  32. #include "elf-bfd.h"
  33. #include "elf/mips.h"
  34.  
  35. /* Get the ECOFF swapping routines.  The 64-bit ABI is not supposed to
  36.    use ECOFF.  However, we support it anyhow for an easier changeover.  */
  37. #include "coff/sym.h"
  38. #include "coff/symconst.h"
  39. #include "coff/internal.h"
  40. #include "coff/ecoff.h"
  41. /* The 64 bit versions of the mdebug data structures are in alpha.h.  */
  42. #include "coff/alpha.h"
  43. #define ECOFF_64
  44. #include "ecoffswap.h"
  45.  
  46. static void mips_elf64_swap_reloc_in
  47.   PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
  48.        Elf64_Mips_Internal_Rel *));
  49. static void mips_elf64_swap_reloca_in
  50.   PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
  51.        Elf64_Mips_Internal_Rela *));
  52. #if 0
  53. static void mips_elf64_swap_reloc_out
  54.   PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
  55.        Elf64_Mips_External_Rel *));
  56. #endif
  57. static void mips_elf64_swap_reloca_out
  58.   PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
  59.        Elf64_Mips_External_Rela *));
  60. static reloc_howto_type *mips_elf64_reloc_type_lookup
  61.   PARAMS ((bfd *, bfd_reloc_code_real_type));
  62. static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
  63. static boolean mips_elf64_slurp_one_reloc_table
  64.   PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
  65. static boolean mips_elf64_slurp_reloc_table
  66.   PARAMS ((bfd *, asection *, asymbol **));
  67. static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
  68. static boolean mips_elf64_section_from_shdr
  69.   PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
  70. static boolean mips_elf64_section_processing
  71.   PARAMS ((bfd *, Elf_Internal_Shdr *));
  72.  
  73. /* The relocation types.  */
  74.  
  75. enum mips_elf64_reloc_type
  76. {
  77.   R_MIPS_NONE = 0,
  78.   R_MIPS_16 = 1,
  79.   R_MIPS_32 = 2,
  80.   R_MIPS_ADD = 2,
  81.   R_MIPS_REL32 = 3,
  82.   R_MIPS_REL = 3,
  83.   R_MIPS_26 = 4,
  84.   R_MIPS_HI16 = 5,
  85.   R_MIPS_LO16 = 6,
  86.   R_MIPS_GPREL16 = 7,
  87.   R_MIPS_GPREL = 7,
  88.   R_MIPS_LITERAL = 8,
  89.   R_MIPS_GOT16 = 9,
  90.   R_MIPS_GOT = 9,
  91.   R_MIPS_PC16 = 10,
  92.   R_MIPS_CALL16 = 11,
  93.   R_MIPS_CALL = 11,
  94.   R_MIPS_GPREL32 = 12,
  95.   R_MIPS_SHIFT5 = 16,
  96.   R_MIPS_SHIFT6 = 17,
  97.   R_MIPS_64 = 18,
  98.   R_MIPS_GOT_DISP = 19,
  99.   R_MIPS_GOT_PAGE = 20,
  100.   R_MIPS_GOT_OFST = 21,
  101.   R_MIPS_GOT_HI16 = 22,
  102.   R_MIPS_GOT_LO16 = 23,
  103.   R_MIPS_SUB = 24,
  104.   R_MIPS_INSERT_A = 25,
  105.   R_MIPS_INSERT_B = 26,
  106.   R_MIPS_DELETE = 27,
  107.   R_MIPS_HIGHER = 28,
  108.   R_MIPS_HIGHEST = 29,
  109.   R_MIPS_CALL_HI16 = 30,
  110.   R_MIPS_CALL_LO16 = 31,
  111.   R_MIPS_SCN_DISP = 32,
  112.   R_MIPS_REL16 = 33,
  113.   R_MIPS_ADD_IMMEDIATE = 34,
  114.   R_MIPS_PJUMP = 35,
  115.   R_MIPS_RELGOT = 36
  116. };
  117.  
  118. /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
  119.    from smaller values.  Start with zero, widen, *then* decrement.  */
  120. #define MINUS_ONE    (((bfd_vma)0) - 1)
  121.  
  122. /* The relocation table used for SHT_REL sections.  */
  123.  
  124. static reloc_howto_type mips_elf64_howto_table_rel[] =
  125. {
  126.   /* No relocation.  */
  127.   HOWTO (R_MIPS_NONE,        /* type */
  128.      0,            /* rightshift */
  129.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  130.      0,            /* bitsize */
  131.      false,            /* pc_relative */
  132.      0,            /* bitpos */
  133.      complain_overflow_dont, /* complain_on_overflow */
  134.      bfd_elf_generic_reloc,    /* special_function */
  135.      "R_MIPS_NONE",        /* name */
  136.      false,            /* partial_inplace */
  137.      0,            /* src_mask */
  138.      0,            /* dst_mask */
  139.      false),        /* pcrel_offset */
  140.  
  141.   /* 16 bit relocation.  */
  142.   HOWTO (R_MIPS_16,        /* type */
  143.      0,            /* rightshift */
  144.      1,            /* size (0 = byte, 1 = short, 2 = long) */
  145.      16,            /* bitsize */
  146.      false,            /* pc_relative */
  147.      0,            /* bitpos */
  148.      complain_overflow_bitfield, /* complain_on_overflow */
  149.      bfd_elf_generic_reloc,    /* special_function */
  150.      "R_MIPS_16",        /* name */
  151.      true,            /* partial_inplace */
  152.      0xffff,        /* src_mask */
  153.      0xffff,        /* dst_mask */
  154.      false),        /* pcrel_offset */
  155.  
  156.   /* 32 bit relocation.  */
  157.   HOWTO (R_MIPS_32,        /* type */
  158.      0,            /* rightshift */
  159.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  160.      32,            /* bitsize */
  161.      false,            /* pc_relative */
  162.      0,            /* bitpos */
  163.      complain_overflow_bitfield, /* complain_on_overflow */
  164.      bfd_elf_generic_reloc,    /* special_function */
  165.      "R_MIPS_32",        /* name */
  166.      true,            /* partial_inplace */
  167.      0xffffffff,        /* src_mask */
  168.      0xffffffff,        /* dst_mask */
  169.      false),        /* pcrel_offset */
  170.  
  171.   /* 32 bit symbol relative relocation.  */
  172.   HOWTO (R_MIPS_REL32,        /* type */
  173.      0,            /* rightshift */
  174.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  175.      32,            /* bitsize */
  176.      false,            /* pc_relative */
  177.      0,            /* bitpos */
  178.      complain_overflow_bitfield, /* complain_on_overflow */
  179.      bfd_elf_generic_reloc,    /* special_function */
  180.      "R_MIPS_REL32",    /* name */
  181.      true,            /* partial_inplace */
  182.      0xffffffff,        /* src_mask */
  183.      0xffffffff,        /* dst_mask */
  184.      false),        /* pcrel_offset */
  185.  
  186.   /* 26 bit branch address.  */
  187.   HOWTO (R_MIPS_26,        /* type */
  188.      2,            /* rightshift */
  189.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  190.      26,            /* bitsize */
  191.      false,            /* pc_relative */
  192.      0,            /* bitpos */
  193.      complain_overflow_dont, /* complain_on_overflow */
  194.                  /* This needs complex overflow
  195.                    detection, because the upper four
  196.                    bits must match the PC.  */
  197.      bfd_elf_generic_reloc,    /* special_function */
  198.      "R_MIPS_26",        /* name */
  199.      true,            /* partial_inplace */
  200.      0x3ffffff,        /* src_mask */
  201.      0x3ffffff,        /* dst_mask */
  202.      false),        /* pcrel_offset */
  203.  
  204.   /* High 16 bits of symbol value.  */
  205.   HOWTO (R_MIPS_HI16,        /* type */
  206.      0,            /* rightshift */
  207.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  208.      16,            /* bitsize */
  209.      false,            /* pc_relative */
  210.      0,            /* bitpos */
  211.      complain_overflow_dont, /* complain_on_overflow */
  212.      _bfd_mips_elf_hi16_reloc,    /* special_function */
  213.      "R_MIPS_HI16",        /* name */
  214.      true,            /* partial_inplace */
  215.      0xffff,        /* src_mask */
  216.      0xffff,        /* dst_mask */
  217.      false),        /* pcrel_offset */
  218.  
  219.   /* Low 16 bits of symbol value.  */
  220.   HOWTO (R_MIPS_LO16,        /* type */
  221.      0,            /* rightshift */
  222.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  223.      16,            /* bitsize */
  224.      false,            /* pc_relative */
  225.      0,            /* bitpos */
  226.      complain_overflow_dont, /* complain_on_overflow */
  227.      _bfd_mips_elf_lo16_reloc,    /* special_function */
  228.      "R_MIPS_LO16",        /* name */
  229.      true,            /* partial_inplace */
  230.      0xffff,        /* src_mask */
  231.      0xffff,        /* dst_mask */
  232.      false),        /* pcrel_offset */
  233.  
  234.   /* GP relative reference.  */
  235.   HOWTO (R_MIPS_GPREL16,    /* type */
  236.      0,            /* rightshift */
  237.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  238.      16,            /* bitsize */
  239.      false,            /* pc_relative */
  240.      0,            /* bitpos */
  241.      complain_overflow_signed, /* complain_on_overflow */
  242.      _bfd_mips_elf_gprel16_reloc, /* special_function */
  243.      "R_MIPS_GPREL16",    /* name */
  244.      true,            /* partial_inplace */
  245.      0xffff,        /* src_mask */
  246.      0xffff,        /* dst_mask */
  247.      false),        /* pcrel_offset */
  248.  
  249.   /* Reference to literal section.  */
  250.   HOWTO (R_MIPS_LITERAL,    /* type */
  251.      0,            /* rightshift */
  252.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  253.      16,            /* bitsize */
  254.      false,            /* pc_relative */
  255.      0,            /* bitpos */
  256.      complain_overflow_signed, /* complain_on_overflow */
  257.      _bfd_mips_elf_gprel16_reloc, /* special_function */
  258.      "R_MIPS_LITERAL",    /* name */
  259.      true,            /* partial_inplace */
  260.      0xffff,        /* src_mask */
  261.      0xffff,        /* dst_mask */
  262.      false),        /* pcrel_offset */
  263.  
  264.   /* Reference to global offset table.  */
  265.   HOWTO (R_MIPS_GOT16,        /* type */
  266.      0,            /* rightshift */
  267.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  268.      16,            /* bitsize */
  269.      false,            /* pc_relative */
  270.      0,            /* bitpos */
  271.      complain_overflow_signed, /* complain_on_overflow */
  272.      _bfd_mips_elf_got16_reloc,    /* special_function */
  273.      "R_MIPS_GOT16",    /* name */
  274.      false,            /* partial_inplace */
  275.      0,            /* src_mask */
  276.      0xffff,        /* dst_mask */
  277.      false),        /* pcrel_offset */
  278.  
  279.   /* 16 bit PC relative reference.  */
  280.   HOWTO (R_MIPS_PC16,        /* type */
  281.      0,            /* rightshift */
  282.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  283.      16,            /* bitsize */
  284.      true,            /* pc_relative */
  285.      0,            /* bitpos */
  286.      complain_overflow_signed, /* complain_on_overflow */
  287.      bfd_elf_generic_reloc,    /* special_function */
  288.      "R_MIPS_PC16",        /* name */
  289.      true,            /* partial_inplace */
  290.      0xffff,        /* src_mask */
  291.      0xffff,        /* dst_mask */
  292.      false),        /* pcrel_offset */
  293.  
  294.   /* 16 bit call through global offset table.  */
  295.   /* FIXME: This is not handled correctly.  */
  296.   HOWTO (R_MIPS_CALL16,        /* type */
  297.      0,            /* rightshift */
  298.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  299.      16,            /* bitsize */
  300.      false,            /* pc_relative */
  301.      0,            /* bitpos */
  302.      complain_overflow_signed, /* complain_on_overflow */
  303.      bfd_elf_generic_reloc,    /* special_function */
  304.      "R_MIPS_CALL16",    /* name */
  305.      false,            /* partial_inplace */
  306.      0,            /* src_mask */
  307.      0xffff,        /* dst_mask */
  308.      false),        /* pcrel_offset */
  309.  
  310.   /* 32 bit GP relative reference.  */
  311.   HOWTO (R_MIPS_GPREL32,    /* type */
  312.      0,            /* rightshift */
  313.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  314.      32,            /* bitsize */
  315.      false,            /* pc_relative */
  316.      0,            /* bitpos */
  317.      complain_overflow_bitfield, /* complain_on_overflow */
  318.      _bfd_mips_elf_gprel32_reloc, /* special_function */
  319.      "R_MIPS_GPREL32",    /* name */
  320.      true,            /* partial_inplace */
  321.      0xffffffff,        /* src_mask */
  322.      0xffffffff,        /* dst_mask */
  323.      false),        /* pcrel_offset */
  324.  
  325.     { 13 },
  326.     { 14 },
  327.     { 15 },
  328.  
  329.   /* A 5 bit shift field.  */
  330.   HOWTO (R_MIPS_SHIFT5,        /* type */
  331.      0,            /* rightshift */
  332.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  333.      5,            /* bitsize */
  334.      false,            /* pc_relative */
  335.      6,            /* bitpos */
  336.      complain_overflow_bitfield, /* complain_on_overflow */
  337.      bfd_elf_generic_reloc,    /* special_function */
  338.      "R_MIPS_SHIFT5",    /* name */
  339.      true,            /* partial_inplace */
  340.      0x000007c0,        /* src_mask */
  341.      0x000007c0,        /* dst_mask */
  342.      false),        /* pcrel_offset */
  343.  
  344.   /* A 6 bit shift field.  */
  345.   /* FIXME: This is not handled correctly; a special function is
  346.      needed to put the most significant bit in the right place.  */
  347.   HOWTO (R_MIPS_SHIFT6,        /* type */
  348.      0,            /* rightshift */
  349.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  350.      6,            /* bitsize */
  351.      false,            /* pc_relative */
  352.      6,            /* bitpos */
  353.      complain_overflow_bitfield, /* complain_on_overflow */
  354.      bfd_elf_generic_reloc,    /* special_function */
  355.      "R_MIPS_SHIFT6",    /* name */
  356.      true,            /* partial_inplace */
  357.      0x000007c4,        /* src_mask */
  358.      0x000007c4,        /* dst_mask */
  359.      false),        /* pcrel_offset */
  360.  
  361.   /* 64 bit relocation.  */
  362.   HOWTO (R_MIPS_64,        /* type */
  363.      0,            /* rightshift */
  364.      4,            /* size (0 = byte, 1 = short, 2 = long) */
  365.      64,            /* bitsize */
  366.      false,            /* pc_relative */
  367.      0,            /* bitpos */
  368.      complain_overflow_bitfield, /* complain_on_overflow */
  369.      bfd_elf_generic_reloc,    /* special_function */
  370.      "R_MIPS_64",        /* name */
  371.      true,            /* partial_inplace */
  372.      MINUS_ONE,        /* src_mask */
  373.      MINUS_ONE,        /* dst_mask */
  374.      false),        /* pcrel_offset */
  375.  
  376.   /* Displacement in the global offset table.  */
  377.   /* FIXME: Not handled correctly.  */
  378.   HOWTO (R_MIPS_GOT_DISP,    /* type */
  379.      0,            /* rightshift */
  380.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  381.      16,            /* bitsize */
  382.      false,            /* pc_relative */
  383.      0,            /* bitpos */
  384.      complain_overflow_bitfield, /* complain_on_overflow */
  385.      bfd_elf_generic_reloc,    /* special_function */
  386.      "R_MIPS_GOT_DISP",    /* name */
  387.      true,            /* partial_inplace */
  388.      0x0000ffff,        /* src_mask */
  389.      0x0000ffff,        /* dst_mask */
  390.      false),        /* pcrel_offset */
  391.  
  392.   /* Displacement to page pointer in the global offset table.  */
  393.   /* FIXME: Not handled correctly.  */
  394.   HOWTO (R_MIPS_GOT_PAGE,    /* type */
  395.      0,            /* rightshift */
  396.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  397.      16,            /* bitsize */
  398.      false,            /* pc_relative */
  399.      0,            /* bitpos */
  400.      complain_overflow_bitfield, /* complain_on_overflow */
  401.      bfd_elf_generic_reloc,    /* special_function */
  402.      "R_MIPS_GOT_PAGE",    /* name */
  403.      true,            /* partial_inplace */
  404.      0x0000ffff,        /* src_mask */
  405.      0x0000ffff,        /* dst_mask */
  406.      false),        /* pcrel_offset */
  407.  
  408.   /* Offset from page pointer in the global offset table.  */
  409.   /* FIXME: Not handled correctly.  */
  410.   HOWTO (R_MIPS_GOT_OFST,    /* type */
  411.      0,            /* rightshift */
  412.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  413.      16,            /* bitsize */
  414.      false,            /* pc_relative */
  415.      0,            /* bitpos */
  416.      complain_overflow_bitfield, /* complain_on_overflow */
  417.      bfd_elf_generic_reloc,    /* special_function */
  418.      "R_MIPS_GOT_OFST",    /* name */
  419.      true,            /* partial_inplace */
  420.      0x0000ffff,        /* src_mask */
  421.      0x0000ffff,        /* dst_mask */
  422.      false),        /* pcrel_offset */
  423.  
  424.   /* High 16 bits of displacement in global offset table.  */
  425.   /* FIXME: Not handled correctly.  */
  426.   HOWTO (R_MIPS_GOT_HI16,    /* type */
  427.      0,            /* rightshift */
  428.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  429.      16,            /* bitsize */
  430.      false,            /* pc_relative */
  431.      0,            /* bitpos */
  432.      complain_overflow_dont, /* complain_on_overflow */
  433.      bfd_elf_generic_reloc,    /* special_function */
  434.      "R_MIPS_GOT_HI16",    /* name */
  435.      true,            /* partial_inplace */
  436.      0x0000ffff,        /* src_mask */
  437.      0x0000ffff,        /* dst_mask */
  438.      false),        /* pcrel_offset */
  439.  
  440.   /* Low 16 bits of displacement in global offset table.  */
  441.   /* FIXME: Not handled correctly.  */
  442.   HOWTO (R_MIPS_GOT_LO16,    /* type */
  443.      0,            /* rightshift */
  444.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  445.      16,            /* bitsize */
  446.      false,            /* pc_relative */
  447.      0,            /* bitpos */
  448.      complain_overflow_dont, /* complain_on_overflow */
  449.      bfd_elf_generic_reloc,    /* special_function */
  450.      "R_MIPS_GOT_LO16",    /* name */
  451.      true,            /* partial_inplace */
  452.      0x0000ffff,        /* src_mask */
  453.      0x0000ffff,        /* dst_mask */
  454.      false),        /* pcrel_offset */
  455.  
  456.   /* 64 bit substraction.  */
  457.   /* FIXME: Not handled correctly.  */
  458.   HOWTO (R_MIPS_SUB,        /* type */
  459.      0,            /* rightshift */
  460.      4,            /* size (0 = byte, 1 = short, 2 = long) */
  461.      64,            /* bitsize */
  462.      false,            /* pc_relative */
  463.      0,            /* bitpos */
  464.      complain_overflow_bitfield, /* complain_on_overflow */
  465.      bfd_elf_generic_reloc,    /* special_function */
  466.      "R_MIPS_SUB",        /* name */
  467.      true,            /* partial_inplace */
  468.      MINUS_ONE,        /* src_mask */
  469.      MINUS_ONE,        /* dst_mask */
  470.      false),        /* pcrel_offset */
  471.  
  472.   /* Insert the addend as an instruction.  */
  473.   /* FIXME: Not handled correctly.  */
  474.   HOWTO (R_MIPS_INSERT_A,    /* type */
  475.      0,            /* rightshift */
  476.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  477.      0,            /* bitsize */
  478.      false,            /* pc_relative */
  479.      0,            /* bitpos */
  480.      complain_overflow_dont, /* complain_on_overflow */
  481.      bfd_elf_generic_reloc,    /* special_function */
  482.      "R_MIPS_INSERT_A",    /* name */
  483.      false,            /* partial_inplace */
  484.      0,            /* src_mask */
  485.      0,            /* dst_mask */
  486.      false),        /* pcrel_offset */
  487.  
  488.   /* Insert the addend as an instruction, and change all relocations
  489.      to refer to the old instruction at the address.  */
  490.   /* FIXME: Not handled correctly.  */
  491.   HOWTO (R_MIPS_INSERT_B,    /* type */
  492.      0,            /* rightshift */
  493.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  494.      0,            /* bitsize */
  495.      false,            /* pc_relative */
  496.      0,            /* bitpos */
  497.      complain_overflow_dont, /* complain_on_overflow */
  498.      bfd_elf_generic_reloc,    /* special_function */
  499.      "R_MIPS_INSERT_B",    /* name */
  500.      false,            /* partial_inplace */
  501.      0,            /* src_mask */
  502.      0,            /* dst_mask */
  503.      false),        /* pcrel_offset */
  504.  
  505.   /* Delete a 32 bit instruction.  */
  506.   /* FIXME: Not handled correctly.  */
  507.   HOWTO (R_MIPS_DELETE,        /* type */
  508.      0,            /* rightshift */
  509.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  510.      0,            /* bitsize */
  511.      false,            /* pc_relative */
  512.      0,            /* bitpos */
  513.      complain_overflow_dont, /* complain_on_overflow */
  514.      bfd_elf_generic_reloc,    /* special_function */
  515.      "R_MIPS_DELETE",    /* name */
  516.      false,            /* partial_inplace */
  517.      0,            /* src_mask */
  518.      0,            /* dst_mask */
  519.      false),        /* pcrel_offset */
  520.  
  521.   /* Get the higher value of a 64 bit addend.  */
  522.   /* FIXME: Not handled correctly.  */
  523.   HOWTO (R_MIPS_HIGHER,        /* type */
  524.      0,            /* rightshift */
  525.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  526.      16,            /* bitsize */
  527.      false,            /* pc_relative */
  528.      0,            /* bitpos */
  529.      complain_overflow_dont, /* complain_on_overflow */
  530.      bfd_elf_generic_reloc,    /* special_function */
  531.      "R_MIPS_HIGHER",    /* name */
  532.      true,            /* partial_inplace */
  533.      0xffff,        /* src_mask */
  534.      0xffff,        /* dst_mask */
  535.      false),        /* pcrel_offset */
  536.  
  537.   /* Get the highest value of a 64 bit addend.  */
  538.   /* FIXME: Not handled correctly.  */
  539.   HOWTO (R_MIPS_HIGHEST,    /* type */
  540.      0,            /* rightshift */
  541.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  542.      16,            /* bitsize */
  543.      false,            /* pc_relative */
  544.      0,            /* bitpos */
  545.      complain_overflow_dont, /* complain_on_overflow */
  546.      bfd_elf_generic_reloc,    /* special_function */
  547.      "R_MIPS_HIGHEST",    /* name */
  548.      true,            /* partial_inplace */
  549.      0xffff,        /* src_mask */
  550.      0xffff,        /* dst_mask */
  551.      false),        /* pcrel_offset */
  552.  
  553.   /* High 16 bits of displacement in global offset table.  */
  554.   /* FIXME: Not handled correctly.  */
  555.   HOWTO (R_MIPS_CALL_HI16,    /* type */
  556.      0,            /* rightshift */
  557.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  558.      16,            /* bitsize */
  559.      false,            /* pc_relative */
  560.      0,            /* bitpos */
  561.      complain_overflow_dont, /* complain_on_overflow */
  562.      bfd_elf_generic_reloc,    /* special_function */
  563.      "R_MIPS_CALL_HI16",    /* name */
  564.      true,            /* partial_inplace */
  565.      0x0000ffff,        /* src_mask */
  566.      0x0000ffff,        /* dst_mask */
  567.      false),        /* pcrel_offset */
  568.  
  569.   /* Low 16 bits of displacement in global offset table.  */
  570.   /* FIXME: Not handled correctly.  */
  571.   HOWTO (R_MIPS_CALL_LO16,    /* type */
  572.      0,            /* rightshift */
  573.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  574.      16,            /* bitsize */
  575.      false,            /* pc_relative */
  576.      0,            /* bitpos */
  577.      complain_overflow_dont, /* complain_on_overflow */
  578.      bfd_elf_generic_reloc,    /* special_function */
  579.      "R_MIPS_CALL_LO16",    /* name */
  580.      true,            /* partial_inplace */
  581.      0x0000ffff,        /* src_mask */
  582.      0x0000ffff,        /* dst_mask */
  583.      false),        /* pcrel_offset */
  584.  
  585.   /* I'm not sure what the remaining relocs are, but they are defined
  586.      on Irix 6.  */
  587.  
  588.   HOWTO (R_MIPS_SCN_DISP,    /* type */
  589.      0,            /* rightshift */
  590.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  591.      0,            /* bitsize */
  592.      false,            /* pc_relative */
  593.      0,            /* bitpos */
  594.      complain_overflow_dont, /* complain_on_overflow */
  595.      bfd_elf_generic_reloc,    /* special_function */
  596.      "R_MIPS_SCN_DISP",    /* name */
  597.      false,            /* partial_inplace */
  598.      0,            /* src_mask */
  599.      0,            /* dst_mask */
  600.      false),        /* pcrel_offset */
  601.  
  602.   HOWTO (R_MIPS_REL16,        /* type */
  603.      0,            /* rightshift */
  604.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  605.      0,            /* bitsize */
  606.      false,            /* pc_relative */
  607.      0,            /* bitpos */
  608.      complain_overflow_dont, /* complain_on_overflow */
  609.      bfd_elf_generic_reloc,    /* special_function */
  610.      "R_MIPS_REL16",    /* name */
  611.      false,            /* partial_inplace */
  612.      0,            /* src_mask */
  613.      0,            /* dst_mask */
  614.      false),        /* pcrel_offset */
  615.  
  616.   HOWTO (R_MIPS_ADD_IMMEDIATE,    /* type */
  617.      0,            /* rightshift */
  618.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  619.      0,            /* bitsize */
  620.      false,            /* pc_relative */
  621.      0,            /* bitpos */
  622.      complain_overflow_dont, /* complain_on_overflow */
  623.      bfd_elf_generic_reloc,    /* special_function */
  624.      "R_MIPS_ADD_IMMEDIATE", /* name */
  625.      false,            /* partial_inplace */
  626.      0,            /* src_mask */
  627.      0,            /* dst_mask */
  628.      false),        /* pcrel_offset */
  629.  
  630.   HOWTO (R_MIPS_PJUMP,        /* type */
  631.      0,            /* rightshift */
  632.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  633.      0,            /* bitsize */
  634.      false,            /* pc_relative */
  635.      0,            /* bitpos */
  636.      complain_overflow_dont, /* complain_on_overflow */
  637.      bfd_elf_generic_reloc,    /* special_function */
  638.      "R_MIPS_PJUMP",    /* name */
  639.      false,            /* partial_inplace */
  640.      0,            /* src_mask */
  641.      0,            /* dst_mask */
  642.      false),        /* pcrel_offset */
  643.  
  644.   HOWTO (R_MIPS_RELGOT,        /* type */
  645.      0,            /* rightshift */
  646.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  647.      0,            /* bitsize */
  648.      false,            /* pc_relative */
  649.      0,            /* bitpos */
  650.      complain_overflow_dont, /* complain_on_overflow */
  651.      bfd_elf_generic_reloc,    /* special_function */
  652.      "R_MIPS_RELGOT",    /* name */
  653.      false,            /* partial_inplace */
  654.      0,            /* src_mask */
  655.      0,            /* dst_mask */
  656.      false)            /* pcrel_offset */
  657. };
  658.  
  659. /* The relocation table used for SHT_RELA sections.  */
  660.  
  661. static reloc_howto_type mips_elf64_howto_table_rela[] =
  662. {
  663.   /* No relocation.  */
  664.   HOWTO (R_MIPS_NONE,        /* type */
  665.      0,            /* rightshift */
  666.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  667.      0,            /* bitsize */
  668.      false,            /* pc_relative */
  669.      0,            /* bitpos */
  670.      complain_overflow_dont, /* complain_on_overflow */
  671.      bfd_elf_generic_reloc,    /* special_function */
  672.      "R_MIPS_NONE",        /* name */
  673.      false,            /* partial_inplace */
  674.      0,            /* src_mask */
  675.      0,            /* dst_mask */
  676.      false),        /* pcrel_offset */
  677.  
  678.   /* 16 bit relocation.  */
  679.   HOWTO (R_MIPS_16,        /* type */
  680.      0,            /* rightshift */
  681.      1,            /* size (0 = byte, 1 = short, 2 = long) */
  682.      16,            /* bitsize */
  683.      false,            /* pc_relative */
  684.      0,            /* bitpos */
  685.      complain_overflow_bitfield, /* complain_on_overflow */
  686.      bfd_elf_generic_reloc,    /* special_function */
  687.      "R_MIPS_16",        /* name */
  688.      true,            /* partial_inplace */
  689.      0,            /* src_mask */
  690.      0xffff,        /* dst_mask */
  691.      false),        /* pcrel_offset */
  692.  
  693.   /* 32 bit relocation.  */
  694.   HOWTO (R_MIPS_32,        /* type */
  695.      0,            /* rightshift */
  696.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  697.      32,            /* bitsize */
  698.      false,            /* pc_relative */
  699.      0,            /* bitpos */
  700.      complain_overflow_bitfield, /* complain_on_overflow */
  701.      bfd_elf_generic_reloc,    /* special_function */
  702.      "R_MIPS_32",        /* name */
  703.      true,            /* partial_inplace */
  704.      0,            /* src_mask */
  705.      0xffffffff,        /* dst_mask */
  706.      false),        /* pcrel_offset */
  707.  
  708.   /* 32 bit symbol relative relocation.  */
  709.   HOWTO (R_MIPS_REL32,        /* type */
  710.      0,            /* rightshift */
  711.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  712.      32,            /* bitsize */
  713.      false,            /* pc_relative */
  714.      0,            /* bitpos */
  715.      complain_overflow_bitfield, /* complain_on_overflow */
  716.      bfd_elf_generic_reloc,    /* special_function */
  717.      "R_MIPS_REL32",    /* name */
  718.      true,            /* partial_inplace */
  719.      0,            /* src_mask */
  720.      0xffffffff,        /* dst_mask */
  721.      false),        /* pcrel_offset */
  722.  
  723.   /* 26 bit branch address.  */
  724.   HOWTO (R_MIPS_26,        /* type */
  725.      2,            /* rightshift */
  726.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  727.      26,            /* bitsize */
  728.      false,            /* pc_relative */
  729.      0,            /* bitpos */
  730.      complain_overflow_dont, /* complain_on_overflow */
  731.                  /* This needs complex overflow
  732.                    detection, because the upper four
  733.                    bits must match the PC.  */
  734.      bfd_elf_generic_reloc,    /* special_function */
  735.      "R_MIPS_26",        /* name */
  736.      true,            /* partial_inplace */
  737.      0,            /* src_mask */
  738.      0x3ffffff,        /* dst_mask */
  739.      false),        /* pcrel_offset */
  740.  
  741.   /* High 16 bits of symbol value.  */
  742.   HOWTO (R_MIPS_HI16,        /* type */
  743.      0,            /* rightshift */
  744.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  745.      16,            /* bitsize */
  746.      false,            /* pc_relative */
  747.      0,            /* bitpos */
  748.      complain_overflow_dont, /* complain_on_overflow */
  749.      bfd_elf_generic_reloc,    /* special_function */
  750.      "R_MIPS_HI16",        /* name */
  751.      true,            /* partial_inplace */
  752.      0,            /* src_mask */
  753.      0xffff,        /* dst_mask */
  754.      false),        /* pcrel_offset */
  755.  
  756.   /* Low 16 bits of symbol value.  */
  757.   HOWTO (R_MIPS_LO16,        /* type */
  758.      0,            /* rightshift */
  759.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  760.      16,            /* bitsize */
  761.      false,            /* pc_relative */
  762.      0,            /* bitpos */
  763.      complain_overflow_dont, /* complain_on_overflow */
  764.      bfd_elf_generic_reloc,    /* special_function */
  765.      "R_MIPS_LO16",        /* name */
  766.      true,            /* partial_inplace */
  767.      0,            /* src_mask */
  768.      0xffff,        /* dst_mask */
  769.      false),        /* pcrel_offset */
  770.  
  771.   /* GP relative reference.  */
  772.   HOWTO (R_MIPS_GPREL16,    /* type */
  773.      0,            /* rightshift */
  774.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  775.      16,            /* bitsize */
  776.      false,            /* pc_relative */
  777.      0,            /* bitpos */
  778.      complain_overflow_signed, /* complain_on_overflow */
  779.      _bfd_mips_elf_gprel16_reloc, /* special_function */
  780.      "R_MIPS_GPREL16",    /* name */
  781.      true,            /* partial_inplace */
  782.      0,            /* src_mask */
  783.      0xffff,        /* dst_mask */
  784.      false),        /* pcrel_offset */
  785.  
  786.   /* Reference to literal section.  */
  787.   HOWTO (R_MIPS_LITERAL,    /* type */
  788.      0,            /* rightshift */
  789.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  790.      16,            /* bitsize */
  791.      false,            /* pc_relative */
  792.      0,            /* bitpos */
  793.      complain_overflow_signed, /* complain_on_overflow */
  794.      _bfd_mips_elf_gprel16_reloc, /* special_function */
  795.      "R_MIPS_LITERAL",    /* name */
  796.      true,            /* partial_inplace */
  797.      0,            /* src_mask */
  798.      0xffff,        /* dst_mask */
  799.      false),        /* pcrel_offset */
  800.  
  801.   /* Reference to global offset table.  */
  802.   /* FIXME: This is not handled correctly.  */
  803.   HOWTO (R_MIPS_GOT16,        /* type */
  804.      0,            /* rightshift */
  805.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  806.      16,            /* bitsize */
  807.      false,            /* pc_relative */
  808.      0,            /* bitpos */
  809.      complain_overflow_signed, /* complain_on_overflow */
  810.      bfd_elf_generic_reloc,    /* special_function */
  811.      "R_MIPS_GOT16",    /* name */
  812.      false,            /* partial_inplace */
  813.      0,            /* src_mask */
  814.      0xffff,        /* dst_mask */
  815.      false),        /* pcrel_offset */
  816.  
  817.   /* 16 bit PC relative reference.  */
  818.   HOWTO (R_MIPS_PC16,        /* type */
  819.      0,            /* rightshift */
  820.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  821.      16,            /* bitsize */
  822.      true,            /* pc_relative */
  823.      0,            /* bitpos */
  824.      complain_overflow_signed, /* complain_on_overflow */
  825.      bfd_elf_generic_reloc,    /* special_function */
  826.      "R_MIPS_PC16",        /* name */
  827.      true,            /* partial_inplace */
  828.      0,            /* src_mask */
  829.      0xffff,        /* dst_mask */
  830.      false),        /* pcrel_offset */
  831.  
  832.   /* 16 bit call through global offset table.  */
  833.   /* FIXME: This is not handled correctly.  */
  834.   HOWTO (R_MIPS_CALL16,        /* type */
  835.      0,            /* rightshift */
  836.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  837.      16,            /* bitsize */
  838.      false,            /* pc_relative */
  839.      0,            /* bitpos */
  840.      complain_overflow_signed, /* complain_on_overflow */
  841.      bfd_elf_generic_reloc,    /* special_function */
  842.      "R_MIPS_CALL16",    /* name */
  843.      false,            /* partial_inplace */
  844.      0,            /* src_mask */
  845.      0xffff,        /* dst_mask */
  846.      false),        /* pcrel_offset */
  847.  
  848.   /* 32 bit GP relative reference.  */
  849.   HOWTO (R_MIPS_GPREL32,    /* type */
  850.      0,            /* rightshift */
  851.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  852.      32,            /* bitsize */
  853.      false,            /* pc_relative */
  854.      0,            /* bitpos */
  855.      complain_overflow_bitfield, /* complain_on_overflow */
  856.      _bfd_mips_elf_gprel32_reloc, /* special_function */
  857.      "R_MIPS_GPREL32",    /* name */
  858.      true,            /* partial_inplace */
  859.      0,            /* src_mask */
  860.      0xffffffff,        /* dst_mask */
  861.      false),        /* pcrel_offset */
  862.  
  863.     { 13 },
  864.     { 14 },
  865.     { 15 },
  866.  
  867.   /* A 5 bit shift field.  */
  868.   HOWTO (R_MIPS_SHIFT5,        /* type */
  869.      0,            /* rightshift */
  870.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  871.      5,            /* bitsize */
  872.      false,            /* pc_relative */
  873.      6,            /* bitpos */
  874.      complain_overflow_bitfield, /* complain_on_overflow */
  875.      bfd_elf_generic_reloc,    /* special_function */
  876.      "R_MIPS_SHIFT5",    /* name */
  877.      true,            /* partial_inplace */
  878.      0,            /* src_mask */
  879.      0x000007c0,        /* dst_mask */
  880.      false),        /* pcrel_offset */
  881.  
  882.   /* A 6 bit shift field.  */
  883.   /* FIXME: This is not handled correctly; a special function is
  884.      needed to put the most significant bit in the right place.  */
  885.   HOWTO (R_MIPS_SHIFT6,        /* type */
  886.      0,            /* rightshift */
  887.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  888.      6,            /* bitsize */
  889.      false,            /* pc_relative */
  890.      6,            /* bitpos */
  891.      complain_overflow_bitfield, /* complain_on_overflow */
  892.      bfd_elf_generic_reloc,    /* special_function */
  893.      "R_MIPS_SHIFT6",    /* name */
  894.      true,            /* partial_inplace */
  895.      0,            /* src_mask */
  896.      0x000007c4,        /* dst_mask */
  897.      false),        /* pcrel_offset */
  898.  
  899.   /* 64 bit relocation.  */
  900.   HOWTO (R_MIPS_64,        /* type */
  901.      0,            /* rightshift */
  902.      4,            /* size (0 = byte, 1 = short, 2 = long) */
  903.      64,            /* bitsize */
  904.      false,            /* pc_relative */
  905.      0,            /* bitpos */
  906.      complain_overflow_bitfield, /* complain_on_overflow */
  907.      bfd_elf_generic_reloc,    /* special_function */
  908.      "R_MIPS_64",        /* name */
  909.      true,            /* partial_inplace */
  910.      0,            /* src_mask */
  911.      MINUS_ONE,        /* dst_mask */
  912.      false),        /* pcrel_offset */
  913.  
  914.   /* Displacement in the global offset table.  */
  915.   /* FIXME: Not handled correctly.  */
  916.   HOWTO (R_MIPS_GOT_DISP,    /* type */
  917.      0,            /* rightshift */
  918.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  919.      16,            /* bitsize */
  920.      false,            /* pc_relative */
  921.      0,            /* bitpos */
  922.      complain_overflow_bitfield, /* complain_on_overflow */
  923.      bfd_elf_generic_reloc,    /* special_function */
  924.      "R_MIPS_GOT_DISP",    /* name */
  925.      true,            /* partial_inplace */
  926.      0,            /* src_mask */
  927.      0x0000ffff,        /* dst_mask */
  928.      false),        /* pcrel_offset */
  929.  
  930.   /* Displacement to page pointer in the global offset table.  */
  931.   /* FIXME: Not handled correctly.  */
  932.   HOWTO (R_MIPS_GOT_PAGE,    /* type */
  933.      0,            /* rightshift */
  934.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  935.      16,            /* bitsize */
  936.      false,            /* pc_relative */
  937.      0,            /* bitpos */
  938.      complain_overflow_bitfield, /* complain_on_overflow */
  939.      bfd_elf_generic_reloc,    /* special_function */
  940.      "R_MIPS_GOT_PAGE",    /* name */
  941.      true,            /* partial_inplace */
  942.      0,            /* src_mask */
  943.      0x0000ffff,        /* dst_mask */
  944.      false),        /* pcrel_offset */
  945.  
  946.   /* Offset from page pointer in the global offset table.  */
  947.   /* FIXME: Not handled correctly.  */
  948.   HOWTO (R_MIPS_GOT_OFST,    /* type */
  949.      0,            /* rightshift */
  950.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  951.      16,            /* bitsize */
  952.      false,            /* pc_relative */
  953.      0,            /* bitpos */
  954.      complain_overflow_bitfield, /* complain_on_overflow */
  955.      bfd_elf_generic_reloc,    /* special_function */
  956.      "R_MIPS_GOT_OFST",    /* name */
  957.      true,            /* partial_inplace */
  958.      0,            /* src_mask */
  959.      0x0000ffff,        /* dst_mask */
  960.      false),        /* pcrel_offset */
  961.  
  962.   /* High 16 bits of displacement in global offset table.  */
  963.   /* FIXME: Not handled correctly.  */
  964.   HOWTO (R_MIPS_GOT_HI16,    /* type */
  965.      0,            /* rightshift */
  966.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  967.      16,            /* bitsize */
  968.      false,            /* pc_relative */
  969.      0,            /* bitpos */
  970.      complain_overflow_dont, /* complain_on_overflow */
  971.      bfd_elf_generic_reloc,    /* special_function */
  972.      "R_MIPS_GOT_HI16",    /* name */
  973.      true,            /* partial_inplace */
  974.      0,            /* src_mask */
  975.      0x0000ffff,        /* dst_mask */
  976.      false),        /* pcrel_offset */
  977.  
  978.   /* Low 16 bits of displacement in global offset table.  */
  979.   /* FIXME: Not handled correctly.  */
  980.   HOWTO (R_MIPS_GOT_LO16,    /* type */
  981.      0,            /* rightshift */
  982.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  983.      16,            /* bitsize */
  984.      false,            /* pc_relative */
  985.      0,            /* bitpos */
  986.      complain_overflow_dont, /* complain_on_overflow */
  987.      bfd_elf_generic_reloc,    /* special_function */
  988.      "R_MIPS_GOT_LO16",    /* name */
  989.      true,            /* partial_inplace */
  990.      0,            /* src_mask */
  991.      0x0000ffff,        /* dst_mask */
  992.      false),        /* pcrel_offset */
  993.  
  994.   /* 64 bit substraction.  */
  995.   /* FIXME: Not handled correctly.  */
  996.   HOWTO (R_MIPS_SUB,        /* type */
  997.      0,            /* rightshift */
  998.      4,            /* size (0 = byte, 1 = short, 2 = long) */
  999.      64,            /* bitsize */
  1000.      false,            /* pc_relative */
  1001.      0,            /* bitpos */
  1002.      complain_overflow_bitfield, /* complain_on_overflow */
  1003.      bfd_elf_generic_reloc,    /* special_function */
  1004.      "R_MIPS_SUB",        /* name */
  1005.      true,            /* partial_inplace */
  1006.      0,            /* src_mask */
  1007.      MINUS_ONE,        /* dst_mask */
  1008.      false),        /* pcrel_offset */
  1009.  
  1010.   /* Insert the addend as an instruction.  */
  1011.   /* FIXME: Not handled correctly.  */
  1012.   HOWTO (R_MIPS_INSERT_A,    /* type */
  1013.      0,            /* rightshift */
  1014.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  1015.      0,            /* bitsize */
  1016.      false,            /* pc_relative */
  1017.      0,            /* bitpos */
  1018.      complain_overflow_dont, /* complain_on_overflow */
  1019.      bfd_elf_generic_reloc,    /* special_function */
  1020.      "R_MIPS_INSERT_A",    /* name */
  1021.      false,            /* partial_inplace */
  1022.      0,            /* src_mask */
  1023.      0,            /* dst_mask */
  1024.      false),        /* pcrel_offset */
  1025.  
  1026.   /* Insert the addend as an instruction, and change all relocations
  1027.      to refer to the old instruction at the address.  */
  1028.   /* FIXME: Not handled correctly.  */
  1029.   HOWTO (R_MIPS_INSERT_B,    /* type */
  1030.      0,            /* rightshift */
  1031.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  1032.      0,            /* bitsize */
  1033.      false,            /* pc_relative */
  1034.      0,            /* bitpos */
  1035.      complain_overflow_dont, /* complain_on_overflow */
  1036.      bfd_elf_generic_reloc,    /* special_function */
  1037.      "R_MIPS_INSERT_B",    /* name */
  1038.      false,            /* partial_inplace */
  1039.      0,            /* src_mask */
  1040.      0,            /* dst_mask */
  1041.      false),        /* pcrel_offset */
  1042.  
  1043.   /* Delete a 32 bit instruction.  */
  1044.   /* FIXME: Not handled correctly.  */
  1045.   HOWTO (R_MIPS_DELETE,        /* type */
  1046.      0,            /* rightshift */
  1047.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  1048.      0,            /* bitsize */
  1049.      false,            /* pc_relative */
  1050.      0,            /* bitpos */
  1051.      complain_overflow_dont, /* complain_on_overflow */
  1052.      bfd_elf_generic_reloc,    /* special_function */
  1053.      "R_MIPS_DELETE",    /* name */
  1054.      false,            /* partial_inplace */
  1055.      0,            /* src_mask */
  1056.      0,            /* dst_mask */
  1057.      false),        /* pcrel_offset */
  1058.  
  1059.   /* Get the higher value of a 64 bit addend.  */
  1060.   /* FIXME: Not handled correctly.  */
  1061.   HOWTO (R_MIPS_HIGHER,        /* type */
  1062.      0,            /* rightshift */
  1063.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  1064.      16,            /* bitsize */
  1065.      false,            /* pc_relative */
  1066.      0,            /* bitpos */
  1067.      complain_overflow_dont, /* complain_on_overflow */
  1068.      bfd_elf_generic_reloc,    /* special_function */
  1069.      "R_MIPS_HIGHER",    /* name */
  1070.      true,            /* partial_inplace */
  1071.      0,            /* src_mask */
  1072.      0xffff,        /* dst_mask */
  1073.      false),        /* pcrel_offset */
  1074.  
  1075.   /* Get the highest value of a 64 bit addend.  */
  1076.   /* FIXME: Not handled correctly.  */
  1077.   HOWTO (R_MIPS_HIGHEST,    /* type */
  1078.      0,            /* rightshift */
  1079.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  1080.      16,            /* bitsize */
  1081.      false,            /* pc_relative */
  1082.      0,            /* bitpos */
  1083.      complain_overflow_dont, /* complain_on_overflow */
  1084.      bfd_elf_generic_reloc,    /* special_function */
  1085.      "R_MIPS_HIGHEST",    /* name */
  1086.      true,            /* partial_inplace */
  1087.      0,            /* src_mask */
  1088.      0xffff,        /* dst_mask */
  1089.      false),        /* pcrel_offset */
  1090.  
  1091.   /* High 16 bits of displacement in global offset table.  */
  1092.   /* FIXME: Not handled correctly.  */
  1093.   HOWTO (R_MIPS_CALL_HI16,    /* type */
  1094.      0,            /* rightshift */
  1095.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  1096.      16,            /* bitsize */
  1097.      false,            /* pc_relative */
  1098.      0,            /* bitpos */
  1099.      complain_overflow_dont, /* complain_on_overflow */
  1100.      bfd_elf_generic_reloc,    /* special_function */
  1101.      "R_MIPS_CALL_HI16",    /* name */
  1102.      true,            /* partial_inplace */
  1103.      0,            /* src_mask */
  1104.      0x0000ffff,        /* dst_mask */
  1105.      false),        /* pcrel_offset */
  1106.  
  1107.   /* Low 16 bits of displacement in global offset table.  */
  1108.   /* FIXME: Not handled correctly.  */
  1109.   HOWTO (R_MIPS_CALL_LO16,    /* type */
  1110.      0,            /* rightshift */
  1111.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  1112.      16,            /* bitsize */
  1113.      false,            /* pc_relative */
  1114.      0,            /* bitpos */
  1115.      complain_overflow_dont, /* complain_on_overflow */
  1116.      bfd_elf_generic_reloc,    /* special_function */
  1117.      "R_MIPS_CALL_LO16",    /* name */
  1118.      true,            /* partial_inplace */
  1119.      0,            /* src_mask */
  1120.      0x0000ffff,        /* dst_mask */
  1121.      false),        /* pcrel_offset */
  1122.  
  1123.   /* I'm not sure what the remaining relocs are, but they are defined
  1124.      on Irix 6.  */
  1125.  
  1126.   HOWTO (R_MIPS_SCN_DISP,    /* type */
  1127.      0,            /* rightshift */
  1128.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  1129.      0,            /* bitsize */
  1130.      false,            /* pc_relative */
  1131.      0,            /* bitpos */
  1132.      complain_overflow_dont, /* complain_on_overflow */
  1133.      bfd_elf_generic_reloc,    /* special_function */
  1134.      "R_MIPS_SCN_DISP",    /* name */
  1135.      false,            /* partial_inplace */
  1136.      0,            /* src_mask */
  1137.      0,            /* dst_mask */
  1138.      false),        /* pcrel_offset */
  1139.  
  1140.   HOWTO (R_MIPS_REL16,        /* type */
  1141.      0,            /* rightshift */
  1142.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  1143.      0,            /* bitsize */
  1144.      false,            /* pc_relative */
  1145.      0,            /* bitpos */
  1146.      complain_overflow_dont, /* complain_on_overflow */
  1147.      bfd_elf_generic_reloc,    /* special_function */
  1148.      "R_MIPS_REL16",    /* name */
  1149.      false,            /* partial_inplace */
  1150.      0,            /* src_mask */
  1151.      0,            /* dst_mask */
  1152.      false),        /* pcrel_offset */
  1153.  
  1154.   HOWTO (R_MIPS_ADD_IMMEDIATE,    /* type */
  1155.      0,            /* rightshift */
  1156.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  1157.      0,            /* bitsize */
  1158.      false,            /* pc_relative */
  1159.      0,            /* bitpos */
  1160.      complain_overflow_dont, /* complain_on_overflow */
  1161.      bfd_elf_generic_reloc,    /* special_function */
  1162.      "R_MIPS_ADD_IMMEDIATE", /* name */
  1163.      false,            /* partial_inplace */
  1164.      0,            /* src_mask */
  1165.      0,            /* dst_mask */
  1166.      false),        /* pcrel_offset */
  1167.  
  1168.   HOWTO (R_MIPS_PJUMP,        /* type */
  1169.      0,            /* rightshift */
  1170.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  1171.      0,            /* bitsize */
  1172.      false,            /* pc_relative */
  1173.      0,            /* bitpos */
  1174.      complain_overflow_dont, /* complain_on_overflow */
  1175.      bfd_elf_generic_reloc,    /* special_function */
  1176.      "R_MIPS_PJUMP",    /* name */
  1177.      false,            /* partial_inplace */
  1178.      0,            /* src_mask */
  1179.      0,            /* dst_mask */
  1180.      false),        /* pcrel_offset */
  1181.  
  1182.   HOWTO (R_MIPS_RELGOT,        /* type */
  1183.      0,            /* rightshift */
  1184.      0,            /* size (0 = byte, 1 = short, 2 = long) */
  1185.      0,            /* bitsize */
  1186.      false,            /* pc_relative */
  1187.      0,            /* bitpos */
  1188.      complain_overflow_dont, /* complain_on_overflow */
  1189.      bfd_elf_generic_reloc,    /* special_function */
  1190.      "R_MIPS_RELGOT",    /* name */
  1191.      false,            /* partial_inplace */
  1192.      0,            /* src_mask */
  1193.      0,            /* dst_mask */
  1194.      false)            /* pcrel_offset */
  1195. };
  1196.  
  1197. /* Swap in a MIPS 64-bit Rel reloc.  */
  1198.  
  1199. static void
  1200. mips_elf64_swap_reloc_in (abfd, src, dst)
  1201.      bfd *abfd;
  1202.      const Elf64_Mips_External_Rel *src;
  1203.      Elf64_Mips_Internal_Rel *dst;
  1204. {
  1205.   dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
  1206.   dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
  1207.   dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
  1208.   dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
  1209.   dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
  1210.   dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
  1211. }
  1212.  
  1213. /* Swap in a MIPS 64-bit Rela reloc.  */
  1214.  
  1215. static void
  1216. mips_elf64_swap_reloca_in (abfd, src, dst)
  1217.      bfd *abfd;
  1218.      const Elf64_Mips_External_Rela *src;
  1219.      Elf64_Mips_Internal_Rela *dst;
  1220. {
  1221.   dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
  1222.   dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
  1223.   dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
  1224.   dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
  1225.   dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
  1226.   dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
  1227.   dst->r_addend = bfd_h_get_64 (abfd, (bfd_byte *) src->r_addend);
  1228. }
  1229.  
  1230. #if 0
  1231.  
  1232. /* This is not currently used.  */
  1233.  
  1234. /* Swap out a MIPS 64-bit Rel reloc.  */
  1235.  
  1236. static void
  1237. mips_elf64_swap_reloc_out (abfd, src, dst)
  1238.      bfd *abfd;
  1239.      const Elf64_Mips_Internal_Rel *src;
  1240.      Elf64_Mips_External_Rel *dst;
  1241. {
  1242.   bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
  1243.   bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
  1244.   bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
  1245.   bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
  1246.   bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
  1247.   bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
  1248. }
  1249.  
  1250. #endif /* 0 */
  1251.  
  1252. /* Swap out a MIPS 64-bit Rela reloc.  */
  1253.  
  1254. static void
  1255. mips_elf64_swap_reloca_out (abfd, src, dst)
  1256.      bfd *abfd;
  1257.      const Elf64_Mips_Internal_Rela *src;
  1258.      Elf64_Mips_External_Rela *dst;
  1259. {
  1260.   bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
  1261.   bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
  1262.   bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
  1263.   bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
  1264.   bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
  1265.   bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
  1266.   bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
  1267. }
  1268.  
  1269. /* A mapping from BFD reloc types to MIPS ELF reloc types.  */
  1270.  
  1271. struct elf_reloc_map
  1272. {
  1273.   bfd_reloc_code_real_type bfd_reloc_val;
  1274.   enum mips_elf64_reloc_type elf_reloc_val;
  1275. };
  1276.  
  1277. static CONST struct elf_reloc_map mips_reloc_map[] =
  1278. {
  1279.   { BFD_RELOC_NONE, R_MIPS_NONE, },
  1280.   { BFD_RELOC_16, R_MIPS_16 },
  1281.   { BFD_RELOC_32, R_MIPS_32 },
  1282.   { BFD_RELOC_64, R_MIPS_64 },
  1283.   { BFD_RELOC_CTOR, R_MIPS_64 },
  1284.   { BFD_RELOC_32_PCREL, R_MIPS_REL32 },
  1285.   { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
  1286.   { BFD_RELOC_HI16_S, R_MIPS_HI16 },
  1287.   { BFD_RELOC_LO16, R_MIPS_LO16 },
  1288.   { BFD_RELOC_MIPS_GPREL, R_MIPS_GPREL16 },
  1289.   { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
  1290.   { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
  1291.   { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
  1292.   { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
  1293.   { BFD_RELOC_MIPS_GPREL32, R_MIPS_GPREL32 },
  1294.   { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
  1295.   { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
  1296.   { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
  1297.   { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 }
  1298. };
  1299.  
  1300. /* Given a BFD reloc type, return a howto structure.  */
  1301.  
  1302. static reloc_howto_type *
  1303. mips_elf64_reloc_type_lookup (abfd, code)
  1304.      bfd *abfd;
  1305.      bfd_reloc_code_real_type code;
  1306. {
  1307.   unsigned int i;
  1308.  
  1309.   for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
  1310.     {
  1311.       if (mips_reloc_map[i].bfd_reloc_val == code)
  1312.     {
  1313.       int v;
  1314.  
  1315.       v = (int) mips_reloc_map[i].elf_reloc_val;
  1316.       return &mips_elf64_howto_table_rel[v];
  1317.     }
  1318.     }
  1319.  
  1320.   return NULL;
  1321. }
  1322.  
  1323. /* Since each entry in an SHT_REL or SHT_RELA section can represent up
  1324.    to three relocs, we must tell the user to allocate more space.  */
  1325.  
  1326. static long
  1327. mips_elf64_get_reloc_upper_bound (abfd, sec)
  1328.      bfd *abfd;
  1329.      asection *sec;
  1330. {
  1331.   return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
  1332. }
  1333.  
  1334. /* Read the relocations from one reloc section.  */
  1335.  
  1336. static boolean
  1337. mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
  1338.      bfd *abfd;
  1339.      asection *asect;
  1340.      asymbol **symbols;
  1341.      const Elf_Internal_Shdr *rel_hdr;
  1342. {
  1343.   PTR allocated = NULL;
  1344.   bfd_byte *native_relocs;
  1345.   arelent *relents;
  1346.   arelent *relent;
  1347.   unsigned int count;
  1348.   unsigned int i;
  1349.   int entsize;
  1350.   reloc_howto_type *howto_table;
  1351.  
  1352.   allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
  1353.   if (allocated == NULL)
  1354.     goto error_return;
  1355.  
  1356.   if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
  1357.       || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
  1358.     goto error_return;
  1359.  
  1360.   native_relocs = (bfd_byte *) allocated;
  1361.  
  1362.   relents = asect->relocation + asect->reloc_count;
  1363.  
  1364.   entsize = rel_hdr->sh_entsize;
  1365.   BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
  1366.           || entsize == sizeof (Elf64_Mips_External_Rela));
  1367.  
  1368.   count = rel_hdr->sh_size / entsize;
  1369.  
  1370.   if (entsize == sizeof (Elf64_Mips_External_Rel))
  1371.     howto_table = mips_elf64_howto_table_rel;
  1372.   else
  1373.     howto_table = mips_elf64_howto_table_rela;
  1374.  
  1375.   relent = relents;
  1376.   for (i = 0; i < count; i++, native_relocs += entsize)
  1377.     {
  1378.       Elf64_Mips_Internal_Rela rela;
  1379.       boolean used_sym, used_ssym;
  1380.       int ir;
  1381.  
  1382.       if (entsize == sizeof (Elf64_Mips_External_Rela))
  1383.     mips_elf64_swap_reloca_in (abfd,
  1384.                    (Elf64_Mips_External_Rela *) native_relocs,
  1385.                    &rela);
  1386.       else
  1387.     {
  1388.       Elf64_Mips_Internal_Rel rel;
  1389.  
  1390.       mips_elf64_swap_reloc_in (abfd,
  1391.                     (Elf64_Mips_External_Rel *) native_relocs,
  1392.                     &rel);
  1393.       rela.r_offset = rel.r_offset;
  1394.       rela.r_sym = rel.r_sym;
  1395.       rela.r_ssym = rel.r_ssym;
  1396.       rela.r_type3 = rel.r_type3;
  1397.       rela.r_type2 = rel.r_type2;
  1398.       rela.r_type = rel.r_type;
  1399.       rela.r_addend = 0;
  1400.     }
  1401.  
  1402.       /* Each entry represents up to three actual relocations.  */
  1403.  
  1404.       used_sym = false;
  1405.       used_ssym = false;
  1406.       for (ir = 0; ir < 3; ir++)
  1407.     {
  1408.       enum mips_elf64_reloc_type type;
  1409.  
  1410.       switch (ir)
  1411.         {
  1412.         default:
  1413.           abort ();
  1414.         case 0:
  1415.           type = (enum mips_elf64_reloc_type) rela.r_type;
  1416.           break;
  1417.         case 1:
  1418.           type = (enum mips_elf64_reloc_type) rela.r_type2;
  1419.           break;
  1420.         case 2:
  1421.           type = (enum mips_elf64_reloc_type) rela.r_type3;
  1422.           break;
  1423.         }
  1424.  
  1425.       if (type == R_MIPS_NONE)
  1426.         {
  1427.           /* There are no more relocations in this entry.  If this
  1428.                  is the first entry, we need to generate a dummy
  1429.                  relocation so that the generic linker knows that
  1430.                  there has been a break in the sequence of relocations
  1431.                  applying to a particular address.  */
  1432.           if (ir == 0)
  1433.         {
  1434.           relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
  1435.           if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
  1436.             relent->address = rela.r_offset;
  1437.           else
  1438.             relent->address = rela.r_offset - asect->vma;
  1439.           relent->addend = 0;
  1440.           relent->howto = &howto_table[(int) R_MIPS_NONE];
  1441.           ++relent;
  1442.         }
  1443.           break;
  1444.         }
  1445.  
  1446.       /* Some types require symbols, whereas some do not.  */
  1447.       switch (type)
  1448.         {
  1449.         case R_MIPS_NONE:
  1450.         case R_MIPS_LITERAL:
  1451.         case R_MIPS_INSERT_A:
  1452.         case R_MIPS_INSERT_B:
  1453.         case R_MIPS_DELETE:
  1454.           relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
  1455.           break;
  1456.  
  1457.         default:
  1458.           if (! used_sym)
  1459.         {
  1460.           if (rela.r_sym == 0)
  1461.             relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
  1462.           else
  1463.             {
  1464.               asymbol **ps, *s;
  1465.  
  1466.               ps = symbols + rela.r_sym - 1;
  1467.               s = *ps;
  1468.               if ((s->flags & BSF_SECTION_SYM) == 0)
  1469.             relent->sym_ptr_ptr = ps;
  1470.               else
  1471.             relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
  1472.             }
  1473.  
  1474.           used_sym = true;
  1475.         }
  1476.           else if (! used_ssym)
  1477.         {
  1478.           switch (rela.r_ssym)
  1479.             {
  1480.             case RSS_UNDEF:
  1481.               relent->sym_ptr_ptr =
  1482.             bfd_abs_section_ptr->symbol_ptr_ptr;
  1483.               break;
  1484.  
  1485.             case RSS_GP:
  1486.             case RSS_GP0:
  1487.             case RSS_LOC:
  1488.               /* FIXME: I think these need to be handled using
  1489.                          special howto structures.  */
  1490.               BFD_ASSERT (0);
  1491.               break;
  1492.  
  1493.             default:
  1494.               BFD_ASSERT (0);
  1495.               break;
  1496.             }
  1497.  
  1498.           used_ssym = true;
  1499.         }
  1500.           else
  1501.         relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
  1502.  
  1503.           break;
  1504.         }
  1505.  
  1506.       /* The address of an ELF reloc is section relative for an
  1507.          object file, and absolute for an executable file or
  1508.          shared library.  The address of a BFD reloc is always
  1509.          section relative.  */
  1510.       if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
  1511.         relent->address = rela.r_offset;
  1512.       else
  1513.         relent->address = rela.r_offset - asect->vma;
  1514.  
  1515.       relent->addend = rela.r_addend;
  1516.  
  1517.       relent->howto = &howto_table[(int) type];
  1518.  
  1519.       ++relent;
  1520.     }
  1521.     }
  1522.  
  1523.   asect->reloc_count += relent - relents;
  1524.  
  1525.   if (allocated != NULL)
  1526.     free (allocated);
  1527.  
  1528.   return true;
  1529.  
  1530.  error_return:
  1531.   if (allocated != NULL)
  1532.     free (allocated);
  1533.   return false;
  1534. }
  1535.  
  1536. /* Read the relocations.  On Irix 6, there can be two reloc sections
  1537.    associated with a single data section.  */
  1538.  
  1539. static boolean
  1540. mips_elf64_slurp_reloc_table (abfd, asect, symbols)
  1541.      bfd *abfd;
  1542.      asection *asect;
  1543.      asymbol **symbols;
  1544. {
  1545.   struct bfd_elf_section_data * const d = elf_section_data (asect);
  1546.  
  1547.   if (asect->relocation != NULL
  1548.       || (asect->flags & SEC_RELOC) == 0
  1549.       || asect->reloc_count == 0)
  1550.     return true;
  1551.  
  1552.   /* Allocate space for 3 arelent structures for each Rel structure.  */
  1553.   asect->relocation = ((arelent *)
  1554.                bfd_alloc (abfd,
  1555.                   asect->reloc_count * 3 * sizeof (arelent)));
  1556.   if (asect->relocation == NULL)
  1557.     return false;
  1558.  
  1559.   /* The slurp_one_reloc_table routine increments reloc_count.  */
  1560.   asect->reloc_count = 0;
  1561.  
  1562.   if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
  1563.     return false;
  1564.   if (d->rel_hdr2 != NULL)
  1565.     {
  1566.       if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
  1567.                           d->rel_hdr2))
  1568.     return false;
  1569.     }
  1570.  
  1571.   return true;
  1572. }
  1573.  
  1574. /* Write out the relocations.  */
  1575.  
  1576. static void
  1577. mips_elf64_write_relocs (abfd, sec, data)
  1578.      bfd *abfd;
  1579.      asection *sec;
  1580.      PTR data;
  1581. {
  1582.   boolean *failedp = (boolean *) data;
  1583.   unsigned int count;
  1584.   Elf_Internal_Shdr *rela_hdr;
  1585.   Elf64_Mips_External_Rela *ext_rela;
  1586.   unsigned int idx;
  1587.   asymbol *last_sym = 0;
  1588.   int last_sym_idx = 0;
  1589.  
  1590.   /* If we have already failed, don't do anything.  */
  1591.   if (*failedp)
  1592.     return;
  1593.  
  1594.   if ((sec->flags & SEC_RELOC) == 0)
  1595.     return;
  1596.  
  1597.   /* The linker backend writes the relocs out itself, and sets the
  1598.      reloc_count field to zero to inhibit writing them here.  Also,
  1599.      sometimes the SEC_RELOC flag gets set even when there aren't any
  1600.      relocs.  */
  1601.   if (sec->reloc_count == 0)
  1602.     return;
  1603.  
  1604.   /* We can combine up to three relocs that refer to the same address
  1605.      if the latter relocs have no associated symbol.  */
  1606.   count = 0;
  1607.   for (idx = 0; idx < sec->reloc_count; idx++)
  1608.     {
  1609.       bfd_vma addr;
  1610.       unsigned int i;
  1611.  
  1612.       ++count;
  1613.  
  1614.       addr = sec->orelocation[idx]->address;
  1615.       for (i = 0; i < 2; i++)
  1616.     {
  1617.       arelent *r;
  1618.  
  1619.       if (idx + 1 >= sec->reloc_count)
  1620.         break;
  1621.       r = sec->orelocation[idx + 1];
  1622.       if (r->address != addr
  1623.           || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
  1624.           || (*r->sym_ptr_ptr)->value != 0)
  1625.         break;
  1626.  
  1627.       /* We can merge the reloc at IDX + 1 with the reloc at IDX.  */
  1628.  
  1629.       ++idx;
  1630.     }
  1631.     }
  1632.  
  1633.   rela_hdr = &elf_section_data (sec)->rel_hdr;
  1634.  
  1635.   rela_hdr->sh_size = rela_hdr->sh_entsize * count;
  1636.   rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
  1637.   if (rela_hdr->contents == NULL)
  1638.     {
  1639.       *failedp = true;
  1640.       return;
  1641.     }
  1642.  
  1643.   ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
  1644.   for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
  1645.     {
  1646.       arelent *ptr;
  1647.       Elf64_Mips_Internal_Rela int_rela;
  1648.       asymbol *sym;
  1649.       int n;
  1650.       unsigned int i;
  1651.  
  1652.       ptr = sec->orelocation[idx];
  1653.  
  1654.       /* The address of an ELF reloc is section relative for an object
  1655.      file, and absolute for an executable file or shared library.
  1656.      The address of a BFD reloc is always section relative.  */
  1657.       if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
  1658.     int_rela.r_offset = ptr->address;
  1659.       else
  1660.     int_rela.r_offset = ptr->address + sec->vma;
  1661.  
  1662.       sym = *ptr->sym_ptr_ptr;
  1663.       if (sym == last_sym)
  1664.     n = last_sym_idx;
  1665.       else
  1666.     {
  1667.       last_sym = sym;
  1668.       n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
  1669.       if (n < 0)
  1670.         {
  1671.           *failedp = true;
  1672.           return;
  1673.         }
  1674.       last_sym_idx = n;
  1675.     }
  1676.  
  1677.       int_rela.r_sym = n;
  1678.  
  1679.       int_rela.r_addend = ptr->addend;
  1680.  
  1681.       int_rela.r_ssym = RSS_UNDEF;
  1682.  
  1683.       if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
  1684.       && ! _bfd_elf_validate_reloc (abfd, ptr))
  1685.     {
  1686.       *failedp = true;
  1687.       return;
  1688.     }
  1689.  
  1690.       int_rela.r_type = ptr->howto->type;
  1691.       int_rela.r_type2 = (int) R_MIPS_NONE;
  1692.       int_rela.r_type3 = (int) R_MIPS_NONE;
  1693.  
  1694.       for (i = 0; i < 2; i++)
  1695.     {
  1696.       arelent *r;
  1697.  
  1698.       if (idx + 1 >= sec->reloc_count)
  1699.         break;
  1700.       r = sec->orelocation[idx + 1];
  1701.       if (r->address != ptr->address
  1702.           || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
  1703.           || (*r->sym_ptr_ptr)->value != 0)
  1704.         break;
  1705.  
  1706.       /* We can merge the reloc at IDX + 1 with the reloc at IDX.  */
  1707.  
  1708.       if (i == 0)
  1709.         int_rela.r_type2 = r->howto->type;
  1710.       else
  1711.         int_rela.r_type3 = r->howto->type;
  1712.  
  1713.       ++idx;
  1714.     }
  1715.  
  1716.       mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
  1717.     }
  1718.  
  1719.   BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
  1720.           == count);
  1721. }
  1722.  
  1723. /* Handle a 64-bit MIPS ELF specific section.  */
  1724.  
  1725. static boolean
  1726. mips_elf64_section_from_shdr (abfd, hdr, name)
  1727.      bfd *abfd;
  1728.      Elf_Internal_Shdr *hdr;
  1729.      char *name;
  1730. {
  1731.   if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
  1732.     return false;
  1733.  
  1734.   /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
  1735.      set the gp value based on what we find.  We may see both
  1736.      SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
  1737.      they should agree.  */
  1738.   if (hdr->sh_type == SHT_MIPS_OPTIONS)
  1739.     {
  1740.       bfd_byte *contents, *l, *lend;
  1741.  
  1742.       contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
  1743.       if (contents == NULL)
  1744.     return false;
  1745.       if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
  1746.                       (file_ptr) 0, hdr->sh_size))
  1747.     {
  1748.       free (contents);
  1749.       return false;
  1750.     }
  1751.       l = contents;
  1752.       lend = contents + hdr->sh_size;
  1753.       while (l + sizeof (Elf_External_Options) <= lend)
  1754.     {
  1755.       Elf_Internal_Options intopt;
  1756.  
  1757.       bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
  1758.                     &intopt);
  1759.       if (intopt.kind == ODK_REGINFO)
  1760.         {
  1761.           Elf64_Internal_RegInfo intreg;
  1762.  
  1763.           bfd_mips_elf64_swap_reginfo_in
  1764.         (abfd,
  1765.          ((Elf64_External_RegInfo *)
  1766.           (l + sizeof (Elf_External_Options))),
  1767.          &intreg);
  1768.           elf_gp (abfd) = intreg.ri_gp_value;
  1769.         }
  1770.       l += intopt.size;
  1771.     }
  1772.       free (contents);
  1773.     }
  1774.  
  1775.   return true;
  1776. }
  1777.  
  1778. /* Work over a section just before writing it out.  We update the GP
  1779.    value in the SHT_MIPS_OPTIONS section based on the value we are
  1780.    using.  */
  1781.  
  1782. static boolean
  1783. mips_elf64_section_processing (abfd, hdr)
  1784.      bfd *abfd;
  1785.      Elf_Internal_Shdr *hdr;
  1786. {
  1787.   if (hdr->sh_type == SHT_MIPS_OPTIONS
  1788.       && hdr->bfd_section != NULL
  1789.       && elf_section_data (hdr->bfd_section) != NULL
  1790.       && elf_section_data (hdr->bfd_section)->tdata != NULL)
  1791.     {
  1792.       bfd_byte *contents, *l, *lend;
  1793.  
  1794.       /* We stored the section contents in the elf_section_data tdata
  1795.      field in the set_section_contents routine.  We save the
  1796.      section contents so that we don't have to read them again.
  1797.      At this point we know that elf_gp is set, so we can look
  1798.      through the section contents to see if there is an
  1799.      ODK_REGINFO structure.  */
  1800.  
  1801.       contents = (bfd_byte *) elf_section_data (hdr->bfd_section)->tdata;
  1802.       l = contents;
  1803.       lend = contents + hdr->sh_size;
  1804.       while (l + sizeof (Elf_External_Options) <= lend)
  1805.     {
  1806.       Elf_Internal_Options intopt;
  1807.  
  1808.       bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
  1809.                     &intopt);
  1810.       if (intopt.kind == ODK_REGINFO)
  1811.         {
  1812.           bfd_byte buf[8];
  1813.  
  1814.           if (bfd_seek (abfd,
  1815.                 (hdr->sh_offset
  1816.                  + (l - contents)
  1817.                  + sizeof (Elf_External_Options)
  1818.                  + (sizeof (Elf64_External_RegInfo) - 8)),
  1819.                  SEEK_SET) == -1)
  1820.         return false;
  1821.           bfd_h_put_64 (abfd, elf_gp (abfd), buf);
  1822.           if (bfd_write (buf, 1, 8, abfd) != 8)
  1823.         return false;
  1824.         }
  1825.       l += intopt.size;
  1826.     }
  1827.     }
  1828.  
  1829.   return _bfd_mips_elf_section_processing (abfd, hdr);
  1830. }
  1831.  
  1832. /* ECOFF swapping routines.  These are used when dealing with the
  1833.    .mdebug section, which is in the ECOFF debugging format.  */
  1834. static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
  1835. {
  1836.   /* Symbol table magic number.  */
  1837.   magicSym2,
  1838.   /* Alignment of debugging information.  E.g., 4.  */
  1839.   8,
  1840.   /* Sizes of external symbolic information.  */
  1841.   sizeof (struct hdr_ext),
  1842.   sizeof (struct dnr_ext),
  1843.   sizeof (struct pdr_ext),
  1844.   sizeof (struct sym_ext),
  1845.   sizeof (struct opt_ext),
  1846.   sizeof (struct fdr_ext),
  1847.   sizeof (struct rfd_ext),
  1848.   sizeof (struct ext_ext),
  1849.   /* Functions to swap in external symbolic data.  */
  1850.   ecoff_swap_hdr_in,
  1851.   ecoff_swap_dnr_in,
  1852.   ecoff_swap_pdr_in,
  1853.   ecoff_swap_sym_in,
  1854.   ecoff_swap_opt_in,
  1855.   ecoff_swap_fdr_in,
  1856.   ecoff_swap_rfd_in,
  1857.   ecoff_swap_ext_in,
  1858.   _bfd_ecoff_swap_tir_in,
  1859.   _bfd_ecoff_swap_rndx_in,
  1860.   /* Functions to swap out external symbolic data.  */
  1861.   ecoff_swap_hdr_out,
  1862.   ecoff_swap_dnr_out,
  1863.   ecoff_swap_pdr_out,
  1864.   ecoff_swap_sym_out,
  1865.   ecoff_swap_opt_out,
  1866.   ecoff_swap_fdr_out,
  1867.   ecoff_swap_rfd_out,
  1868.   ecoff_swap_ext_out,
  1869.   _bfd_ecoff_swap_tir_out,
  1870.   _bfd_ecoff_swap_rndx_out,
  1871.   /* Function to read in symbolic data.  */
  1872.   _bfd_mips_elf_read_ecoff_info
  1873. };
  1874.  
  1875. /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
  1876.    standard ELF.  This structure is used to redirect the relocation
  1877.    handling routines.  */
  1878.  
  1879. const struct elf_size_info mips_elf64_size_info =
  1880. {
  1881.   sizeof (Elf64_External_Ehdr),
  1882.   sizeof (Elf64_External_Phdr),
  1883.   sizeof (Elf64_External_Shdr),
  1884.   sizeof (Elf64_Mips_External_Rel),
  1885.   sizeof (Elf64_Mips_External_Rela),
  1886.   sizeof (Elf64_External_Sym),
  1887.   sizeof (Elf64_External_Dyn),
  1888.   sizeof (Elf_External_Note),
  1889.   64,        /* arch_size */
  1890.   8,        /* file_align */
  1891.   ELFCLASS64,
  1892.   EV_CURRENT,
  1893.   bfd_elf64_write_out_phdrs,
  1894.   bfd_elf64_write_shdrs_and_ehdr,
  1895.   mips_elf64_write_relocs,
  1896.   bfd_elf64_swap_symbol_out,
  1897.   mips_elf64_slurp_reloc_table,
  1898.   bfd_elf64_slurp_symbol_table,
  1899.   bfd_elf64_swap_dyn_in
  1900. };
  1901.  
  1902. #define TARGET_LITTLE_SYM        bfd_elf64_littlemips_vec
  1903. #define TARGET_LITTLE_NAME        "elf64-littlemips"
  1904. #define TARGET_BIG_SYM            bfd_elf64_bigmips_vec
  1905. #define TARGET_BIG_NAME            "elf64-bigmips"
  1906. #define ELF_ARCH            bfd_arch_mips
  1907. #define ELF_MACHINE_CODE        EM_MIPS
  1908. #define ELF_MAXPAGESIZE            0x1000
  1909. #define elf_backend_size_info        mips_elf64_size_info
  1910. #define elf_backend_object_p        _bfd_mips_elf_object_p
  1911. #define elf_backend_section_from_shdr    mips_elf64_section_from_shdr
  1912. #define elf_backend_fake_sections    _bfd_mips_elf_fake_sections
  1913. #define elf_backend_section_from_bfd_section \
  1914.                     _bfd_mips_elf_section_from_bfd_section
  1915. #define elf_backend_section_processing    mips_elf64_section_processing
  1916. #define elf_backend_symbol_processing    _bfd_mips_elf_symbol_processing
  1917. #define elf_backend_final_write_processing \
  1918.                     _bfd_mips_elf_final_write_processing
  1919. #define elf_backend_ecoff_debug_swap    &mips_elf64_ecoff_debug_swap
  1920.  
  1921. #define bfd_elf64_find_nearest_line    _bfd_mips_elf_find_nearest_line
  1922. #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
  1923. #define bfd_elf64_bfd_reloc_type_lookup    mips_elf64_reloc_type_lookup
  1924. #define bfd_elf64_set_section_contents    _bfd_mips_elf_set_section_contents
  1925. #define bfd_elf64_bfd_copy_private_bfd_data \
  1926.                     _bfd_mips_elf_copy_private_bfd_data
  1927. #define bfd_elf64_bfd_merge_private_bfd_data \
  1928.                     _bfd_mips_elf_merge_private_bfd_data
  1929. #define bfd_elf64_bfd_set_private_flags    _bfd_mips_elf_set_private_flags
  1930.  
  1931. #include "elf64-target.h"
  1932.