* Makefile.in (cli-cmds.o): Depend on $(gdb_vfork_h)
[deliverable/binutils-gdb.git] / bfd / elf32-mips.c
index 875e316bf72b5e0abb9c0bfd0f0eb449e3ffeffd..67688c996d31dde931c672ef9439b7a2bed29828 100644 (file)
@@ -1,6 +1,6 @@
 /* MIPS-specific support for 32-bit ELF
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+   2003 Free Software Foundation, Inc.
 
    Most of the information added by Ian Lance Taylor, Cygnus Support,
    <ian@cygnus.com>.
@@ -47,12 +47,17 @@ 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
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf_hi16_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf_lo16_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf_got16_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_reloc_status_type gprel32_with_gp
+  PARAMS ((bfd *, asymbol *, arelent *, asection *, bfd_boolean, PTR,
+          bfd_vma));
 static bfd_reloc_status_type mips_elf_gprel32_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips32_64bit_reloc
@@ -60,25 +65,28 @@ static bfd_reloc_status_type mips32_64bit_reloc
 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 static reloc_howto_type *mips_elf32_rtype_to_howto
-  PARAMS ((unsigned int, boolean));
+  PARAMS ((unsigned int, bfd_boolean));
 static void mips_info_to_howto_rel
   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
 static void mips_info_to_howto_rela
   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
-static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *));
-static boolean mips_elf32_object_p PARAMS ((bfd *));
-static boolean mips_elf_is_local_label_name
+static bfd_boolean mips_elf_sym_is_global
+  PARAMS ((bfd *, asymbol *));
+static bfd_boolean mips_elf32_object_p
+  PARAMS ((bfd *));
+static bfd_boolean mips_elf_is_local_label_name
   PARAMS ((bfd *, const char *));
 static bfd_reloc_status_type mips16_jump_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips16_gprel_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf_final_gp
-  PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *));
-static boolean mips_elf_assign_gp PARAMS ((bfd *, bfd_vma *));
-static boolean elf32_mips_grok_prstatus
+  PARAMS ((bfd *, asymbol *, bfd_boolean, char **, bfd_vma *));
+static bfd_boolean mips_elf_assign_gp
+  PARAMS ((bfd *, bfd_vma *));
+static bfd_boolean elf32_mips_grok_prstatus
   PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean elf32_mips_grok_psinfo
+static bfd_boolean elf32_mips_grok_psinfo
   PARAMS ((bfd *, Elf_Internal_Note *));
 static irix_compat_t elf32_mips_irix_compat
   PARAMS ((bfd *));
@@ -110,198 +118,198 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         0,                     /* rightshift */
         0,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_NONE",         /* name */
-        false,                 /* partial_inplace */
+        FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* 16 bit relocation.  */
   HOWTO (R_MIPS_16,            /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_16",           /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* 32 bit relocation.  */
   HOWTO (R_MIPS_32,            /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_32",           /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* 32 bit symbol relative relocation.  */
   HOWTO (R_MIPS_REL32,         /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_REL32",        /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* 26 bit jump address.  */
   HOWTO (R_MIPS_26,            /* type */
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         26,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
                                /* This needs complex overflow
                                   detection, because the upper four
                                   bits must match the PC + 4.  */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_26",           /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x03ffffff,            /* src_mask */
         0x03ffffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* High 16 bits of symbol value.  */
   HOWTO (R_MIPS_HI16,          /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         mips_elf_hi16_reloc,   /* special_function */
         "R_MIPS_HI16",         /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Low 16 bits of symbol value.  */
   HOWTO (R_MIPS_LO16,          /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         mips_elf_lo16_reloc,   /* special_function */
         "R_MIPS_LO16",         /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* GP relative reference.  */
   HOWTO (R_MIPS_GPREL16,       /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf32_gprel16_reloc, /* special_function */
         "R_MIPS_GPREL16",      /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Reference to literal section.  */
   HOWTO (R_MIPS_LITERAL,       /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf32_gprel16_reloc, /* special_function */
         "R_MIPS_LITERAL",      /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Reference to global offset table.  */
   HOWTO (R_MIPS_GOT16,         /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         mips_elf_got16_reloc,  /* special_function */
         "R_MIPS_GOT16",        /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* 16 bit PC relative reference.  */
   HOWTO (R_MIPS_PC16,          /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        true,                  /* pc_relative */
+        TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_PC16",         /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        true),                 /* pcrel_offset */
+        TRUE),                 /* pcrel_offset */
 
   /* 16 bit call through global offset table.  */
   HOWTO (R_MIPS_CALL16,                /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL16",       /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* 32 bit GP relative reference.  */
   HOWTO (R_MIPS_GPREL32,       /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         mips_elf_gprel32_reloc, /* special_function */
         "R_MIPS_GPREL32",      /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* The remaining relocs are defined on Irix 5, although they are
      not defined by the ABI.  */
@@ -314,15 +322,15 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         5,                     /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         6,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SHIFT5",       /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x000007c0,            /* src_mask */
         0x000007c0,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* A 6 bit shift field.  */
   /* FIXME: This is not handled correctly; a special function is
@@ -331,120 +339,120 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         6,                     /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         6,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SHIFT6",       /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x000007c4,            /* src_mask */
         0x000007c4,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* A 64 bit relocation.  */
   HOWTO (R_MIPS_64,            /* type */
         0,                     /* rightshift */
         4,                     /* size (0 = byte, 1 = short, 2 = long) */
         64,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         mips32_64bit_reloc,    /* special_function */
         "R_MIPS_64",           /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         MINUS_ONE,             /* src_mask */
         MINUS_ONE,             /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Displacement in the global offset table.  */
   HOWTO (R_MIPS_GOT_DISP,      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_DISP",     /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Displacement to page pointer in the global offset table.  */
   HOWTO (R_MIPS_GOT_PAGE,      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_PAGE",     /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Offset from page pointer in the global offset table.  */
   HOWTO (R_MIPS_GOT_OFST,      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_OFST",     /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* High 16 bits of displacement in global offset table.  */
   HOWTO (R_MIPS_GOT_HI16,      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_HI16",     /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Low 16 bits of displacement in global offset table.  */
   HOWTO (R_MIPS_GOT_LO16,      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GOT_LO16",     /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* 64 bit subtraction.  Used in the N32 ABI.  */
   HOWTO (R_MIPS_SUB,           /* type */
         0,                     /* rightshift */
         4,                     /* size (0 = byte, 1 = short, 2 = long) */
         64,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SUB",          /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         MINUS_ONE,             /* src_mask */
         MINUS_ONE,             /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Used to cause the linker to insert and delete instructions?  */
   EMPTY_HOWTO (R_MIPS_INSERT_A),
@@ -456,75 +464,75 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_HIGHER",       /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Get the highest value of a 64 bit addend.  */
   HOWTO (R_MIPS_HIGHEST,       /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_HIGHEST",      /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* High 16 bits of displacement in global offset table.  */
   HOWTO (R_MIPS_CALL_HI16,     /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL_HI16",    /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Low 16 bits of displacement in global offset table.  */
   HOWTO (R_MIPS_CALL_LO16,     /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_CALL_LO16",    /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   /* Section displacement.  */
   HOWTO (R_MIPS_SCN_DISP,       /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_SCN_DISP",     /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 
   EMPTY_HOWTO (R_MIPS_REL16),
   EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
@@ -537,15 +545,15 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_JALR",         /* name */
-        false,                 /* partial_inplace */
+        FALSE,                 /* partial_inplace */
         0x00000000,            /* src_mask */
         0x00000000,            /* dst_mask */
-        false),                /* pcrel_offset */
+        FALSE),                /* pcrel_offset */
 };
 
 /* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link.  This
@@ -555,15 +563,15 @@ static reloc_howto_type elf_mips_ctor64_howto =
         0,                     /* rightshift */
         4,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         mips32_64bit_reloc,    /* special_function */
         "R_MIPS_64",           /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        false);                /* pcrel_offset */
+        FALSE);                /* pcrel_offset */
 
 /* The reloc used for the mips16 jump instruction.  */
 static reloc_howto_type elf_mips16_jump_howto =
@@ -571,7 +579,7 @@ static reloc_howto_type elf_mips16_jump_howto =
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         26,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
                                /* This needs complex overflow
@@ -579,10 +587,10 @@ static reloc_howto_type elf_mips16_jump_howto =
                                   bits must match the PC.  */
         mips16_jump_reloc,     /* special_function */
         "R_MIPS16_26",         /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x3ffffff,             /* src_mask */
         0x3ffffff,             /* dst_mask */
-        false);                /* pcrel_offset */
+        FALSE);                /* pcrel_offset */
 
 /* The reloc used for the mips16 gprel instruction.  */
 static reloc_howto_type elf_mips16_gprel_howto =
@@ -590,15 +598,15 @@ static reloc_howto_type elf_mips16_gprel_howto =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         mips16_gprel_reloc,    /* special_function */
         "R_MIPS16_GPREL",      /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0x07ff001f,            /* src_mask */
         0x07ff001f,            /* dst_mask */
-        false);                /* pcrel_offset */
+        FALSE);                /* pcrel_offset */
 
 /* GNU extensions for embedded-pic.  */
 /* High 16 bits of symbol value, pc-relative.  */
@@ -607,15 +615,15 @@ static reloc_howto_type elf_mips_gnu_rel_hi16 =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        true,                  /* pc_relative */
+        TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         mips_elf_hi16_reloc,   /* special_function */
         "R_MIPS_GNU_REL_HI16", /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
-        true);                 /* pcrel_offset */
+        TRUE);                 /* pcrel_offset */
 
 /* Low 16 bits of symbol value, pc-relative.  */
 static reloc_howto_type elf_mips_gnu_rel_lo16 =
@@ -623,15 +631,15 @@ static reloc_howto_type elf_mips_gnu_rel_lo16 =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        true,                  /* pc_relative */
+        TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         mips_elf_lo16_reloc,   /* special_function */
         "R_MIPS_GNU_REL_LO16", /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
-        true);                 /* pcrel_offset */
+        TRUE);                 /* pcrel_offset */
 
 /* 16 bit offset for pc-relative branches.  */
 static reloc_howto_type elf_mips_gnu_rel16_s2 =
@@ -639,15 +647,15 @@ static reloc_howto_type elf_mips_gnu_rel16_s2 =
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        true,                  /* pc_relative */
+        TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_GNU_REL16_S2", /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
-        true);                 /* pcrel_offset */
+        TRUE);                 /* pcrel_offset */
 
 /* 64 bit pc-relative.  */
 static reloc_howto_type elf_mips_gnu_pcrel64 =
@@ -655,15 +663,15 @@ static reloc_howto_type elf_mips_gnu_pcrel64 =
         0,                     /* rightshift */
         4,                     /* size (0 = byte, 1 = short, 2 = long) */
         64,                    /* bitsize */
-        true,                  /* pc_relative */
+        TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_PC64",         /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         MINUS_ONE,             /* src_mask */
         MINUS_ONE,             /* dst_mask */
-        true);                 /* pcrel_offset */
+        TRUE);                 /* pcrel_offset */
 
 /* 32 bit pc-relative.  */
 static reloc_howto_type elf_mips_gnu_pcrel32 =
@@ -671,15 +679,15 @@ static reloc_howto_type elf_mips_gnu_pcrel32 =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        true,                  /* pc_relative */
+        TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        mips_elf_generic_reloc, /* special_function */
         "R_MIPS_PC32",         /* name */
-        true,                  /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        true);                 /* pcrel_offset */
+        TRUE);                 /* pcrel_offset */
 
 /* GNU extension to record C++ vtable hierarchy */
 static reloc_howto_type elf_mips_gnu_vtinherit_howto =
@@ -687,15 +695,15 @@ static reloc_howto_type elf_mips_gnu_vtinherit_howto =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         NULL,                  /* special_function */
         "R_MIPS_GNU_VTINHERIT", /* name */
-        false,                 /* partial_inplace */
+        FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        false);                /* pcrel_offset */
+        FALSE);                /* pcrel_offset */
 
 /* GNU extension to record C++ vtable member usage */
 static reloc_howto_type elf_mips_gnu_vtentry_howto =
@@ -703,15 +711,42 @@ static reloc_howto_type elf_mips_gnu_vtentry_howto =
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
-        false,                 /* pc_relative */
+        FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_elf_rel_vtable_reloc_fn, /* special_function */
         "R_MIPS_GNU_VTENTRY",  /* name */
-        false,                 /* partial_inplace */
+        FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        false);                /* pcrel_offset */
+        FALSE);                /* pcrel_offset */
+
+/* We use this instead of bfd_elf_generic_reloc because the latter
+   gets the handling of zero addends wrong. */
+static bfd_reloc_status_type
+mips_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section,
+                       output_bfd, error_message)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     PTR data ATTRIBUTE_UNUSED;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message ATTRIBUTE_UNUSED;
+{
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
+  if (output_bfd != (bfd *) NULL
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && (symbol->flags & BSF_LOCAL) != 0)
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  /* Just go on, nothing to see here.  */
+  return bfd_reloc_continue;
+}
 
 /* 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
@@ -758,7 +793,7 @@ mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, input_section,
      to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -768,17 +803,17 @@ mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, input_section,
 
   if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
     {
-      boolean relocateable;
+      bfd_boolean relocateable;
       bfd_vma gp;
 
       if (ret == bfd_reloc_undefined)
        abort ();
 
       if (output_bfd != NULL)
-       relocateable = true;
+       relocateable = TRUE;
       else
        {
-         relocateable = false;
+         relocateable = FALSE;
          output_bfd = symbol->section->output_section->owner;
        }
 
@@ -902,7 +937,7 @@ mips_elf_lo16_reloc (abfd, reloc_entry, symbol, data, input_section,
 
       /* FIXME: Does this case ever occur?  */
 
-      ret = mips_elf_final_gp (output_bfd, symbol, true, error_message, &gp);
+      ret = mips_elf_final_gp (output_bfd, symbol, TRUE, error_message, &gp);
       if (ret != bfd_reloc_ok)
        return ret;
 
@@ -920,8 +955,8 @@ mips_elf_lo16_reloc (abfd, reloc_entry, symbol, data, input_section,
     }
 
   /* Now do the LO16 reloc in the usual way.  */
-  return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
-                               input_section, output_bfd, error_message);
+  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
@@ -953,26 +988,20 @@ mips_elf_got16_reloc (abfd, reloc_entry, symbol, data, input_section,
      to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
 
-  /* If we're relocating, and this is a local symbol, we can handle it
-     just like HI16.  */
-  if (output_bfd != (bfd *) NULL
-      && (symbol->flags & BSF_SECTION_SYM) != 0)
-    return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
-                               input_section, output_bfd, error_message);
-
-  abort ();
+  return mips_elf_hi16_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
+/* Set the GP value for OUTPUT_BFD.  Returns FALSE if this is a
    dangerous relocation.  */
 
-static boolean
+static bfd_boolean
 mips_elf_assign_gp (output_bfd, pgp)
      bfd *output_bfd;
      bfd_vma *pgp;
@@ -984,7 +1013,7 @@ mips_elf_assign_gp (output_bfd, pgp)
   /* If we've already figured out what GP will be, just return it.  */
   *pgp = _bfd_get_gp_value (output_bfd);
   if (*pgp)
-    return true;
+    return TRUE;
 
   count = bfd_get_symcount (output_bfd);
   sym = bfd_get_outsymbols (output_bfd);
@@ -1014,10 +1043,10 @@ mips_elf_assign_gp (output_bfd, pgp)
       /* Only get the error once.  */
       *pgp = 4;
       _bfd_set_gp_value (output_bfd, *pgp);
-      return false;
+      return FALSE;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* We have to figure out the gp value, so that we can adjust the
@@ -1030,7 +1059,7 @@ static bfd_reloc_status_type
 mips_elf_final_gp (output_bfd, symbol, relocateable, error_message, pgp)
      bfd *output_bfd;
      asymbol *symbol;
-     boolean relocateable;
+     bfd_boolean relocateable;
      char **error_message;
      bfd_vma *pgp;
 {
@@ -1080,27 +1109,25 @@ _bfd_mips_elf32_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
      bfd *output_bfd;
      char **error_message;
 {
-  boolean relocateable;
+  bfd_boolean relocateable;
   bfd_reloc_status_type ret;
   bfd_vma gp;
 
-  /* If we're relocating, and this is an external symbol with no
-     addend, we don't want to change anything.  We will only have an
-     addend if this is a newly created reloc, not read from an ELF
-     file.  */
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
 
   if (output_bfd != (bfd *) NULL)
-    relocateable = true;
+    relocateable = TRUE;
   else
     {
-      relocateable = false;
+      relocateable = FALSE;
       output_bfd = symbol->section->output_section->owner;
     }
 
@@ -1117,10 +1144,6 @@ _bfd_mips_elf32_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
 /* Do a R_MIPS_GPREL32 relocation.  This is a 32 bit value which must
    become the offset from the gp register.  */
 
-static bfd_reloc_status_type gprel32_with_gp PARAMS ((bfd *, asymbol *,
-                                                     arelent *, asection *,
-                                                     boolean, PTR, bfd_vma));
-
 static bfd_reloc_status_type
 mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
                        output_bfd, error_message)
@@ -1132,17 +1155,15 @@ mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
      bfd *output_bfd;
      char **error_message;
 {
-  boolean relocateable;
+  bfd_boolean relocateable;
   bfd_reloc_status_type ret;
   bfd_vma gp;
 
-  /* If we're relocating, and this is an external symbol with no
-     addend, we don't want to change anything.  We will only have an
-     addend if this is a newly created reloc, not read from an ELF
-     file.  */
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       *error_message = (char *)
        _("32bits gp relative relocation occurs for an external symbol");
@@ -1150,21 +1171,18 @@ mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
     }
 
   if (output_bfd != (bfd *) NULL)
-    {
-      relocateable = true;
-      gp = _bfd_get_gp_value (output_bfd);
-    }
+    relocateable = TRUE;
   else
     {
-      relocateable = false;
+      relocateable = FALSE;
       output_bfd = symbol->section->output_section->owner;
-
-      ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
-                              error_message, &gp);
-      if (ret != bfd_reloc_ok)
-       return ret;
     }
 
+  ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
+                          error_message, &gp);
+  if (ret != bfd_reloc_ok)
+    return ret;
+
   return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
                          relocateable, data, gp);
 }
@@ -1176,12 +1194,12 @@ gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
      asymbol *symbol;
      arelent *reloc_entry;
      asection *input_section;
-     boolean relocateable;
+     bfd_boolean relocateable;
      PTR data;
      bfd_vma gp;
 {
   bfd_vma relocation;
-  unsigned long val;
+  bfd_vma val;
 
   if (bfd_is_com_section (symbol->section))
     relocation = 0;
@@ -1194,16 +1212,11 @@ gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  if (reloc_entry->howto->src_mask == 0)
-    {
-      /* This case arises with the 64-bit MIPS ELF ABI.  */
-      val = 0;
-    }
-  else
-    val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
   /* Set val to the offset into the section or symbol.  */
-  val += reloc_entry->addend;
+  val = reloc_entry->addend;
+
+  if (reloc_entry->howto->partial_inplace)
+    val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
 
   /* Adjust val for the final section location and GP value.  If we
      are producing relocateable output, we don't want to do this for
@@ -1212,7 +1225,10 @@ gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
       || (symbol->flags & BSF_SECTION_SYM) != 0)
     val += relocation - gp;
 
-  bfd_put_32 (abfd, (bfd_vma) val, (bfd_byte *) data + reloc_entry->address);
+  if (reloc_entry->howto->partial_inplace)
+    bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
+  else
+    reloc_entry->addend = val;
 
   if (relocateable)
     reloc_entry->address += input_section->output_offset;
@@ -1240,8 +1256,8 @@ mips32_64bit_reloc (abfd, reloc_entry, symbol, data, input_section,
   unsigned long val;
   bfd_size_type addr;
 
-  r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
-                            input_section, output_bfd, error_message);
+  r = mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+                             input_section, output_bfd, error_message);
   if (r != bfd_reloc_continue)
     return r;
 
@@ -1290,13 +1306,13 @@ mips16_jump_reloc (abfd, reloc_entry, symbol, data, input_section,
 
   /* FIXME.  */
   {
-    static boolean warned;
+    static bfd_boolean warned;
 
     if (! warned)
       (*_bfd_error_handler)
        (_("Linking mips16 objects into %s format is not supported"),
         bfd_get_target (input_section->output_section->owner));
-    warned = true;
+    warned = TRUE;
   }
 
   return bfd_reloc_undefined;
@@ -1315,29 +1331,29 @@ mips16_gprel_reloc (abfd, reloc_entry, symbol, data, input_section,
      bfd *output_bfd;
      char **error_message;
 {
-  boolean relocateable;
+  bfd_boolean relocateable;
   bfd_reloc_status_type ret;
   bfd_vma gp;
-  unsigned short extend, insn;
-  unsigned long final;
+  unsigned short extend = 0;
+  unsigned short insn = 0;
+  bfd_signed_vma val;
+  bfd_vma relocation;
 
-  /* If we're relocating, and this is an external symbol with no
-     addend, we don't want to change anything.  We will only have an
-     addend if this is a newly created reloc, not read from an ELF
-     file.  */
+  /* If we're relocating, and this is an external symbol, we don't want
+     to change anything.  */
   if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
-      && reloc_entry->addend == 0)
+      && (symbol->flags & BSF_LOCAL) != 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
 
   if (output_bfd != NULL)
-    relocateable = true;
+    relocateable = TRUE;
   else
     {
-      relocateable = false;
+      relocateable = FALSE;
       output_bfd = symbol->section->output_section->owner;
     }
 
@@ -1349,33 +1365,55 @@ mips16_gprel_reloc (abfd, reloc_entry, symbol, data, input_section,
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  /* Pick up the mips16 extend instruction and the real instruction.  */
-  extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
-  insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
-
-  /* Stuff the current addend back as a 32 bit value, do the usual
-     relocation, and then clean up.  */
-  bfd_put_32 (abfd,
-             (bfd_vma) (((extend & 0x1f) << 11)
-                        | (extend & 0x7e0)
-                        | (insn & 0x1f)),
-             (bfd_byte *) data + reloc_entry->address);
-
-  ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
-                                      input_section, relocateable, data, gp);
-
-  final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-  bfd_put_16 (abfd,
-             (bfd_vma) ((extend & 0xf800)
-                        | ((final >> 11) & 0x1f)
-                        | (final & 0x7e0)),
-             (bfd_byte *) data + reloc_entry->address);
-  bfd_put_16 (abfd,
-             (bfd_vma) ((insn & 0xffe0)
-                        | (final & 0x1f)),
-             (bfd_byte *) data + reloc_entry->address + 2);
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
 
-  return ret;
+  relocation += symbol->section->output_section->vma;
+  relocation += symbol->section->output_offset;
+
+  /* Set val to the offset into the section or symbol.  */
+  val = reloc_entry->addend;
+
+  if (reloc_entry->howto->partial_inplace)
+    {
+      /* Pick up the mips16 extend instruction and the real instruction.  */
+      extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
+      insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
+      val += ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
+    }
+
+  _bfd_mips_elf_sign_extend(val, 16);
+
+  /* Adjust val for the final section location and GP value.  If we
+     are producing relocateable output, we don't want to do this for
+     an external symbol.  */
+  if (! relocateable
+      || (symbol->flags & BSF_SECTION_SYM) != 0)
+    val += relocation - gp;
+
+  if (reloc_entry->howto->partial_inplace)
+    {
+      bfd_put_16 (abfd,
+                 (bfd_vma) ((extend & 0xf800)
+                            | ((val >> 11) & 0x1f)
+                            | (val & 0x7e0)),
+                 (bfd_byte *) data + reloc_entry->address);
+      bfd_put_16 (abfd,
+                 (bfd_vma) ((insn & 0xffe0)
+                            | (val & 0x1f)),
+                 (bfd_byte *) data + reloc_entry->address + 2);
+    }
+  else
+    reloc_entry->addend = val;
+
+  if (relocateable)
+    reloc_entry->address += input_section->output_offset;
+  else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
+    return bfd_reloc_overflow;
+
+  return bfd_reloc_ok;
 }
 
 /* A mapping from BFD reloc types to MIPS ELF reloc types.  */
@@ -1437,11 +1475,12 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
     case BFD_RELOC_CTOR:
       /* We need to handle BFD_RELOC_CTOR specially.
         Select the right relocation (R_MIPS_32 or R_MIPS_64) based on the
-        size of addresses on this architecture.  */
-      if (bfd_arch_bits_per_address (abfd) == 32)
-       return &howto_table[(int) R_MIPS_32];
-      else
+        size of addresses of the ABI.  */
+      if ((elf_elfheader (abfd)->e_flags & (E_MIPS_ABI_O64
+                                           | E_MIPS_ABI_EABI64)) != 0)
        return &elf_mips_ctor64_howto;
+      else
+       return &howto_table[(int) R_MIPS_32];
 
     case BFD_RELOC_MIPS16_JMP:
       return &elf_mips16_jump_howto;
@@ -1469,7 +1508,7 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
 static reloc_howto_type *
 mips_elf32_rtype_to_howto (r_type, rela_p)
      unsigned int r_type;
-     boolean rela_p ATTRIBUTE_UNUSED;
+     bfd_boolean rela_p ATTRIBUTE_UNUSED;
 {
   switch (r_type)
     {
@@ -1508,7 +1547,7 @@ mips_info_to_howto_rel (abfd, cache_ptr, dst)
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  cache_ptr->howto = mips_elf32_rtype_to_howto (r_type, false);
+  cache_ptr->howto = mips_elf32_rtype_to_howto (r_type, FALSE);
 
   /* The addend for a GPREL16 or LITERAL relocation comes from the GP
      value for the object file.  We get the addend now, rather than
@@ -1540,7 +1579,7 @@ mips_info_to_howto_rela (abfd, cache_ptr, dst)
    symbols.  On most ELF targets the split is between static symbols
    and externally visible symbols.  */
 
-static boolean
+static bfd_boolean
 mips_elf_sym_is_global (abfd, sym)
      bfd *abfd ATTRIBUTE_UNUSED;
      asymbol *sym;
@@ -1555,7 +1594,7 @@ mips_elf_sym_is_global (abfd, sym)
 \f
 /* Set the right machine number for a MIPS ELF file.  */
 
-static boolean
+static bfd_boolean
 mips_elf32_object_p (abfd)
      bfd *abfd;
 {
@@ -1565,26 +1604,26 @@ mips_elf32_object_p (abfd)
      sorted correctly such that local symbols precede global symbols,
      and the sh_info field in the symbol table is not always right.  */
   if (SGI_COMPAT (abfd))
-    elf_bad_symtab (abfd) = true;
+    elf_bad_symtab (abfd) = TRUE;
 
   if (ABI_N32_P (abfd))
-    return false;
+    return FALSE;
 
   mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags);
   bfd_default_set_arch_mach (abfd, bfd_arch_mips, mach);
 
-  return true;
+  return TRUE;
 }
 \f
 /* MIPS ELF local labels start with '$', not 'L'.  */
 
-static boolean
+static bfd_boolean
 mips_elf_is_local_label_name (abfd, name)
      bfd *abfd;
      const char *name;
 {
   if (name[0] == '$')
-    return true;
+    return TRUE;
 
   /* On Irix 6, the labels go back to starting with '.', so we accept
      the generic ELF local label syntax as well.  */
@@ -1592,7 +1631,7 @@ mips_elf_is_local_label_name (abfd, name)
 }
 \f
 /* Support for core dump NOTE sections.  */
-static boolean
+static bfd_boolean
 elf32_mips_grok_prstatus (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -1603,7 +1642,7 @@ elf32_mips_grok_prstatus (abfd, note)
   switch (note->descsz)
     {
       default:
-       return false;
+       return FALSE;
 
       case 256:                /* Linux/MIPS */
        /* pr_cursig */
@@ -1624,7 +1663,7 @@ elf32_mips_grok_prstatus (abfd, note)
                                          raw_size, note->descpos + offset);
 }
 
-static boolean
+static bfd_boolean
 elf32_mips_grok_psinfo (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -1632,7 +1671,7 @@ elf32_mips_grok_psinfo (abfd, note)
   switch (note->descsz)
     {
       default:
-       return false;
+       return FALSE;
 
       case 128:                /* Linux/MIPS elf_prpsinfo */
        elf_tdata (abfd)->core_program
@@ -1653,7 +1692,7 @@ elf32_mips_grok_psinfo (abfd, note)
       command[n - 1] = '\0';
   }
 
-  return true;
+  return TRUE;
 }
 \f
 /* Depending on the target vector we generate some version of Irix
@@ -1676,7 +1715,7 @@ elf32_mips_irix_compat (abfd)
    after the add_symbols entry point has been called for all the
    objects, and before the final_link entry point is called.  */
 
-boolean
+bfd_boolean
 bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -1695,7 +1734,7 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
   *errmsg = NULL;
 
   if (datasec->reloc_count == 0)
-    return true;
+    return TRUE;
 
   /* Read this BFD's symbols if we haven't done so already, or get the cached
      copy if it exists.  */
@@ -1712,7 +1751,7 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
     }
 
   /* Get a copy of the native relocations.  */
-  internal_relocs = (_bfd_elf32_link_read_relocs
+  internal_relocs = (_bfd_elf_link_read_relocs
                     (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
                      info->keep_memory));
   if (internal_relocs == NULL)
@@ -1794,7 +1833,7 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
   if (isymbuf != NULL
       && symtab_hdr->contents != (unsigned char *) isymbuf)
     free (isymbuf);
-  return true;
+  return TRUE;
 
  error_return:
   if (internal_relocs != NULL
@@ -1803,7 +1842,7 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
   if (isymbuf != NULL
       && symtab_hdr->contents != (unsigned char *) isymbuf)
     free (isymbuf);
-  return false;
+  return FALSE;
 }
 \f
 /* ECOFF swapping routines.  These are used when dealing with the
@@ -1855,9 +1894,9 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
    a value of 0x1000, and we are compatible.  */
 #define ELF_MAXPAGESIZE                        0x1000
 
-#define elf_backend_collect            true
-#define elf_backend_type_change_ok     true
-#define elf_backend_can_gc_sections    true
+#define elf_backend_collect            TRUE
+#define elf_backend_type_change_ok     TRUE
+#define elf_backend_can_gc_sections    TRUE
 #define elf_info_to_howto              mips_info_to_howto_rela
 #define elf_info_to_howto_rel          mips_info_to_howto_rel
 #define elf_backend_sym_is_global      mips_elf_sym_is_global
@@ -1904,7 +1943,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 #define elf_backend_may_use_rel_p      1
 #define elf_backend_may_use_rela_p     0
 #define elf_backend_default_use_rela_p 0
-#define elf_backend_sign_extend_vma    true
+#define elf_backend_sign_extend_vma    TRUE
 
 #define elf_backend_discard_info       _bfd_mips_elf_discard_info
 #define elf_backend_ignore_discarded_relocs \
@@ -1914,6 +1953,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 #define bfd_elf32_bfd_is_local_label_name \
                                        mips_elf_is_local_label_name
 #define bfd_elf32_find_nearest_line    _bfd_mips_elf_find_nearest_line
+#define bfd_elf32_new_section_hook     _bfd_mips_elf_new_section_hook
 #define bfd_elf32_set_section_contents _bfd_mips_elf_set_section_contents
 #define bfd_elf32_bfd_get_relocated_section_contents \
                                _bfd_elf_mips_get_relocated_section_contents
This page took 0.078203 seconds and 4 git commands to generate.