This commit was manufactured by cvs2svn to create tag 'drow-cplus-
[external/binutils.git] / bfd / elfn32-mips.c
index 973edd5..49cf898 100644 (file)
@@ -47,6 +47,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define ECOFF_SIGNED_32
 #include "ecoffswap.h"
 
+static bfd_reloc_status_type mips_elf_generic_reloc
+  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+static bfd_reloc_status_type mips_elf_hi16_reloc
+  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+static bfd_reloc_status_type mips_elf_lo16_reloc
+  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+static bfd_reloc_status_type mips_elf_got16_reloc
+  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
 static bfd_boolean mips_elf_assign_gp
   (bfd *, bfd_vma *);
 static bfd_reloc_status_type mips_elf_final_gp
@@ -87,6 +95,10 @@ static irix_compat_t elf_n32_mips_irix_compat
 extern const bfd_target bfd_elf32_nbigmips_vec;
 extern const bfd_target bfd_elf32_nlittlemips_vec;
 
+static asection *prev_reloc_section = NULL;
+static bfd_vma prev_reloc_address = -1;
+static bfd_vma prev_reloc_addend = 0;
+
 /* Nonzero if ABFD is using the N32 ABI.  */
 #define ABI_N32_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
@@ -114,7 +126,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_NONE",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -129,7 +141,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_16",           /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -144,7 +156,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_32",           /* name */
         TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -159,7 +171,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_REL32",        /* name */
         TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -177,7 +189,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
                                /* This needs complex overflow
                                   detection, because the upper four
                                   bits must match the PC + 4.  */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_26",           /* name */
         TRUE,                  /* partial_inplace */
         0x03ffffff,            /* src_mask */
@@ -189,13 +201,13 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
 
   /* High 16 bits of symbol value.  */
   HOWTO (R_MIPS_HI16,          /* type */
-        16,                    /* rightshift */
+        0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_hi16_reloc, /* special_function */
+        mips_elf_hi16_reloc,   /* special_function */
         "R_MIPS_HI16",         /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -210,7 +222,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_lo16_reloc, /* special_function */
+        mips_elf_lo16_reloc,   /* special_function */
         "R_MIPS_LO16",         /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -255,7 +267,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_got16_reloc, /* special_function */
+        mips_elf_got16_reloc,  /* special_function */
         "R_MIPS_GOT16",        /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -270,7 +282,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_PC16",         /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -285,7 +297,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL16",       /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -321,7 +333,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         6,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SHIFT5",       /* name */
         TRUE,                  /* partial_inplace */
         0x000007c0,            /* src_mask */
@@ -351,7 +363,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_64",           /* name */
         TRUE,                  /* partial_inplace */
         MINUS_ONE,             /* src_mask */
@@ -366,7 +378,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_DISP",     /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -381,7 +393,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_PAGE",     /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -396,7 +408,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_OFST",     /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -411,7 +423,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_HI16",     /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -426,7 +438,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_LO16",     /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -441,7 +453,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SUB",          /* name */
         TRUE,                  /* partial_inplace */
         MINUS_ONE,             /* src_mask */
@@ -457,7 +469,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_INSERT_A",     /* name */
         TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -474,7 +486,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_INSERT_B",     /* name */
         TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -490,7 +502,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_DELETE",       /* name */
         TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -514,7 +526,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL_HI16",    /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -529,7 +541,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL_LO16",    /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -544,7 +556,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SCN_DISP",     /* name */
         TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -558,7 +570,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_REL16",        /* name */
         TRUE,                  /* partial_inplace */
         0xffff,                /* src_mask */
@@ -578,7 +590,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_RELGOT",       /* name */
         TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -594,7 +606,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_JALR",         /* name */
         FALSE,                 /* partial_inplace */
         0x00000000,            /* src_mask */
@@ -614,7 +626,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_NONE",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -629,7 +641,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_16",           /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -644,7 +656,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_32",           /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -659,7 +671,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_REL32",        /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -677,7 +689,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
                                /* This needs complex overflow
                                   detection, because the upper 36
                                   bits must match the PC + 4.  */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_26",           /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -692,7 +704,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_HI16",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -707,7 +719,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_LO16",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -752,7 +764,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_got16_reloc,  /* special_function */
         "R_MIPS_GOT16",        /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -767,7 +779,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_PC16",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -782,7 +794,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL16",       /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -816,7 +828,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         6,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SHIFT5",       /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -846,7 +858,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_64",           /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -861,7 +873,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_DISP",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -876,7 +888,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_PAGE",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -891,7 +903,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_OFST",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -906,7 +918,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_HI16",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -921,7 +933,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_LO16",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -936,7 +948,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SUB",          /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -952,7 +964,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_INSERT_A",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -969,7 +981,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_INSERT_B",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -985,7 +997,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_DELETE",       /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1000,7 +1012,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_HIGHER",       /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1015,7 +1027,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_HIGHEST",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1030,7 +1042,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL_HI16",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1045,7 +1057,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL_LO16",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1060,7 +1072,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SCN_DISP",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1075,7 +1087,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_REL16",        /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1095,7 +1107,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_RELGOT",       /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1111,7 +1123,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_JALR",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1195,7 +1207,7 @@ static reloc_howto_type elf_mips_gnu_rel16_s2 =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GNU_REL16_S2", /* name */
         TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -1211,13 +1223,224 @@ static reloc_howto_type elf_mips_gnu_rela16_s2 =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GNU_REL16_S2", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         TRUE);                 /* pcrel_offset */
 \f
+/* This is derived from bfd_elf_generic_reloc.  NewABI allows us to have
+   several relocations against the same address.  The addend is derived
+   from the addends of preceding relocations.  If we don't need to
+   do something special,  we simply keep track of the addend.  */
+
+#define GET_RELOC_ADDEND(obfd, sym, entry, sec)                                \
+{                                                                      \
+  /* If we're relocating, and this is an external symbol, we don't     \
+     want to change anything.  */                                      \
+    if ((obfd) != NULL                                                 \
+       && ((sym)->flags & BSF_SECTION_SYM) == 0                        \
+       && (! (entry)->howto->partial_inplace                           \
+           || (entry)->addend == 0))                                   \
+      {                                                                        \
+        (entry)->address += (sec)->output_offset;                      \
+        return bfd_reloc_ok;                                           \
+      }                                                                        \
+                                                                       \
+    /* The addend of combined relocs is remembered and left for                \
+       subsequent relocs.  */                                          \
+    if (prev_reloc_address != (entry)->address                         \
+       || prev_reloc_section != (sec))                                 \
+      {                                                                        \
+       prev_reloc_section = (sec);                                     \
+        prev_reloc_address = (entry)->address;                         \
+        prev_reloc_addend = (entry)->addend;                           \
+      }                                                                        \
+    else                                                               \
+      (entry)->addend = prev_reloc_addend;                             \
+}
+
+#define SET_RELOC_ADDEND(entry)                                                \
+{                                                                      \
+  prev_reloc_addend = (entry)->addend;                                 \
+}
+
+static bfd_reloc_status_type
+mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+                       asymbol *symbol, void *data ATTRIBUTE_UNUSED,
+                       asection *input_section, bfd *output_bfd,
+                       char **error_message ATTRIBUTE_UNUSED)
+{
+  GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
+
+  return bfd_reloc_continue;
+}
+\f
+/* Do a R_MIPS_HI16 relocation.  This has to be done in combination
+   with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to
+   the HI16.  Here we just save the information we need; we do the
+   actual relocation when we see the LO16.
+
+   MIPS ELF requires that the LO16 immediately follow the HI16.  As a
+   GNU extension, for non-pc-relative relocations, we permit an
+   arbitrary number of HI16 relocs to be associated with a single LO16
+   reloc.  This extension permits gcc to output the HI and LO relocs
+   itself.
+
+   This cannot be done for PC-relative relocations because both the HI16
+   and LO16 parts of the relocations must be done relative to the LO16
+   part, and there can be carry to or borrow from the HI16 part.  */
+
+struct mips_hi16
+{
+  struct mips_hi16 *next;
+  bfd_byte *addr;
+  bfd_vma addend;
+};
+
+/* FIXME: This should not be a static variable.  */
+
+static struct mips_hi16 *mips_hi16_list;
+
+static bfd_reloc_status_type
+mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+                    asymbol *symbol, void *data, asection *input_section,
+                    bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
+{
+  bfd_reloc_status_type ret;
+  bfd_vma relocation;
+  struct mips_hi16 *n;
+
+  GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
+
+  ret = bfd_reloc_ok;
+
+  if (bfd_is_und_section (symbol->section) && output_bfd == NULL)
+    ret = bfd_reloc_undefined;
+
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
+
+  relocation += symbol->section->output_section->vma;
+  relocation += symbol->section->output_offset;
+  relocation += reloc_entry->addend;
+
+  if (reloc_entry->address > input_section->_cooked_size)
+    return bfd_reloc_outofrange;
+
+  /* Save the information, and let LO16 do the actual relocation.  */
+  n = bfd_malloc (sizeof *n);
+  if (n == NULL)
+    return bfd_reloc_outofrange;
+  n->addr = (bfd_byte *) data + reloc_entry->address;
+  n->addend = relocation;
+  n->next = mips_hi16_list;
+  mips_hi16_list = n;
+
+  if (output_bfd != NULL)
+    reloc_entry->address += input_section->output_offset;
+
+  return ret;
+}
+
+/* Do a R_MIPS_LO16 relocation.  This is a straightforward 16 bit
+   inplace relocation; this function exists in order to do the
+   R_MIPS_HI16 relocation described above.  */
+
+static bfd_reloc_status_type
+mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+                    void *data, asection *input_section, bfd *output_bfd,
+                    char **error_message)
+{
+  if (mips_hi16_list != NULL)
+    {
+      struct mips_hi16 *l;
+
+      l = mips_hi16_list;
+      while (l != NULL)
+       {
+         unsigned long insn;
+         unsigned long val;
+         unsigned long vallo;
+         struct mips_hi16 *next;
+
+         /* Do the HI16 relocation.  Note that we actually don't need
+            to know anything about the LO16 itself, except where to
+            find the low 16 bits of the addend needed by the LO16.  */
+         insn = bfd_get_32 (abfd, l->addr);
+         vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+
+         /* The low order 16 bits are always treated as a signed
+            value.  */
+         vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000;
+         val = ((insn & 0xffff) << 16) + vallo;
+         val += l->addend;
+
+         /* If PC-relative, we need to subtract out the address of the LO
+            half of the HI/LO.  (The actual relocation is relative
+            to that instruction.)  */
+         if (reloc_entry->howto->pc_relative)
+           val -= reloc_entry->address;
+
+         /* At this point, "val" has the value of the combined HI/LO
+            pair.  If the low order 16 bits (which will be used for
+            the LO16 insn) are negative, then we will need an
+            adjustment for the high order 16 bits.  */
+         val += 0x8000;
+         val = (val >> 16) & 0xffff;
+
+         insn &= ~ (bfd_vma) 0xffff;
+         insn |= val;
+         bfd_put_32 (abfd, insn, l->addr);
+
+         next = l->next;
+         free (l);
+         l = next;
+       }
+
+      mips_hi16_list = NULL;
+    }
+
+  /* Now do the LO16 reloc in the usual way.  */
+  return mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+                                input_section, output_bfd, error_message);
+}
+
+/* Do a R_MIPS_GOT16 reloc.  This is a reloc against the global offset
+   table used for PIC code.  If the symbol is an external symbol, the
+   instruction is modified to contain the offset of the appropriate
+   entry in the global offset table.  If the symbol is a section
+   symbol, the next reloc is a R_MIPS_LO16 reloc.  The two 16 bit
+   addends are combined to form the real addend against the section
+   symbol; the GOT16 is modified to contain the offset of an entry in
+   the global offset table, and the LO16 is modified to offset it
+   appropriately.  Thus an offset larger than 16 bits requires a
+   modified value in the global offset table.
+
+   This implementation suffices for the assembler, but the linker does
+   not yet know how to create global offset tables.  */
+
+static bfd_reloc_status_type
+mips_elf_got16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+                     void *data, asection *input_section, bfd *output_bfd,
+                     char **error_message)
+{
+  /* If we're relocating, and this is a local symbol, we can handle it
+     just like an R_MIPS_HI16.  */
+  if (output_bfd != NULL
+      && ((symbol->flags & BSF_SECTION_SYM) != 0
+         || (symbol->flags & BSF_LOCAL) == 0))
+    return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
+                               input_section, output_bfd, error_message);
+
+  /* Otherwise we try to handle it as R_MIPS_GOT_DISP.  */
+  return mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+                                input_section, output_bfd, error_message);
+}
+
 /* Set the GP value for OUTPUT_BFD.  Returns FALSE if this is a
    dangerous relocation.  */
 
@@ -1319,6 +1542,8 @@ mips_elf_gprel16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
   bfd_reloc_status_type ret;
   bfd_vma gp;
 
+  GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
+
   if (output_bfd != NULL)
     relocatable = TRUE;
   else
@@ -1348,6 +1573,8 @@ mips_elf_literal_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
   bfd_reloc_status_type ret;
   bfd_vma gp;
 
+  GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
+
   /* FIXME: The entries in the .lit8 and .lit4 sections should be merged.  */
   if (output_bfd != NULL)
     relocatable = TRUE;
@@ -1379,6 +1606,8 @@ mips_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
   bfd_reloc_status_type ret;
   bfd_vma gp;
 
+  GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
+
   /* R_MIPS_GPREL32 relocations are defined for local symbols only.  */
   if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
@@ -1455,33 +1684,36 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry,
    the rest is at bits 6-10. The bitpos already got right by the howto.  */
 
 static bfd_reloc_status_type
-mips_elf_shift6_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                      void *data, asection *input_section, bfd *output_bfd,
-                      char **error_message)
+mips_elf_shift6_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+                      asymbol *symbol, void *data ATTRIBUTE_UNUSED,
+                      asection *input_section, bfd *output_bfd,
+                      char **error_message ATTRIBUTE_UNUSED)
 {
+  GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
+
   if (reloc_entry->howto->partial_inplace)
     {
       reloc_entry->addend = ((reloc_entry->addend & 0x00007c0)
                             | (reloc_entry->addend & 0x00000800) >> 9);
     }
 
-  return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
-                                     input_section, output_bfd,
-                                     error_message);
+  SET_RELOC_ADDEND (reloc_entry)
+
+  return bfd_reloc_continue;
 }
 \f
 /* Handle a mips16 jump.  */
 
 static bfd_reloc_status_type
-mips16_jump_reloc (bfd *abfd ATTRIBUTE_UNUSED,
-                  arelent *reloc_entry ATTRIBUTE_UNUSED,
-                  asymbol *symbol ATTRIBUTE_UNUSED,
-                  void *data ATTRIBUTE_UNUSED,
-                  asection *input_section, bfd *output_bfd ATTRIBUTE_UNUSED,
+mips16_jump_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+                  asymbol *symbol, void *data ATTRIBUTE_UNUSED,
+                  asection *input_section, bfd *output_bfd,
                   char **error_message ATTRIBUTE_UNUSED)
 {
   static bfd_boolean warned = FALSE;
 
+  GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
+
   /* FIXME.  */
   if (! warned)
     (*_bfd_error_handler)
@@ -1507,6 +1739,8 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
   bfd_signed_vma val;
   bfd_vma relocation;
 
+  GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
+
   if (output_bfd != NULL)
     relocatable = TRUE;
   else
@@ -1570,6 +1804,9 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
   return bfd_reloc_ok;
 }
+
+#undef GET_RELOC_ADDEND
+#undef SET_RELOC_ADDEND
 \f
 /* A mapping from BFD reloc types to MIPS ELF reloc types.  */
 
@@ -1873,6 +2110,11 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 #define ELF_ARCH                       bfd_arch_mips
 #define ELF_MACHINE_CODE               EM_MIPS
 
+/* The SVR4 MIPS ABI says that this should be 0x10000, but Irix 5 uses
+   a value of 0x1000, and we are compatible.
+   FIXME: How does this affect NewABI?  */
+#define ELF_MAXPAGESIZE                        0x1000
+
 #define elf_backend_collect            TRUE
 #define elf_backend_type_change_ok     TRUE
 #define elf_backend_can_gc_sections    TRUE
@@ -1954,30 +2196,20 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 #define TARGET_BIG_SYM                  bfd_elf32_nbigmips_vec
 #define TARGET_BIG_NAME                 "elf32-nbigmips"
 
-/* The SVR4 MIPS ABI says that this should be 0x10000, but Irix 5 uses
-   a value of 0x1000, and we are compatible.
-   FIXME: How does this affect NewABI?  */
-#define ELF_MAXPAGESIZE                        0x1000
-
 #include "elf32-target.h"
 
 /* Support for traditional mips targets using n32 ABI.  */
+#define INCLUDED_TARGET_FILE            /* More a type of flag.  */
+
 #undef TARGET_LITTLE_SYM
 #undef TARGET_LITTLE_NAME
 #undef TARGET_BIG_SYM
 #undef TARGET_BIG_NAME
 
-#undef ELF_MAXPAGESIZE
-
 #define TARGET_LITTLE_SYM               bfd_elf32_ntradlittlemips_vec
 #define TARGET_LITTLE_NAME              "elf32-ntradlittlemips"
 #define TARGET_BIG_SYM                  bfd_elf32_ntradbigmips_vec
 #define TARGET_BIG_NAME                 "elf32-ntradbigmips"
 
-/* The SVR4 MIPS ABI says that this should be 0x10000, and Linux uses
-   page sizes of up to that limit, so we need to respect it.  */
-#define ELF_MAXPAGESIZE                        0x10000
-#define elf32_bed                      elf32_tradbed
-
 /* Include the target file again for this target.  */
 #include "elf32-target.h"