include/
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index 4c5496516a8e06d2e68a4cead8ce3a99ce9839a5..4d73239b3a1a4169dab13ce9cf500f989c03438b 100644 (file)
@@ -1,6 +1,6 @@
 /* MIPS-specific support for ELF
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003 Free Software Foundation, Inc.
+   2003, 2004, 2005 Free Software Foundation, Inc.
 
    Most of the information added by Ian Lance Taylor, Cygnus Support,
    <ian@cygnus.com>.
@@ -369,115 +369,24 @@ typedef struct runtime_pdr {
 #define cbRPDR sizeof (RPDR)
 #define rpdNil ((pRPDR) 0)
 \f
-static struct bfd_hash_entry *mips_elf_link_hash_newfunc
-  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static void ecoff_swap_rpdr_out
-  PARAMS ((bfd *, const RPDR *, struct rpdr_ext *));
-static bfd_boolean mips_elf_create_procedure_table
-  PARAMS ((PTR, bfd *, struct bfd_link_info *, asection *,
-          struct ecoff_debug_info *));
-static bfd_boolean mips_elf_check_mips16_stubs
-  PARAMS ((struct mips_elf_link_hash_entry *, PTR));
-static void bfd_mips_elf32_swap_gptab_in
-  PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *));
-static void bfd_mips_elf32_swap_gptab_out
-  PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *));
-static void bfd_elf32_swap_compact_rel_out
-  PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *));
-static void bfd_elf32_swap_crinfo_out
-  PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *));
-static int sort_dynamic_relocs
-  PARAMS ((const void *, const void *));
-static int sort_dynamic_relocs_64
-  PARAMS ((const void *, const void *));
-static bfd_boolean mips_elf_output_extsym
-  PARAMS ((struct mips_elf_link_hash_entry *, PTR));
-static int gptab_compare PARAMS ((const void *, const void *));
-static asection * mips_elf_rel_dyn_section PARAMS ((bfd *, bfd_boolean));
-static asection * mips_elf_got_section PARAMS ((bfd *, bfd_boolean));
-static struct mips_got_info *mips_elf_got_info
-  PARAMS ((bfd *, asection **));
-static long mips_elf_get_global_gotsym_index PARAMS ((bfd *abfd));
-static bfd_vma mips_elf_local_got_index
-  PARAMS ((bfd *, bfd *, struct bfd_link_info *, bfd_vma));
-static bfd_vma mips_elf_global_got_index
-  PARAMS ((bfd *, bfd *, struct elf_link_hash_entry *));
-static bfd_vma mips_elf_got_page
-  PARAMS ((bfd *, bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *));
-static bfd_vma mips_elf_got16_entry
-  PARAMS ((bfd *, bfd *, struct bfd_link_info *, bfd_vma, bfd_boolean));
-static bfd_vma mips_elf_got_offset_from_index
-  PARAMS ((bfd *, bfd *, bfd *, bfd_vma));
 static struct mips_got_entry *mips_elf_create_local_got_entry
-  PARAMS ((bfd *, bfd *, struct mips_got_info *, asection *, bfd_vma));
-static bfd_boolean mips_elf_sort_hash_table
-  PARAMS ((struct bfd_link_info *, unsigned long));
+  (bfd *, bfd *, struct mips_got_info *, asection *, bfd_vma);
 static bfd_boolean mips_elf_sort_hash_table_f
-  PARAMS ((struct mips_elf_link_hash_entry *, PTR));
-static bfd_boolean mips_elf_record_local_got_symbol
-  PARAMS ((bfd *, long, bfd_vma, struct mips_got_info *));
-static bfd_boolean mips_elf_record_global_got_symbol
-  PARAMS ((struct elf_link_hash_entry *, bfd *, struct bfd_link_info *,
-          struct mips_got_info *));
-static const Elf_Internal_Rela *mips_elf_next_relocation
-  PARAMS ((bfd *, unsigned int, const Elf_Internal_Rela *,
-          const Elf_Internal_Rela *));
-static bfd_boolean mips_elf_local_relocation_p
-  PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, bfd_boolean));
-static bfd_boolean mips_elf_overflow_p PARAMS ((bfd_vma, int));
-static bfd_vma mips_elf_high PARAMS ((bfd_vma));
-static bfd_vma mips_elf_higher PARAMS ((bfd_vma));
-static bfd_vma mips_elf_highest PARAMS ((bfd_vma));
-static bfd_boolean mips_elf_create_compact_rel_section
-  PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean mips_elf_create_got_section
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean));
-static bfd_reloc_status_type mips_elf_calculate_relocation
-  PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *,
-          const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
-          Elf_Internal_Sym *, asection **, bfd_vma *, const char **,
-          bfd_boolean *, bfd_boolean));
-static bfd_vma mips_elf_obtain_contents
-  PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *));
-static bfd_boolean mips_elf_perform_relocation
-  PARAMS ((struct bfd_link_info *, reloc_howto_type *,
-          const Elf_Internal_Rela *, bfd_vma, bfd *, asection *, bfd_byte *,
-          bfd_boolean));
+  (struct mips_elf_link_hash_entry *, void *);
+static bfd_vma mips_elf_high
+  (bfd_vma);
 static bfd_boolean mips_elf_stub_section_p
-  PARAMS ((bfd *, asection *));
-static void mips_elf_allocate_dynamic_relocations
-  PARAMS ((bfd *, unsigned int));
+  (bfd *, asection *);
 static bfd_boolean mips_elf_create_dynamic_relocation
-  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
-          struct mips_elf_link_hash_entry *, asection *,
-          bfd_vma, bfd_vma *, asection *));
-static void mips_set_isa_flags PARAMS ((bfd *));
-static INLINE char* elf_mips_abi_name PARAMS ((bfd *));
-static void mips_elf_irix6_finish_dynamic_symbol
-  PARAMS ((bfd *, const char *, Elf_Internal_Sym *));
-static bfd_boolean mips_mach_extends_p PARAMS ((unsigned long, unsigned long));
-static bfd_boolean mips_32bit_flags_p PARAMS ((flagword));
-static INLINE hashval_t mips_elf_hash_bfd_vma PARAMS ((bfd_vma));
-static hashval_t mips_elf_got_entry_hash PARAMS ((const PTR));
-static int mips_elf_got_entry_eq PARAMS ((const PTR, const PTR));
-
-static bfd_boolean mips_elf_multi_got
-  PARAMS ((bfd *, struct bfd_link_info *, struct mips_got_info *,
-          asection *, bfd_size_type));
-static hashval_t mips_elf_multi_got_entry_hash PARAMS ((const PTR));
-static int mips_elf_multi_got_entry_eq PARAMS ((const PTR, const PTR));
-static hashval_t mips_elf_bfd2got_entry_hash PARAMS ((const PTR));
-static int mips_elf_bfd2got_entry_eq PARAMS ((const PTR, const PTR));
-static int mips_elf_make_got_per_bfd PARAMS ((void **, void *));
-static int mips_elf_merge_gots PARAMS ((void **, void *));
-static int mips_elf_set_global_got_offset PARAMS ((void**, void *));
-static int mips_elf_resolve_final_got_entry PARAMS ((void**, void *));
-static void mips_elf_resolve_final_got_entries
-  PARAMS ((struct mips_got_info *));
+  (bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
+   struct mips_elf_link_hash_entry *, asection *, bfd_vma,
+   bfd_vma *, asection *);
+static hashval_t mips_elf_got_entry_hash
+  (const void *);
 static bfd_vma mips_elf_adjust_gp
-  PARAMS ((bfd *, struct mips_got_info *, bfd *));
+  (bfd *, struct mips_got_info *, bfd *);
 static struct mips_got_info *mips_elf_got_for_ibfd
-  PARAMS ((struct mips_got_info *, bfd *));
+  (struct mips_got_info *, bfd *);
 
 /* This will be used when we sort the dynamic relocation records.  */
 static bfd *reldyn_sorting_bfd;
@@ -507,8 +416,7 @@ static bfd *reldyn_sorting_bfd;
   (NEWABI_P (abfd) ? ".MIPS.options" : ".options")
 
 /* The name of the stub section.  */
-#define MIPS_ELF_STUB_SECTION_NAME(abfd) \
-  (NEWABI_P (abfd) ? ".MIPS.stubs" : ".stub")
+#define MIPS_ELF_STUB_SECTION_NAME(abfd) ".MIPS.stubs"
 
 /* The size of an external REL relocation.  */
 #define MIPS_ELF_REL_SIZE(abfd) \
@@ -541,17 +449,8 @@ static bfd *reldyn_sorting_bfd;
    : bfd_put_32 (abfd, val, ptr))
 
 /* Add a dynamic symbol table-entry.  */
-#ifdef BFD64
-#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val)                     \
-  (ABI_64_P (elf_hash_table (info)->dynobj)                            \
-   ? bfd_elf64_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val)  \
-   : bfd_elf32_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val))
-#else
-#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val)                     \
-  (ABI_64_P (elf_hash_table (info)->dynobj)                            \
-   ? (abort (), FALSE)                                                 \
-   : bfd_elf32_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val))
-#endif
+#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val)     \
+  _bfd_elf_add_dynamic_entry (info, tag, val)
 
 #define MIPS_ELF_RTYPE_TO_HOWTO(abfd, rtype, rela)                     \
   (get_elf_backend_data (abfd)->elf_backend_mips_rtype_to_howto (rtype, rela))
@@ -576,6 +475,7 @@ static bfd *reldyn_sorting_bfd;
 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
    from smaller values.  Start with zero, widen, *then* decrement.  */
 #define MINUS_ONE      (((bfd_vma)0) - 1)
+#define MINUS_TWO      (((bfd_vma)0) - 2)
 
 /* The number of local .got entries we reserve.  */
 #define MIPS_RESERVED_GOTNO (2)
@@ -587,17 +487,20 @@ static bfd *reldyn_sorting_bfd;
    offsets from $gp.  */
 #define MIPS_ELF_GOT_MAX_SIZE(abfd) (ELF_MIPS_GP_OFFSET(abfd) + 0x7fff)
 
-/* Instructions which appear in a stub.  For some reason the stub is
-   slightly different on an SGI system.  */
+/* Instructions which appear in a stub.  */
 #define STUB_LW(abfd)                                          \
   ((ABI_64_P (abfd)                                            \
     ? 0xdf998010               /* ld t9,0x8010(gp) */          \
     : 0x8f998010))              /* lw t9,0x8010(gp) */
 #define STUB_MOVE(abfd)                                         \
-  (SGI_COMPAT (abfd) ? 0x03e07825 : 0x03e07821)         /* move t7,ra */
-#define STUB_JALR 0x0320f809                           /* jal t9 */
+   ((ABI_64_P (abfd)                                           \
+     ? 0x03e0782d              /* daddu t7,ra */               \
+     : 0x03e07821))            /* addu t7,ra */
+#define STUB_JALR 0x0320f809   /* jalr t9,ra */
 #define STUB_LI16(abfd)                                         \
-  (SGI_COMPAT (abfd) ? 0x34180000 : 0x24180000)         /* ori t8,zero,0 */
+  ((ABI_64_P (abfd)                                            \
+   ? 0x64180000                        /* daddiu t8,zero,0 */          \
+   : 0x24180000))              /* addiu t8,zero,0 */
 #define MIPS_FUNCTION_STUB_SIZE (16)
 
 /* The name of the dynamic interpreter.  This is put in the .interp
@@ -677,7 +580,7 @@ static bfd *reldyn_sorting_bfd;
 #define mips_elf_link_hash_traverse(table, func, info)                 \
   (elf_link_hash_traverse                                              \
    (&(table)->root,                                                    \
-    (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
+    (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func),   \
     (info)))
 
 /* Get the MIPS ELF linker hash table from a link_info structure.  */
@@ -688,28 +591,24 @@ static bfd *reldyn_sorting_bfd;
 /* Create an entry in a MIPS ELF linker hash table.  */
 
 static struct bfd_hash_entry *
-mips_elf_link_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
+                           struct bfd_hash_table *table, const char *string)
 {
   struct mips_elf_link_hash_entry *ret =
     (struct mips_elf_link_hash_entry *) entry;
 
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
-  if (ret == (struct mips_elf_link_hash_entry *) NULL)
-    ret = ((struct mips_elf_link_hash_entry *)
-          bfd_hash_allocate (table,
-                             sizeof (struct mips_elf_link_hash_entry)));
-  if (ret == (struct mips_elf_link_hash_entry *) NULL)
+  if (ret == NULL)
+    ret = bfd_hash_allocate (table, sizeof (struct mips_elf_link_hash_entry));
+  if (ret == NULL)
     return (struct bfd_hash_entry *) ret;
 
   /* Call the allocation method of the superclass.  */
   ret = ((struct mips_elf_link_hash_entry *)
         _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
                                     table, string));
-  if (ret != (struct mips_elf_link_hash_entry *) NULL)
+  if (ret != NULL)
     {
       /* Set local fields.  */
       memset (&ret->esym, 0, sizeof (EXTR));
@@ -730,17 +629,15 @@ mips_elf_link_hash_newfunc (entry, table, string)
 }
 
 bfd_boolean
-_bfd_mips_elf_new_section_hook (abfd, sec)
-     bfd *abfd;
-     asection *sec;
+_bfd_mips_elf_new_section_hook (bfd *abfd, asection *sec)
 {
   struct _mips_elf_section_data *sdata;
   bfd_size_type amt = sizeof (*sdata);
 
-  sdata = (struct _mips_elf_section_data *) bfd_zalloc (abfd, amt);
+  sdata = bfd_zalloc (abfd, amt);
   if (sdata == NULL)
     return FALSE;
-  sec->used_by_bfd = (PTR) sdata;
+  sec->used_by_bfd = sdata;
 
   return _bfd_elf_new_section_hook (abfd, sec);
 }
@@ -749,23 +646,21 @@ _bfd_mips_elf_new_section_hook (abfd, sec)
    ecoff_debug_info structure.  */
 
 bfd_boolean
-_bfd_mips_elf_read_ecoff_info (abfd, section, debug)
-     bfd *abfd;
-     asection *section;
-     struct ecoff_debug_info *debug;
+_bfd_mips_elf_read_ecoff_info (bfd *abfd, asection *section,
+                              struct ecoff_debug_info *debug)
 {
   HDRR *symhdr;
   const struct ecoff_debug_swap *swap;
-  char *ext_hdr = NULL;
+  char *ext_hdr;
 
   swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
   memset (debug, 0, sizeof (*debug));
 
-  ext_hdr = (char *) bfd_malloc (swap->external_hdr_size);
+  ext_hdr = bfd_malloc (swap->external_hdr_size);
   if (ext_hdr == NULL && swap->external_hdr_size != 0)
     goto error_return;
 
-  if (! bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
+  if (! bfd_get_section_contents (abfd, section, ext_hdr, 0,
                                  swap->external_hdr_size))
     goto error_return;
 
@@ -780,30 +675,29 @@ _bfd_mips_elf_read_ecoff_info (abfd, section, debug)
   else                                                                 \
     {                                                                  \
       bfd_size_type amt = (bfd_size_type) size * symhdr->count;                \
-      debug->ptr = (type) bfd_malloc (amt);                            \
+      debug->ptr = bfd_malloc (amt);                                   \
       if (debug->ptr == NULL)                                          \
        goto error_return;                                              \
-      if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0    \
+      if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0               \
          || bfd_bread (debug->ptr, amt, abfd) != amt)                  \
        goto error_return;                                              \
     }
 
   READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
-  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
-  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
-  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
-  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
+  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
+  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
+  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
+  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
   READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
        union aux_ext *);
   READ (ss, cbSsOffset, issMax, sizeof (char), char *);
   READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
-  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
-  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
-  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
+  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
+  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
+  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *);
 #undef READ
 
   debug->fdr = NULL;
-  debug->adjust = NULL;
 
   return TRUE;
 
@@ -838,10 +732,7 @@ _bfd_mips_elf_read_ecoff_info (abfd, section, debug)
 /* Swap RPDR (runtime procedure table entry) for output.  */
 
 static void
-ecoff_swap_rpdr_out (abfd, in, ex)
-     bfd *abfd;
-     const RPDR *in;
-     struct rpdr_ext *ex;
+ecoff_swap_rpdr_out (bfd *abfd, const RPDR *in, struct rpdr_ext *ex)
 {
   H_PUT_S32 (abfd, in->adr, ex->p_adr);
   H_PUT_32 (abfd, in->regmask, ex->p_regmask);
@@ -862,18 +753,15 @@ ecoff_swap_rpdr_out (abfd, in, ex)
 /* Create a runtime procedure table from the .mdebug section.  */
 
 static bfd_boolean
-mips_elf_create_procedure_table (handle, abfd, info, s, debug)
-     PTR handle;
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *s;
-     struct ecoff_debug_info *debug;
+mips_elf_create_procedure_table (void *handle, bfd *abfd,
+                                struct bfd_link_info *info, asection *s,
+                                struct ecoff_debug_info *debug)
 {
   const struct ecoff_debug_swap *swap;
   HDRR *hdr = &debug->symbolic_header;
   RPDR *rpdr, *rp;
   struct rpdr_ext *erp;
-  PTR rtproc;
+  void *rtproc;
   struct pdr_ext *epdr;
   struct sym_ext *esym;
   char *ss, **sv;
@@ -900,44 +788,44 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
     {
       size = swap->external_pdr_size;
 
-      epdr = (struct pdr_ext *) bfd_malloc (size * count);
+      epdr = bfd_malloc (size * count);
       if (epdr == NULL)
        goto error_return;
 
-      if (! _bfd_ecoff_get_accumulated_pdr (handle, (PTR) epdr))
+      if (! _bfd_ecoff_get_accumulated_pdr (handle, (bfd_byte *) epdr))
        goto error_return;
 
       size = sizeof (RPDR);
-      rp = rpdr = (RPDR *) bfd_malloc (size * count);
+      rp = rpdr = bfd_malloc (size * count);
       if (rpdr == NULL)
        goto error_return;
 
       size = sizeof (char *);
-      sv = (char **) bfd_malloc (size * count);
+      sv = bfd_malloc (size * count);
       if (sv == NULL)
        goto error_return;
 
       count = hdr->isymMax;
       size = swap->external_sym_size;
-      esym = (struct sym_ext *) bfd_malloc (size * count);
+      esym = bfd_malloc (size * count);
       if (esym == NULL)
        goto error_return;
 
-      if (! _bfd_ecoff_get_accumulated_sym (handle, (PTR) esym))
+      if (! _bfd_ecoff_get_accumulated_sym (handle, (bfd_byte *) esym))
        goto error_return;
 
       count = hdr->issMax;
-      ss = (char *) bfd_malloc (count);
+      ss = bfd_malloc (count);
       if (ss == NULL)
        goto error_return;
-      if (! _bfd_ecoff_get_accumulated_ss (handle, (PTR) ss))
+      if (! _bfd_ecoff_get_accumulated_ss (handle, (bfd_byte *) ss))
        goto error_return;
 
       count = hdr->ipdMax;
       for (i = 0; i < (unsigned long) count; i++, rp++)
        {
-         (*swap->swap_pdr_in) (abfd, (PTR) (epdr + i), &pdr);
-         (*swap->swap_sym_in) (abfd, (PTR) &esym[pdr.isym], &sym);
+         (*swap->swap_pdr_in) (abfd, epdr + i, &pdr);
+         (*swap->swap_sym_in) (abfd, &esym[pdr.isym], &sym);
          rp->adr = sym.value;
          rp->regmask = pdr.regmask;
          rp->regoffset = pdr.regoffset;
@@ -954,7 +842,7 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
 
   size = sizeof (struct rpdr_ext) * (count + 2) + sindex;
   size = BFD_ALIGN (size, 16);
-  rtproc = (PTR) bfd_alloc (abfd, size);
+  rtproc = bfd_alloc (abfd, size);
   if (rtproc == NULL)
     {
       mips_elf_hash_table (info)->procedure_count = 0;
@@ -963,7 +851,7 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
 
   mips_elf_hash_table (info)->procedure_count = count + 2;
 
-  erp = (struct rpdr_ext *) rtproc;
+  erp = rtproc;
   memset (erp, 0, sizeof (struct rpdr_ext));
   erp++;
   str = (char *) rtproc + sizeof (struct rpdr_ext) * (count + 2);
@@ -978,12 +866,12 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
   H_PUT_S32 (abfd, -1, (erp + count)->p_adr);
 
   /* Set the size and contents of .rtproc section.  */
-  s->_raw_size = size;
-  s->contents = (bfd_byte *) rtproc;
+  s->size = size;
+  s->contents = rtproc;
 
   /* Skip this section later on (I don't think this currently
      matters, but someday it might).  */
-  s->link_order_head = (struct bfd_link_order *) NULL;
+  s->link_order_head = NULL;
 
   if (epdr != NULL)
     free (epdr);
@@ -1016,9 +904,8 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
    discard them.  */
 
 static bfd_boolean
-mips_elf_check_mips16_stubs (h, data)
-     struct mips_elf_link_hash_entry *h;
-     PTR data ATTRIBUTE_UNUSED;
+mips_elf_check_mips16_stubs (struct mips_elf_link_hash_entry *h,
+                            void *data ATTRIBUTE_UNUSED)
 {
   if (h->root.root.type == bfd_link_hash_warning)
     h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
@@ -1029,8 +916,7 @@ mips_elf_check_mips16_stubs (h, data)
       /* We don't need the fn_stub; the only references to this symbol
          are 16 bit calls.  Clobber the size to 0 to prevent it from
          being included in the link.  */
-      h->fn_stub->_raw_size = 0;
-      h->fn_stub->_cooked_size = 0;
+      h->fn_stub->size = 0;
       h->fn_stub->flags &= ~SEC_RELOC;
       h->fn_stub->reloc_count = 0;
       h->fn_stub->flags |= SEC_EXCLUDE;
@@ -1042,8 +928,7 @@ mips_elf_check_mips16_stubs (h, data)
       /* We don't need the call_stub; this is a 16 bit function, so
          calls from other 16 bit functions are OK.  Clobber the size
          to 0 to prevent it from being included in the link.  */
-      h->call_stub->_raw_size = 0;
-      h->call_stub->_cooked_size = 0;
+      h->call_stub->size = 0;
       h->call_stub->flags &= ~SEC_RELOC;
       h->call_stub->reloc_count = 0;
       h->call_stub->flags |= SEC_EXCLUDE;
@@ -1055,8 +940,7 @@ mips_elf_check_mips16_stubs (h, data)
       /* We don't need the call_stub; this is a 16 bit function, so
          calls from other 16 bit functions are OK.  Clobber the size
          to 0 to prevent it from being included in the link.  */
-      h->call_fp_stub->_raw_size = 0;
-      h->call_fp_stub->_cooked_size = 0;
+      h->call_fp_stub->size = 0;
       h->call_fp_stub->flags &= ~SEC_RELOC;
       h->call_fp_stub->reloc_count = 0;
       h->call_fp_stub->flags |= SEC_EXCLUDE;
@@ -1065,20 +949,160 @@ mips_elf_check_mips16_stubs (h, data)
   return TRUE;
 }
 \f
+/* R_MIPS16_26 is used for the mips16 jal and jalx instructions.
+   Most mips16 instructions are 16 bits, but these instructions
+   are 32 bits.
+
+   The format of these instructions is:
+
+   +--------------+--------------------------------+
+   |     JALX     | X|   Imm 20:16  |   Imm 25:21  |
+   +--------------+--------------------------------+
+   |                Immediate  15:0                |
+   +-----------------------------------------------+
+
+   JALX is the 5-bit value 00011.  X is 0 for jal, 1 for jalx.
+   Note that the immediate value in the first word is swapped.
+
+   When producing a relocatable object file, R_MIPS16_26 is
+   handled mostly like R_MIPS_26.  In particular, the addend is
+   stored as a straight 26-bit value in a 32-bit instruction.
+   (gas makes life simpler for itself by never adjusting a
+   R_MIPS16_26 reloc to be against a section, so the addend is
+   always zero).  However, the 32 bit instruction is stored as 2
+   16-bit values, rather than a single 32-bit value.  In a
+   big-endian file, the result is the same; in a little-endian
+   file, the two 16-bit halves of the 32 bit value are swapped.
+   This is so that a disassembler can recognize the jal
+   instruction.
+
+   When doing a final link, R_MIPS16_26 is treated as a 32 bit
+   instruction stored as two 16-bit values.  The addend A is the
+   contents of the targ26 field.  The calculation is the same as
+   R_MIPS_26.  When storing the calculated value, reorder the
+   immediate value as shown above, and don't forget to store the
+   value as two 16-bit values.
+
+   To put it in MIPS ABI terms, the relocation field is T-targ26-16,
+   defined as
+
+   big-endian:
+   +--------+----------------------+
+   |        |                      |
+   |        |    targ26-16         |
+   |31    26|25                   0|
+   +--------+----------------------+
+
+   little-endian:
+   +----------+------+-------------+
+   |          |      |             |
+   |  sub1    |      |     sub2    |
+   |0        9|10  15|16         31|
+   +----------+--------------------+
+   where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is
+   ((sub1 << 16) | sub2)).
+
+   When producing a relocatable object file, the calculation is
+   (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
+   When producing a fully linked file, the calculation is
+   let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
+   ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff)
+
+   R_MIPS16_GPREL is used for GP-relative addressing in mips16
+   mode.  A typical instruction will have a format like this:
+
+   +--------------+--------------------------------+
+   |    EXTEND    |     Imm 10:5    |   Imm 15:11  |
+   +--------------+--------------------------------+
+   |    Major     |   rx   |   ry   |   Imm  4:0   |
+   +--------------+--------------------------------+
+
+   EXTEND is the five bit value 11110.  Major is the instruction
+   opcode.
+
+   This is handled exactly like R_MIPS_GPREL16, except that the
+   addend is retrieved and stored as shown in this diagram; that
+   is, the Imm fields above replace the V-rel16 field.
+
+   All we need to do here is shuffle the bits appropriately.  As
+   above, the two 16-bit halves must be swapped on a
+   little-endian system.
+
+   R_MIPS16_HI16 and R_MIPS16_LO16 are used in mips16 mode to
+   access data when neither GP-relative nor PC-relative addressing
+   can be used.  They are handled like R_MIPS_HI16 and R_MIPS_LO16,
+   except that the addend is retrieved and stored as shown above
+   for R_MIPS16_GPREL.
+  */
+void
+_bfd_mips16_elf_reloc_unshuffle (bfd *abfd, int r_type,
+                                bfd_boolean jal_shuffle, bfd_byte *data)
+{
+  bfd_vma extend, insn, val;
+
+  if (r_type != R_MIPS16_26 && r_type != R_MIPS16_GPREL
+      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
+    return;
+
+  /* Pick up the mips16 extend instruction and the real instruction.  */
+  extend = bfd_get_16 (abfd, data);
+  insn = bfd_get_16 (abfd, data + 2);
+  if (r_type == R_MIPS16_26)
+    {
+      if (jal_shuffle)
+       val = ((extend & 0xfc00) << 16) | ((extend & 0x3e0) << 11)
+             | ((extend & 0x1f) << 21) | insn;
+      else
+       val = extend << 16 | insn;
+    }
+  else
+    val = ((extend & 0xf800) << 16) | ((insn & 0xffe0) << 11)
+         | ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
+  bfd_put_32 (abfd, val, data);
+}
+
+void
+_bfd_mips16_elf_reloc_shuffle (bfd *abfd, int r_type,
+                              bfd_boolean jal_shuffle, bfd_byte *data)
+{
+  bfd_vma extend, insn, val;
+
+  if (r_type != R_MIPS16_26 && r_type != R_MIPS16_GPREL
+      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
+    return;
+
+  val = bfd_get_32 (abfd, data);
+  if (r_type == R_MIPS16_26)
+    {
+      if (jal_shuffle)
+       {
+         insn = val & 0xffff;
+         extend = ((val >> 16) & 0xfc00) | ((val >> 11) & 0x3e0)
+                  | ((val >> 21) & 0x1f);
+       }
+      else
+       {
+         insn = val & 0xffff;
+         extend = val >> 16;
+       }
+    }
+  else
+    {
+      insn = ((val >> 11) & 0xffe0) | (val & 0x1f);
+      extend = ((val >> 16) & 0xf800) | ((val >> 11) & 0x1f) | (val & 0x7e0);
+    }
+  bfd_put_16 (abfd, insn, data + 2);
+  bfd_put_16 (abfd, extend, data);
+}
+
 bfd_reloc_status_type
-_bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
-                              relocatable, data, gp)
-     bfd *abfd;
-     asymbol *symbol;
-     arelent *reloc_entry;
-     asection *input_section;
-     bfd_boolean relocatable;
-     PTR data;
-     bfd_vma gp;
+_bfd_mips_elf_gprel16_with_gp (bfd *abfd, asymbol *symbol,
+                              arelent *reloc_entry, asection *input_section,
+                              bfd_boolean relocatable, void *data, bfd_vma gp)
 {
   bfd_vma relocation;
-  unsigned long insn = 0;
   bfd_signed_vma val;
+  bfd_reloc_status_type status;
 
   if (bfd_is_com_section (symbol->section))
     relocation = 0;
@@ -1088,19 +1112,13 @@ _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
   relocation += symbol->section->output_section->vma;
   relocation += symbol->section->output_offset;
 
-  if (reloc_entry->address > input_section->_cooked_size)
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
     return bfd_reloc_outofrange;
 
   /* Set val to the offset into the section or symbol.  */
   val = reloc_entry->addend;
 
-  if (reloc_entry->howto->partial_inplace)
-    {
-      insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-      val += insn & 0xffff;
-    }
-
-  _bfd_mips_elf_sign_extend(val, 16);
+  _bfd_mips_elf_sign_extend (val, 16);
 
   /* Adjust val for the final section location and GP value.  If we
      are producing relocatable output, we don't want to do this for
@@ -1111,17 +1129,220 @@ _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
 
   if (reloc_entry->howto->partial_inplace)
     {
-      insn = (insn & ~0xffff) | (val & 0xffff);
-      bfd_put_32 (abfd, (bfd_vma) insn,
-                 (bfd_byte *) data + reloc_entry->address);
+      status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
+                                      (bfd_byte *) data
+                                      + reloc_entry->address);
+      if (status != bfd_reloc_ok)
+       return status;
     }
   else
     reloc_entry->addend = val;
 
   if (relocatable)
     reloc_entry->address += input_section->output_offset;
-  else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
-    return bfd_reloc_overflow;
+
+  return bfd_reloc_ok;
+}
+
+/* Used to store a REL high-part relocation such as R_MIPS_HI16 or
+   R_MIPS_GOT16.  REL is the relocation, INPUT_SECTION is the section
+   that contains the relocation field and DATA points to the start of
+   INPUT_SECTION.  */
+
+struct mips_hi16
+{
+  struct mips_hi16 *next;
+  bfd_byte *data;
+  asection *input_section;
+  arelent rel;
+};
+
+/* FIXME: This should not be a static variable.  */
+
+static struct mips_hi16 *mips_hi16_list;
+
+/* A howto special_function for REL *HI16 relocations.  We can only
+   calculate the correct value once we've seen the partnering
+   *LO16 relocation, so just save the information for later.
+
+   The ABI requires that the *LO16 immediately follow the *HI16.
+   However, as a GNU extension, we permit an arbitrary number of
+   *HI16s to be associated with a single *LO16.  This significantly
+   simplies the relocation handling in gcc.  */
+
+bfd_reloc_status_type
+_bfd_mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+                         asymbol *symbol ATTRIBUTE_UNUSED, void *data,
+                         asection *input_section, bfd *output_bfd,
+                         char **error_message ATTRIBUTE_UNUSED)
+{
+  struct mips_hi16 *n;
+
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+    return bfd_reloc_outofrange;
+
+  n = bfd_malloc (sizeof *n);
+  if (n == NULL)
+    return bfd_reloc_outofrange;
+
+  n->next = mips_hi16_list;
+  n->data = data;
+  n->input_section = input_section;
+  n->rel = *reloc_entry;
+  mips_hi16_list = n;
+
+  if (output_bfd != NULL)
+    reloc_entry->address += input_section->output_offset;
+
+  return bfd_reloc_ok;
+}
+
+/* A howto special_function for REL R_MIPS_GOT16 relocations.  This is just
+   like any other 16-bit relocation when applied to global symbols, but is
+   treated in the same as R_MIPS_HI16 when applied to local symbols.  */
+
+bfd_reloc_status_type
+_bfd_mips_elf_got16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+                          void *data, asection *input_section,
+                          bfd *output_bfd, char **error_message)
+{
+  if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+      || bfd_is_und_section (bfd_get_section (symbol))
+      || bfd_is_com_section (bfd_get_section (symbol)))
+    /* The relocation is against a global symbol.  */
+    return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+                                       input_section, output_bfd,
+                                       error_message);
+
+  return _bfd_mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
+                                  input_section, output_bfd, error_message);
+}
+
+/* A howto special_function for REL *LO16 relocations.  The *LO16 itself
+   is a straightforward 16 bit inplace relocation, but we must deal with
+   any partnering high-part relocations as well.  */
+
+bfd_reloc_status_type
+_bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+                         void *data, asection *input_section,
+                         bfd *output_bfd, char **error_message)
+{
+  bfd_vma vallo;
+  bfd_byte *location = (bfd_byte *) data + reloc_entry->address;
+
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+    return bfd_reloc_outofrange;
+
+  _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE,
+                                  location);
+  vallo = bfd_get_32 (abfd, location);
+  _bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, FALSE,
+                                location);
+
+  while (mips_hi16_list != NULL)
+    {
+      bfd_reloc_status_type ret;
+      struct mips_hi16 *hi;
+
+      hi = mips_hi16_list;
+
+      /* R_MIPS_GOT16 relocations are something of a special case.  We
+        want to install the addend in the same way as for a R_MIPS_HI16
+        relocation (with a rightshift of 16).  However, since GOT16
+        relocations can also be used with global symbols, their howto
+        has a rightshift of 0.  */
+      if (hi->rel.howto->type == R_MIPS_GOT16)
+       hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16, FALSE);
+
+      /* VALLO is a signed 16-bit number.  Bias it by 0x8000 so that any
+        carry or borrow will induce a change of +1 or -1 in the high part.  */
+      hi->rel.addend += (vallo + 0x8000) & 0xffff;
+
+      ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
+                                        hi->input_section, output_bfd,
+                                        error_message);
+      if (ret != bfd_reloc_ok)
+       return ret;
+
+      mips_hi16_list = hi->next;
+      free (hi);
+    }
+
+  return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+                                     input_section, output_bfd,
+                                     error_message);
+}
+
+/* A generic howto special_function.  This calculates and installs the
+   relocation itself, thus avoiding the oft-discussed problems in
+   bfd_perform_relocation and bfd_install_relocation.  */
+
+bfd_reloc_status_type
+_bfd_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)
+{
+  bfd_signed_vma val;
+  bfd_reloc_status_type status;
+  bfd_boolean relocatable;
+
+  relocatable = (output_bfd != NULL);
+
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+    return bfd_reloc_outofrange;
+
+  /* Build up the field adjustment in VAL.  */
+  val = 0;
+  if (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0)
+    {
+      /* Either we're calculating the final field value or we have a
+        relocation against a section symbol.  Add in the section's
+        offset or address.  */
+      val += symbol->section->output_section->vma;
+      val += symbol->section->output_offset;
+    }
+
+  if (!relocatable)
+    {
+      /* We're calculating the final field value.  Add in the symbol's value
+        and, if pc-relative, subtract the address of the field itself.  */
+      val += symbol->value;
+      if (reloc_entry->howto->pc_relative)
+       {
+         val -= input_section->output_section->vma;
+         val -= input_section->output_offset;
+         val -= reloc_entry->address;
+       }
+    }
+
+  /* VAL is now the final adjustment.  If we're keeping this relocation
+     in the output file, and if the relocation uses a separate addend,
+     we just need to add VAL to that addend.  Otherwise we need to add
+     VAL to the relocation field itself.  */
+  if (relocatable && !reloc_entry->howto->partial_inplace)
+    reloc_entry->addend += val;
+  else
+    {
+      bfd_byte *location = (bfd_byte *) data + reloc_entry->address;
+
+      /* Add in the separate addend, if any.  */
+      val += reloc_entry->addend;
+
+      /* Add VAL to the relocation field.  */
+      _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE,
+                                      location);
+      status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
+                                      location);
+      _bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, FALSE,
+                                    location);
+
+      if (status != bfd_reloc_ok)
+       return status;
+    }
+
+  if (relocatable)
+    reloc_entry->address += input_section->output_offset;
 
   return bfd_reloc_ok;
 }
@@ -1130,30 +1351,24 @@ _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
    on the equivalence of the two elements of the union.  */
 
 static void
-bfd_mips_elf32_swap_gptab_in (abfd, ex, in)
-     bfd *abfd;
-     const Elf32_External_gptab *ex;
-     Elf32_gptab *in;
+bfd_mips_elf32_swap_gptab_in (bfd *abfd, const Elf32_External_gptab *ex,
+                             Elf32_gptab *in)
 {
   in->gt_entry.gt_g_value = H_GET_32 (abfd, ex->gt_entry.gt_g_value);
   in->gt_entry.gt_bytes = H_GET_32 (abfd, ex->gt_entry.gt_bytes);
 }
 
 static void
-bfd_mips_elf32_swap_gptab_out (abfd, in, ex)
-     bfd *abfd;
-     const Elf32_gptab *in;
-     Elf32_External_gptab *ex;
+bfd_mips_elf32_swap_gptab_out (bfd *abfd, const Elf32_gptab *in,
+                              Elf32_External_gptab *ex)
 {
   H_PUT_32 (abfd, in->gt_entry.gt_g_value, ex->gt_entry.gt_g_value);
   H_PUT_32 (abfd, in->gt_entry.gt_bytes, ex->gt_entry.gt_bytes);
 }
 
 static void
-bfd_elf32_swap_compact_rel_out (abfd, in, ex)
-     bfd *abfd;
-     const Elf32_compact_rel *in;
-     Elf32_External_compact_rel *ex;
+bfd_elf32_swap_compact_rel_out (bfd *abfd, const Elf32_compact_rel *in,
+                               Elf32_External_compact_rel *ex)
 {
   H_PUT_32 (abfd, in->id1, ex->id1);
   H_PUT_32 (abfd, in->num, ex->num);
@@ -1164,10 +1379,8 @@ bfd_elf32_swap_compact_rel_out (abfd, in, ex)
 }
 
 static void
-bfd_elf32_swap_crinfo_out (abfd, in, ex)
-     bfd *abfd;
-     const Elf32_crinfo *in;
-     Elf32_External_crinfo *ex;
+bfd_elf32_swap_crinfo_out (bfd *abfd, const Elf32_crinfo *in,
+                          Elf32_External_crinfo *ex)
 {
   unsigned long l;
 
@@ -1185,10 +1398,8 @@ bfd_elf32_swap_crinfo_out (abfd, in, ex)
    BFD, so they are globally visible.  */
 
 void
-bfd_mips_elf32_swap_reginfo_in (abfd, ex, in)
-     bfd *abfd;
-     const Elf32_External_RegInfo *ex;
-     Elf32_RegInfo *in;
+bfd_mips_elf32_swap_reginfo_in (bfd *abfd, const Elf32_External_RegInfo *ex,
+                               Elf32_RegInfo *in)
 {
   in->ri_gprmask = H_GET_32 (abfd, ex->ri_gprmask);
   in->ri_cprmask[0] = H_GET_32 (abfd, ex->ri_cprmask[0]);
@@ -1199,10 +1410,8 @@ bfd_mips_elf32_swap_reginfo_in (abfd, ex, in)
 }
 
 void
-bfd_mips_elf32_swap_reginfo_out (abfd, in, ex)
-     bfd *abfd;
-     const Elf32_RegInfo *in;
-     Elf32_External_RegInfo *ex;
+bfd_mips_elf32_swap_reginfo_out (bfd *abfd, const Elf32_RegInfo *in,
+                                Elf32_External_RegInfo *ex)
 {
   H_PUT_32 (abfd, in->ri_gprmask, ex->ri_gprmask);
   H_PUT_32 (abfd, in->ri_cprmask[0], ex->ri_cprmask[0]);
@@ -1219,10 +1428,8 @@ bfd_mips_elf32_swap_reginfo_out (abfd, in, ex)
    without worrying about whether the 64 bit ABI has been included.  */
 
 void
-bfd_mips_elf64_swap_reginfo_in (abfd, ex, in)
-     bfd *abfd;
-     const Elf64_External_RegInfo *ex;
-     Elf64_Internal_RegInfo *in;
+bfd_mips_elf64_swap_reginfo_in (bfd *abfd, const Elf64_External_RegInfo *ex,
+                               Elf64_Internal_RegInfo *in)
 {
   in->ri_gprmask = H_GET_32 (abfd, ex->ri_gprmask);
   in->ri_pad = H_GET_32 (abfd, ex->ri_pad);
@@ -1234,10 +1441,8 @@ bfd_mips_elf64_swap_reginfo_in (abfd, ex, in)
 }
 
 void
-bfd_mips_elf64_swap_reginfo_out (abfd, in, ex)
-     bfd *abfd;
-     const Elf64_Internal_RegInfo *in;
-     Elf64_External_RegInfo *ex;
+bfd_mips_elf64_swap_reginfo_out (bfd *abfd, const Elf64_Internal_RegInfo *in,
+                                Elf64_External_RegInfo *ex)
 {
   H_PUT_32 (abfd, in->ri_gprmask, ex->ri_gprmask);
   H_PUT_32 (abfd, in->ri_pad, ex->ri_pad);
@@ -1251,10 +1456,8 @@ bfd_mips_elf64_swap_reginfo_out (abfd, in, ex)
 /* Swap in an options header.  */
 
 void
-bfd_mips_elf_swap_options_in (abfd, ex, in)
-     bfd *abfd;
-     const Elf_External_Options *ex;
-     Elf_Internal_Options *in;
+bfd_mips_elf_swap_options_in (bfd *abfd, const Elf_External_Options *ex,
+                             Elf_Internal_Options *in)
 {
   in->kind = H_GET_8 (abfd, ex->kind);
   in->size = H_GET_8 (abfd, ex->size);
@@ -1265,10 +1468,8 @@ bfd_mips_elf_swap_options_in (abfd, ex, in)
 /* Swap out an options header.  */
 
 void
-bfd_mips_elf_swap_options_out (abfd, in, ex)
-     bfd *abfd;
-     const Elf_Internal_Options *in;
-     Elf_External_Options *ex;
+bfd_mips_elf_swap_options_out (bfd *abfd, const Elf_Internal_Options *in,
+                              Elf_External_Options *ex)
 {
   H_PUT_8 (abfd, in->kind, ex->kind);
   H_PUT_8 (abfd, in->size, ex->size);
@@ -1280,9 +1481,7 @@ bfd_mips_elf_swap_options_out (abfd, in, ex)
    entries by increasing r_symndx value.  */
 
 static int
-sort_dynamic_relocs (arg1, arg2)
-     const PTR arg1;
-     const PTR arg2;
+sort_dynamic_relocs (const void *arg1, const void *arg2)
 {
   Elf_Internal_Rela int_reloc1;
   Elf_Internal_Rela int_reloc2;
@@ -1296,10 +1495,10 @@ sort_dynamic_relocs (arg1, arg2)
 /* Like sort_dynamic_relocs, but used for elf64 relocations.  */
 
 static int
-sort_dynamic_relocs_64 (arg1, arg2)
-     const PTR arg1;
-     const PTR arg2;
+sort_dynamic_relocs_64 (const void *arg1 ATTRIBUTE_UNUSED,
+                       const void *arg2 ATTRIBUTE_UNUSED)
 {
+#ifdef BFD64
   Elf_Internal_Rela int_reloc1[3];
   Elf_Internal_Rela int_reloc2[3];
 
@@ -1310,6 +1509,9 @@ sort_dynamic_relocs_64 (arg1, arg2)
 
   return (ELF64_R_SYM (int_reloc1[0].r_info)
          - ELF64_R_SYM (int_reloc2[0].r_info));
+#else
+  abort ();
+#endif
 }
 
 
@@ -1328,11 +1530,9 @@ sort_dynamic_relocs_64 (arg1, arg2)
    when generating a final executable.  */
 
 static bfd_boolean
-mips_elf_output_extsym (h, data)
-     struct mips_elf_link_hash_entry *h;
-     PTR data;
+mips_elf_output_extsym (struct mips_elf_link_hash_entry *h, void *data)
 {
-  struct extsym_info *einfo = (struct extsym_info *) data;
+  struct extsym_info *einfo = data;
   bfd_boolean strip;
   asection *sec, *output_section;
 
@@ -1341,10 +1541,11 @@ mips_elf_output_extsym (h, data)
 
   if (h->root.indx == -2)
     strip = FALSE;
-  else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
-           || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
-          && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
-          && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
+  else if ((h->root.def_dynamic
+           || h->root.ref_dynamic
+           || h->root.type == bfd_link_hash_new)
+          && !h->root.def_regular
+          && !h->root.ref_regular)
     strip = TRUE;
   else if (einfo->info->strip == strip_all
           || (einfo->info->strip == strip_some
@@ -1462,7 +1663,7 @@ mips_elf_output_extsym (h, data)
       else
        h->esym.asym.value = 0;
     }
-  else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+  else if (h->root.needs_plt)
     {
       struct mips_elf_link_hash_entry *hd = h;
       bfd_boolean no_fn_stub = h->no_fn_stub;
@@ -1510,12 +1711,10 @@ mips_elf_output_extsym (h, data)
 /* A comparison routine used to sort .gptab entries.  */
 
 static int
-gptab_compare (p1, p2)
-     const PTR p1;
-     const PTR p2;
+gptab_compare (const void *p1, const void *p2)
 {
-  const Elf32_gptab *a1 = (const Elf32_gptab *) p1;
-  const Elf32_gptab *a2 = (const Elf32_gptab *) p2;
+  const Elf32_gptab *a1 = p1;
+  const Elf32_gptab *a2 = p2;
 
   return a1->gt_entry.gt_g_value - a2->gt_entry.gt_g_value;
 }
@@ -1526,8 +1725,7 @@ gptab_compare (p1, p2)
    hash number.  */
 
 static INLINE hashval_t
-mips_elf_hash_bfd_vma (addr)
-     bfd_vma addr;
+mips_elf_hash_bfd_vma (bfd_vma addr)
 {
 #ifdef BFD64
   return addr + (addr >> 32);
@@ -1541,8 +1739,7 @@ mips_elf_hash_bfd_vma (addr)
    union members.  */
 
 static hashval_t
-mips_elf_got_entry_hash (entry_)
-     const PTR entry_;
+mips_elf_got_entry_hash (const void *entry_)
 {
   const struct mips_got_entry *entry = (struct mips_got_entry *)entry_;
 
@@ -1554,9 +1751,7 @@ mips_elf_got_entry_hash (entry_)
 }
 
 static int
-mips_elf_got_entry_eq (entry1, entry2)
-     const PTR entry1;
-     const PTR entry2;
+mips_elf_got_entry_eq (const void *entry1, const void *entry2)
 {
   const struct mips_got_entry *e1 = (struct mips_got_entry *)entry1;
   const struct mips_got_entry *e2 = (struct mips_got_entry *)entry2;
@@ -1573,8 +1768,7 @@ mips_elf_got_entry_eq (entry1, entry2)
    accordingly.  */
 
 static hashval_t
-mips_elf_multi_got_entry_hash (entry_)
-     const PTR entry_;
+mips_elf_multi_got_entry_hash (const void *entry_)
 {
   const struct mips_got_entry *entry = (struct mips_got_entry *)entry_;
 
@@ -1588,9 +1782,7 @@ mips_elf_multi_got_entry_hash (entry_)
 }
 
 static int
-mips_elf_multi_got_entry_eq (entry1, entry2)
-     const PTR entry1;
-     const PTR entry2;
+mips_elf_multi_got_entry_eq (const void *entry1, const void *entry2)
 {
   const struct mips_got_entry *e1 = (struct mips_got_entry *)entry1;
   const struct mips_got_entry *e2 = (struct mips_got_entry *)entry2;
@@ -1605,9 +1797,7 @@ mips_elf_multi_got_entry_eq (entry1, entry2)
 /* Returns the dynamic relocation section for DYNOBJ.  */
 
 static asection *
-mips_elf_rel_dyn_section (dynobj, create_p)
-     bfd *dynobj;
-     bfd_boolean create_p;
+mips_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p)
 {
   static const char dname[] = ".rel.dyn";
   asection *sreloc;
@@ -1634,9 +1824,7 @@ mips_elf_rel_dyn_section (dynobj, create_p)
 /* Returns the GOT section for ABFD.  */
 
 static asection *
-mips_elf_got_section (abfd, maybe_excluded)
-     bfd *abfd;
-     bfd_boolean maybe_excluded;
+mips_elf_got_section (bfd *abfd, bfd_boolean maybe_excluded)
 {
   asection *sgot = bfd_get_section_by_name (abfd, ".got");
   if (sgot == NULL
@@ -1650,9 +1838,7 @@ mips_elf_got_section (abfd, maybe_excluded)
    section.  */
 
 static struct mips_got_info *
-mips_elf_got_info (abfd, sgotp)
-     bfd *abfd;
-     asection **sgotp;
+mips_elf_got_info (bfd *abfd, asection **sgotp)
 {
   asection *sgot;
   struct mips_got_info *g;
@@ -1669,38 +1855,13 @@ mips_elf_got_info (abfd, sgotp)
   return g;
 }
 
-/* Obtain the lowest dynamic index of a symbol that was assigned a
-   global GOT entry.  */
-static long
-mips_elf_get_global_gotsym_index (abfd)
-     bfd *abfd;
-{
-  asection *sgot;
-  struct mips_got_info *g;
-
-  if (abfd == NULL)
-    return 0;
-
-  sgot = mips_elf_got_section (abfd, TRUE);
-  if (sgot == NULL || mips_elf_section_data (sgot) == NULL)
-    return 0;
-
-  g = mips_elf_section_data (sgot)->u.got_info;
-  if (g == NULL || g->global_gotsym == NULL)
-    return 0;
-
-  return g->global_gotsym->dynindx;
-}
-
 /* Returns the GOT offset at which the indicated address can be found.
    If there is not yet a GOT entry for this value, create one.  Returns
    -1 if no satisfactory GOT offset can be found.  */
 
 static bfd_vma
-mips_elf_local_got_index (abfd, ibfd, info, value)
-     bfd *abfd, *ibfd;
-     struct bfd_link_info *info;
-     bfd_vma value;
+mips_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
+                         bfd_vma value)
 {
   asection *sgot;
   struct mips_got_info *g;
@@ -1718,9 +1879,7 @@ mips_elf_local_got_index (abfd, ibfd, info, value)
 /* Returns the GOT index for the global symbol indicated by H.  */
 
 static bfd_vma
-mips_elf_global_got_index (abfd, ibfd, h)
-     bfd *abfd, *ibfd;
-     struct elf_link_hash_entry *h;
+mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h)
 {
   bfd_vma index;
   asection *sgot;
@@ -1741,7 +1900,7 @@ mips_elf_global_got_index (abfd, ibfd, h)
          e.symndx = -1;
          e.d.h = (struct mips_elf_link_hash_entry *)h;
 
-         p = (struct mips_got_entry *) htab_find (g->got_entries, &e);
+         p = htab_find (g->got_entries, &e);
 
          BFD_ASSERT (p->gotidx > 0);
          return p->gotidx;
@@ -1758,7 +1917,7 @@ mips_elf_global_got_index (abfd, ibfd, h)
   BFD_ASSERT (h->dynindx >= global_got_dynindx);
   index = ((h->dynindx - global_got_dynindx + g->local_gotno)
           * MIPS_ELF_GOT_SIZE (abfd));
-  BFD_ASSERT (index < sgot->_raw_size);
+  BFD_ASSERT (index < sgot->size);
 
   return index;
 }
@@ -1770,11 +1929,8 @@ mips_elf_global_got_index (abfd, ibfd, h)
    OFFSETP, if it is non-NULL.  */
 
 static bfd_vma
-mips_elf_got_page (abfd, ibfd, info, value, offsetp)
-     bfd *abfd, *ibfd;
-     struct bfd_link_info *info;
-     bfd_vma value;
-     bfd_vma *offsetp;
+mips_elf_got_page (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
+                  bfd_vma value, bfd_vma *offsetp)
 {
   asection *sgot;
   struct mips_got_info *g;
@@ -1802,11 +1958,8 @@ mips_elf_got_page (abfd, ibfd, info, value, offsetp)
    for value.  Return the index into the GOT for this entry.  */
 
 static bfd_vma
-mips_elf_got16_entry (abfd, ibfd, info, value, external)
-     bfd *abfd, *ibfd;
-     struct bfd_link_info *info;
-     bfd_vma value;
-     bfd_boolean external;
+mips_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
+                     bfd_vma value, bfd_boolean external)
 {
   asection *sgot;
   struct mips_got_info *g;
@@ -1834,11 +1987,8 @@ mips_elf_got16_entry (abfd, ibfd, info, value, external)
    in the GOT.  */
 
 static bfd_vma
-mips_elf_got_offset_from_index (dynobj, output_bfd, input_bfd, index)
-     bfd *dynobj;
-     bfd *output_bfd;
-     bfd *input_bfd;
-     bfd_vma index;
+mips_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd,
+                               bfd *input_bfd, bfd_vma index)
 {
   asection *sgot;
   bfd_vma gp;
@@ -1855,11 +2005,9 @@ mips_elf_got_offset_from_index (dynobj, output_bfd, input_bfd, index)
    or -1 if it could not be created.  */
 
 static struct mips_got_entry *
-mips_elf_create_local_got_entry (abfd, ibfd, gg, sgot, value)
-     bfd *abfd, *ibfd;
-     struct mips_got_info *gg;
-     asection *sgot;
-     bfd_vma value;
+mips_elf_create_local_got_entry (bfd *abfd, bfd *ibfd,
+                                struct mips_got_info *gg,
+                                asection *sgot, bfd_vma value)
 {
   struct mips_got_entry entry, **loc;
   struct mips_got_info *g;
@@ -1913,9 +2061,7 @@ mips_elf_create_local_got_entry (abfd, ibfd, gg, sgot, value)
    section symbols are added and the count is higher.  */
 
 static bfd_boolean
-mips_elf_sort_hash_table (info, max_local)
-     struct bfd_link_info *info;
-     unsigned long max_local;
+mips_elf_sort_hash_table (struct bfd_link_info *info, unsigned long max_local)
 {
   struct mips_elf_hash_sort_data hsd;
   struct mips_got_info *g;
@@ -1960,12 +2106,9 @@ mips_elf_sort_hash_table (info, max_local)
    index.  */
 
 static bfd_boolean
-mips_elf_sort_hash_table_f (h, data)
-     struct mips_elf_link_hash_entry *h;
-     PTR data;
+mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data)
 {
-  struct mips_elf_hash_sort_data *hsd
-    = (struct mips_elf_hash_sort_data *) data;
+  struct mips_elf_hash_sort_data *hsd = data;
 
   if (h->root.root.type == bfd_link_hash_warning)
     h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
@@ -2001,11 +2144,9 @@ mips_elf_sort_hash_table_f (h, data)
    posterity.  */
 
 static bfd_boolean
-mips_elf_record_global_got_symbol (h, abfd, info, g)
-     struct elf_link_hash_entry *h;
-     bfd *abfd;
-     struct bfd_link_info *info;
-     struct mips_got_info *g;
+mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
+                                  bfd *abfd, struct bfd_link_info *info,
+                                  struct mips_got_info *g)
 {
   struct mips_got_entry entry, **loc;
 
@@ -2020,7 +2161,7 @@ mips_elf_record_global_got_symbol (h, abfd, info, g)
          _bfd_mips_elf_hide_symbol (info, h, TRUE);
          break;
        }
-      if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+      if (!bfd_elf_link_record_dynamic_symbol (info, h))
        return FALSE;
     }
 
@@ -2059,11 +2200,8 @@ mips_elf_record_global_got_symbol (h, abfd, info, g)
    SYMNDX in input bfd ABDF, plus ADDEND.  */
 
 static bfd_boolean
-mips_elf_record_local_got_symbol (abfd, symndx, addend, g)
-     bfd *abfd;
-     long symndx;
-     bfd_vma addend;
-     struct mips_got_info *g;
+mips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
+                                 struct mips_got_info *g)
 {
   struct mips_got_entry entry, **loc;
 
@@ -2091,8 +2229,7 @@ mips_elf_record_local_got_symbol (abfd, symndx, addend, g)
 /* Compute the hash value of the bfd in a bfd2got hash entry.  */
 
 static hashval_t
-mips_elf_bfd2got_entry_hash (entry_)
-     const PTR entry_;
+mips_elf_bfd2got_entry_hash (const void *entry_)
 {
   const struct mips_elf_bfd2got_hash *entry
     = (struct mips_elf_bfd2got_hash *)entry_;
@@ -2103,9 +2240,7 @@ mips_elf_bfd2got_entry_hash (entry_)
 /* Check whether two hash entries have the same bfd.  */
 
 static int
-mips_elf_bfd2got_entry_eq (entry1, entry2)
-     const PTR entry1;
-     const PTR entry2;
+mips_elf_bfd2got_entry_eq (const void *entry1, const void *entry2)
 {
   const struct mips_elf_bfd2got_hash *e1
     = (const struct mips_elf_bfd2got_hash *)entry1;
@@ -2119,9 +2254,7 @@ mips_elf_bfd2got_entry_eq (entry1, entry2)
    be the master GOT data.  */
 
 static struct mips_got_info *
-mips_elf_got_for_ibfd (g, ibfd)
-     struct mips_got_info *g;
-     bfd *ibfd;
+mips_elf_got_for_ibfd (struct mips_got_info *g, bfd *ibfd)
 {
   struct mips_elf_bfd2got_hash e, *p;
 
@@ -2129,7 +2262,7 @@ mips_elf_got_for_ibfd (g, ibfd)
     return g;
 
   e.bfd = ibfd;
-  p = (struct mips_elf_bfd2got_hash *) htab_find (g->bfd2got, &e);
+  p = htab_find (g->bfd2got, &e);
   return p ? p->g : NULL;
 }
 
@@ -2138,9 +2271,7 @@ mips_elf_got_for_ibfd (g, ibfd)
    bfd requires.  */
 
 static int
-mips_elf_make_got_per_bfd (entryp, p)
-     void **entryp;
-     void *p;
+mips_elf_make_got_per_bfd (void **entryp, void *p)
 {
   struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
   struct mips_elf_got_per_bfd_arg *arg = (struct mips_elf_got_per_bfd_arg *)p;
@@ -2184,8 +2315,7 @@ mips_elf_make_got_per_bfd (entryp, p)
       g->local_gotno = 0;
       g->assigned_gotno = -1;
       g->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
-                                       mips_elf_multi_got_entry_eq,
-                                       (htab_del) NULL);
+                                       mips_elf_multi_got_entry_eq, NULL);
       if (g->got_entries == NULL)
        {
          arg->obfd = 0;
@@ -2219,9 +2349,7 @@ mips_elf_make_got_per_bfd (entryp, p)
    and then make make the new got current.  */
 
 static int
-mips_elf_merge_gots (bfd2got_, p)
-     void **bfd2got_;
-     void *p;
+mips_elf_merge_gots (void **bfd2got_, void *p)
 {
   struct mips_elf_bfd2got_hash *bfd2got
     = (struct mips_elf_bfd2got_hash *)*bfd2got_;
@@ -2260,7 +2388,7 @@ mips_elf_merge_gots (bfd2got_, p)
         got entries, since they're all in the master got_entries hash
         table anyway.  */
 
-      BFD_ASSERT (old_lcount + lcount == arg->primary->local_gotno);
+      BFD_ASSERT (old_lcount + lcount >= arg->primary->local_gotno);
       BFD_ASSERT (old_gcount + gcount >= arg->primary->global_gotno);
 
       arg->primary_count = arg->primary->local_gotno
@@ -2284,7 +2412,7 @@ mips_elf_merge_gots (bfd2got_, p)
 
       htab_delete (g->got_entries);
 
-      BFD_ASSERT (old_lcount + lcount == arg->current->local_gotno);
+      BFD_ASSERT (old_lcount + lcount >= arg->current->local_gotno);
       BFD_ASSERT (old_gcount + gcount >= arg->current->global_gotno);
 
       arg->current_count = arg->current->local_gotno
@@ -2315,12 +2443,10 @@ mips_elf_merge_gots (bfd2got_, p)
    first available global GOT entry in G.  VALUE must contain the size
    of a GOT entry in bytes.  For each global GOT entry that requires a
    dynamic relocation, NEEDED_RELOCS is incremented, and the symbol is
-   marked as not elligible for lazy resolution through a function
+   marked as not eligible for lazy resolution through a function
    stub.  */
 static int
-mips_elf_set_global_got_offset (entryp, p)
-     void **entryp;
-     void *p;
+mips_elf_set_global_got_offset (void **entryp, void *p)
 {
   struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
   struct mips_elf_set_global_got_offset_arg *arg
@@ -2335,16 +2461,10 @@ mips_elf_set_global_got_offset (entryp, p)
          BFD_ASSERT (g->global_gotsym == NULL);
 
          entry->gotidx = arg->value * (long) g->assigned_gotno++;
-         /* We can't do lazy update of GOT entries for
-            non-primary GOTs since the PLT entries don't use the
-            right offsets, so punt at it for now.  */
-         entry->d.h->no_fn_stub = TRUE;
          if (arg->info->shared
              || (elf_hash_table (arg->info)->dynamic_sections_created
-                 && ((entry->d.h->root.elf_link_hash_flags
-                      & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
-                 && ((entry->d.h->root.elf_link_hash_flags
-                      & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+                 && entry->d.h->root.def_dynamic
+                 && !entry->d.h->root.def_regular))
            ++arg->needed_relocs;
        }
       else
@@ -2354,6 +2474,21 @@ mips_elf_set_global_got_offset (entryp, p)
   return 1;
 }
 
+/* Mark any global symbols referenced in the GOT we are iterating over
+   as inelligible for lazy resolution stubs.  */
+static int
+mips_elf_set_no_stub (void **entryp, void *p ATTRIBUTE_UNUSED)
+{
+  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
+
+  if (entry->abfd != NULL
+      && entry->symndx == -1
+      && entry->d.h->root.dynindx != -1)
+    entry->d.h->no_fn_stub = TRUE;
+
+  return 1;
+}
+
 /* Follow indirect and warning hash entries so that each got entry
    points to the final symbol definition.  P must point to a pointer
    to the hash table we're traversing.  Since this traversal may
@@ -2361,9 +2496,7 @@ mips_elf_set_global_got_offset (entryp, p)
    we've made a potentially-destructive change to the hash table, so
    the traversal must be restarted.  */
 static int
-mips_elf_resolve_final_got_entry (entryp, p)
-     void **entryp;
-     void *p;
+mips_elf_resolve_final_got_entry (void **entryp, void *p)
 {
   struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
   htab_t got_entries = *(htab_t *)p;
@@ -2405,8 +2538,7 @@ mips_elf_resolve_final_got_entry (entryp, p)
 /* Turn indirect got entries in a got_entries table into their final
    locations.  */
 static void
-mips_elf_resolve_final_got_entries (g)
-     struct mips_got_info *g;
+mips_elf_resolve_final_got_entries (struct mips_got_info *g)
 {
   htab_t got_entries;
 
@@ -2424,10 +2556,7 @@ mips_elf_resolve_final_got_entries (g)
 /* Return the offset of an input bfd IBFD's GOT from the beginning of
    the primary GOT.  */
 static bfd_vma
-mips_elf_adjust_gp (abfd, g, ibfd)
-     bfd *abfd;
-     struct mips_got_info *g;
-     bfd *ibfd;
+mips_elf_adjust_gp (bfd *abfd, struct mips_got_info *g, bfd *ibfd)
 {
   if (g->bfd2got == NULL)
     return 0;
@@ -2447,12 +2576,9 @@ mips_elf_adjust_gp (abfd, g, ibfd)
    a sequence of GOTs, each one 16-bit addressable.  */
 
 static bfd_boolean
-mips_elf_multi_got (abfd, info, g, got, pages)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     struct mips_got_info *g;
-     asection *got;
-     bfd_size_type pages;
+mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
+                   struct mips_got_info *g, asection *got,
+                   bfd_size_type pages)
 {
   struct mips_elf_got_per_bfd_arg got_per_bfd_arg;
   struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
@@ -2460,8 +2586,7 @@ mips_elf_multi_got (abfd, info, g, got, pages)
   unsigned int assign;
 
   g->bfd2got = htab_try_create (1, mips_elf_bfd2got_entry_hash,
-                               mips_elf_bfd2got_entry_eq,
-                               (htab_del) NULL);
+                               mips_elf_bfd2got_entry_eq, NULL);
   if (g->bfd2got == NULL)
     return FALSE;
 
@@ -2506,7 +2631,7 @@ mips_elf_multi_got (abfd, info, g, got, pages)
       g->next->assigned_gotno = 0;
       g->next->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
                                              mips_elf_multi_got_entry_eq,
-                                             (htab_del) NULL);
+                                             NULL);
       if (g->next->got_entries == NULL)
        return FALSE;
       g->next->bfd2got = NULL;
@@ -2621,10 +2746,15 @@ mips_elf_multi_got (abfd, info, g, got, pages)
       g->next = gg->next;
       gg->next = g;
       g = gn;
+
+      /* Mark global symbols in every non-primary GOT as ineligible for
+        stubs.  */
+      if (g)
+       htab_traverse (g->got_entries, mips_elf_set_no_stub, NULL);
     }
   while (g);
 
-  got->_raw_size = (gg->next->local_gotno
+  got->size = (gg->next->local_gotno
                    + gg->next->global_gotno) * MIPS_ELF_GOT_SIZE (abfd);
 
   return TRUE;
@@ -2635,18 +2765,10 @@ mips_elf_multi_got (abfd, info, g, got, pages)
    RELOCATION.  RELEND is one-past-the-end of the relocation table.  */
 
 static const Elf_Internal_Rela *
-mips_elf_next_relocation (abfd, r_type, relocation, relend)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     unsigned int r_type;
-     const Elf_Internal_Rela *relocation;
-     const Elf_Internal_Rela *relend;
-{
-  /* According to the MIPS ELF ABI, the R_MIPS_LO16 relocation must be
-     immediately following.  However, for the IRIX6 ABI, the next
-     relocation may be a composed relocation consisting of several
-     relocations for the same address.  In that case, the R_MIPS_LO16
-     relocation may occur as one of these.  We permit a similar
-     extension in general, as that is useful for GCC.  */
+mips_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type,
+                         const Elf_Internal_Rela *relocation,
+                         const Elf_Internal_Rela *relend)
+{
   while (relocation < relend)
     {
       if (ELF_R_TYPE (abfd, relocation->r_info) == r_type)
@@ -2663,12 +2785,10 @@ mips_elf_next_relocation (abfd, r_type, relocation, relend)
 /* Return whether a relocation is against a local symbol.  */
 
 static bfd_boolean
-mips_elf_local_relocation_p (input_bfd, relocation, local_sections,
-                            check_forced)
-     bfd *input_bfd;
-     const Elf_Internal_Rela *relocation;
-     asection **local_sections;
-     bfd_boolean check_forced;
+mips_elf_local_relocation_p (bfd *input_bfd,
+                            const Elf_Internal_Rela *relocation,
+                            asection **local_sections,
+                            bfd_boolean check_forced)
 {
   unsigned long r_symndx;
   Elf_Internal_Shdr *symtab_hdr;
@@ -2694,7 +2814,7 @@ mips_elf_local_relocation_p (input_bfd, relocation, local_sections,
       while (h->root.root.type == bfd_link_hash_indirect
             || h->root.root.type == bfd_link_hash_warning)
        h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
-      if ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+      if (h->root.forced_local)
        return TRUE;
     }
 
@@ -2704,9 +2824,7 @@ mips_elf_local_relocation_p (input_bfd, relocation, local_sections,
 /* Sign-extend VALUE, which has the indicated number of BITS.  */
 
 bfd_vma
-_bfd_mips_elf_sign_extend (value, bits)
-     bfd_vma value;
-     int bits;
+_bfd_mips_elf_sign_extend (bfd_vma value, int bits)
 {
   if (value & ((bfd_vma) 1 << (bits - 1)))
     /* VALUE is negative.  */
@@ -2716,13 +2834,11 @@ _bfd_mips_elf_sign_extend (value, bits)
 }
 
 /* Return non-zero if the indicated VALUE has overflowed the maximum
-   range expressable by a signed number with the indicated number of
+   range expressible by a signed number with the indicated number of
    BITS.  */
 
 static bfd_boolean
-mips_elf_overflow_p (value, bits)
-     bfd_vma value;
-     int bits;
+mips_elf_overflow_p (bfd_vma value, int bits)
 {
   bfd_signed_vma svalue = (bfd_signed_vma) value;
 
@@ -2740,8 +2856,7 @@ mips_elf_overflow_p (value, bits)
 /* Calculate the %high function.  */
 
 static bfd_vma
-mips_elf_high (value)
-     bfd_vma value;
+mips_elf_high (bfd_vma value)
 {
   return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff;
 }
@@ -2749,37 +2864,34 @@ mips_elf_high (value)
 /* Calculate the %higher function.  */
 
 static bfd_vma
-mips_elf_higher (value)
-     bfd_vma value ATTRIBUTE_UNUSED;
+mips_elf_higher (bfd_vma value ATTRIBUTE_UNUSED)
 {
 #ifdef BFD64
   return ((value + (bfd_vma) 0x80008000) >> 32) & 0xffff;
 #else
   abort ();
-  return (bfd_vma) -1;
+  return MINUS_ONE;
 #endif
 }
 
 /* Calculate the %highest function.  */
 
 static bfd_vma
-mips_elf_highest (value)
-     bfd_vma value ATTRIBUTE_UNUSED;
+mips_elf_highest (bfd_vma value ATTRIBUTE_UNUSED)
 {
 #ifdef BFD64
   return ((value + (((bfd_vma) 0x8000 << 32) | 0x80008000)) >> 48) & 0xffff;
 #else
   abort ();
-  return (bfd_vma) -1;
+  return MINUS_ONE;
 #endif
 }
 \f
 /* Create the .compact_rel section.  */
 
 static bfd_boolean
-mips_elf_create_compact_rel_section (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+mips_elf_create_compact_rel_section
+  (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   flagword flags;
   register asection *s;
@@ -2796,7 +2908,7 @@ mips_elf_create_compact_rel_section (abfd, info)
                                          MIPS_ELF_LOG_FILE_ALIGN (abfd)))
        return FALSE;
 
-      s->_raw_size = sizeof (Elf32_External_compact_rel);
+      s->size = sizeof (Elf32_External_compact_rel);
     }
 
   return TRUE;
@@ -2805,10 +2917,8 @@ mips_elf_create_compact_rel_section (abfd, info)
 /* Create the .got section to hold the global offset table.  */
 
 static bfd_boolean
-mips_elf_create_got_section (abfd, info, maybe_exclude)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean maybe_exclude;
+mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info,
+                            bfd_boolean maybe_exclude)
 {
   flagword flags;
   register asection *s;
@@ -2846,31 +2956,30 @@ mips_elf_create_got_section (abfd, info, maybe_exclude)
   bh = NULL;
   if (! (_bfd_generic_link_add_one_symbol
         (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
-         (bfd_vma) 0, (const char *) NULL, FALSE,
-         get_elf_backend_data (abfd)->collect, &bh)))
+         0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
     return FALSE;
 
   h = (struct elf_link_hash_entry *) bh;
-  h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
-  h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+  h->non_elf = 0;
+  h->def_regular = 1;
   h->type = STT_OBJECT;
 
   if (info->shared
-      && ! bfd_elf32_link_record_dynamic_symbol (info, h))
+      && ! bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
 
   amt = sizeof (struct mips_got_info);
-  g = (struct mips_got_info *) bfd_alloc (abfd, amt);
+  g = bfd_alloc (abfd, amt);
   if (g == NULL)
     return FALSE;
   g->global_gotsym = NULL;
+  g->global_gotno = 0;
   g->local_gotno = MIPS_RESERVED_GOTNO;
   g->assigned_gotno = MIPS_RESERVED_GOTNO;
   g->bfd2got = NULL;
   g->next = NULL;
   g->got_entries = htab_try_create (1, mips_elf_got_entry_hash,
-                                   mips_elf_got_entry_eq,
-                                   (htab_del) NULL);
+                                   mips_elf_got_entry_eq, NULL);
   if (g->got_entries == NULL)
     return FALSE;
   mips_elf_section_data (s)->u.got_info = g;
@@ -2894,23 +3003,15 @@ mips_elf_create_got_section (abfd, info, maybe_exclude)
    overflow occurs, and bfd_reloc_ok to indicate success.  */
 
 static bfd_reloc_status_type
-mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
-                              relocation, addend, howto, local_syms,
-                              local_sections, valuep, namep,
-                              require_jalxp, save_addend)
-     bfd *abfd;
-     bfd *input_bfd;
-     asection *input_section;
-     struct bfd_link_info *info;
-     const Elf_Internal_Rela *relocation;
-     bfd_vma addend;
-     reloc_howto_type *howto;
-     Elf_Internal_Sym *local_syms;
-     asection **local_sections;
-     bfd_vma *valuep;
-     const char **namep;
-     bfd_boolean *require_jalxp;
-     bfd_boolean save_addend;
+mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
+                              asection *input_section,
+                              struct bfd_link_info *info,
+                              const Elf_Internal_Rela *relocation,
+                              bfd_vma addend, reloc_howto_type *howto,
+                              Elf_Internal_Sym *local_syms,
+                              asection **local_sections, bfd_vma *valuep,
+                              const char **namep, bfd_boolean *require_jalxp,
+                              bfd_boolean save_addend)
 {
   /* The eventual value we will return.  */
   bfd_vma value;
@@ -3008,6 +3109,8 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
     }
   else
     {
+      /* ??? Could we use RELOC_FOR_GLOBAL_SYMBOL here ?  */
+
       /* For global symbols we look up the symbol in the hash-table.  */
       h = ((struct mips_elf_link_hash_entry *)
           elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
@@ -3021,12 +3124,13 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
 
       /* See if this is the special _gp_disp symbol.  Note that such a
         symbol must always be a global symbol.  */
-      if (strcmp (h->root.root.root.string, "_gp_disp") == 0
+      if (strcmp (*namep, "_gp_disp") == 0
          && ! NEWABI_P (input_bfd))
        {
          /* Relocations against _gp_disp are permitted only with
             R_MIPS_HI16 and R_MIPS_LO16 relocations.  */
-         if (r_type != R_MIPS_HI16 && r_type != R_MIPS_LO16)
+         if (r_type != R_MIPS_HI16 && r_type != R_MIPS_LO16
+             && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
            return bfd_reloc_notsupported;
 
          gp_disp_p = TRUE;
@@ -3053,12 +3157,11 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
           and check to see if they exist by looking at their
           addresses.  */
        symbol = 0;
-      else if (info->shared
-              && !info->no_undefined
+      else if (info->unresolved_syms_in_objects == RM_IGNORE
               && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
        symbol = 0;
-      else if (strcmp (h->root.root.root.string, "_DYNAMIC_LINK") == 0 ||
-              strcmp (h->root.root.root.string, "_DYNAMIC_LINKING") == 0)
+      else if (strcmp (*namep, SGI_COMPAT (input_bfd)
+                      ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING") == 0)
        {
          /* If this is a dynamic link, we should have created a
             _DYNAMIC_LINK symbol or _DYNAMIC_LINKING(for normal mips) symbol
@@ -3075,8 +3178,8 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
          if (! ((*info->callbacks->undefined_symbol)
                 (info, h->root.root.root.string, input_bfd,
                  input_section, relocation->r_offset,
-                 (!info->shared || info->no_undefined
-                  || ELF_ST_VISIBILITY (h->root.other)))))
+                 (info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
+                  || ELF_ST_VISIBILITY (h->root.other))))
            return bfd_reloc_undefined;
          symbol = 0;
        }
@@ -3138,7 +3241,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       else
        sec = h->call_fp_stub;
 
-      BFD_ASSERT (sec->_raw_size > 0);
+      BFD_ASSERT (sec->size > 0);
       symbol = sec->output_section->vma + sec->output_offset;
     }
 
@@ -3157,12 +3260,9 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
     {
     case R_MIPS_GOT_PAGE:
     case R_MIPS_GOT_OFST:
-      /* If this symbol got a global GOT entry, we have to decay
-        GOT_PAGE/GOT_OFST to GOT_DISP/addend.  */
-      local_p = local_p || ! h
-       || (h->root.dynindx
-           < mips_elf_get_global_gotsym_index (elf_hash_table (info)
-                                               ->dynobj));
+      /* We need to decay to GOT_DISP/addend if the symbol doesn't
+        bind locally.  */
+      local_p = local_p || _bfd_elf_symbol_refs_local_p (&h->root, info, 1);
       if (local_p || r_type == R_MIPS_GOT_OFST)
        break;
       /* Fall through.  */
@@ -3188,7 +3288,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
          if (! elf_hash_table(info)->dynamic_sections_created
              || (info->shared
                  && (info->symbolic || h->root.dynindx == -1)
-                 && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+                 && h->root.def_regular))
            {
              /* This is a static link or a -Bsymbolic link.  The
                 symbol is defined locally, or was forced to be local.
@@ -3217,10 +3317,12 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
 
     case R_MIPS_HI16:
     case R_MIPS_LO16:
-    case R_MIPS16_GPREL:
     case R_MIPS_GPREL16:
     case R_MIPS_GPREL32:
     case R_MIPS_LITERAL:
+    case R_MIPS16_HI16:
+    case R_MIPS16_LO16:
+    case R_MIPS16_GPREL:
       gp0 = _bfd_get_gp_value (input_bfd);
       gp = _bfd_get_gp_value (abfd);
       if (elf_hash_table (info)->dynobj)
@@ -3251,10 +3353,8 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       if ((info->shared
           || (elf_hash_table (info)->dynamic_sections_created
               && h != NULL
-              && ((h->root.elf_link_hash_flags
-                   & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
-              && ((h->root.elf_link_hash_flags
-                   & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+              && h->root.def_dynamic
+              && !h->root.def_regular))
          && r_symndx != 0
          && (input_section->flags & SEC_ALLOC) != 0)
        {
@@ -3285,28 +3385,16 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       break;
 
     case R_MIPS_PC32:
-    case R_MIPS_PC64:
-    case R_MIPS_GNU_REL_LO16:
       value = symbol + addend - p;
       value &= howto->dst_mask;
       break;
 
     case R_MIPS_GNU_REL16_S2:
-      value = symbol + _bfd_mips_elf_sign_extend (addend << 2, 18) - p;
+      value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
       overflowed_p = mips_elf_overflow_p (value, 18);
       value = (value >> 2) & howto->dst_mask;
       break;
 
-    case R_MIPS_GNU_REL_HI16:
-      /* Instead of subtracting 'p' here, we should be subtracting the
-        equivalent value for the LO part of the reloc, since the value
-        here is relative to that address.  Because that's not easy to do,
-        we adjust 'addend' in _bfd_mips_elf_relocate_section().  See also
-        the comment there for more information.  */
-      value = mips_elf_high (addend + symbol - p);
-      value &= howto->dst_mask;
-      break;
-
     case R_MIPS16_26:
       /* The calculation for R_MIPS16_26 is just the same as for an
         R_MIPS_26.  It's only the storage of the relocated field into
@@ -3315,13 +3403,18 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
         R_MIPS_26 case here.  */
     case R_MIPS_26:
       if (local_p)
-       value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
+       value = ((addend | ((p + 4) & 0xf0000000)) + symbol) >> 2;
       else
-       value = (_bfd_mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
+       {
+         value = (_bfd_mips_elf_sign_extend (addend, 28) + symbol) >> 2;
+         if (h->root.root.type != bfd_link_hash_undefweak)
+           overflowed_p = (value >> 26) != ((p + 4) >> 28);
+       }
       value &= howto->dst_mask;
       break;
 
     case R_MIPS_HI16:
+    case R_MIPS16_HI16:
       if (!gp_disp_p)
        {
          value = mips_elf_high (addend + symbol);
@@ -3329,17 +3422,35 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
        }
       else
        {
-         value = mips_elf_high (addend + gp - p);
+         /* For MIPS16 ABI code we generate this sequence
+               0: li      $v0,%hi(_gp_disp)
+               4: addiupc $v1,%lo(_gp_disp)
+               8: sll     $v0,16
+              12: addu    $v0,$v1
+              14: move    $gp,$v0
+            So the offsets of hi and lo relocs are the same, but the
+            $pc is four higher than $t9 would be, so reduce
+            both reloc addends by 4. */
+         if (r_type == R_MIPS16_HI16)
+           value = mips_elf_high (addend + gp - p - 4);
+         else
+           value = mips_elf_high (addend + gp - p);
          overflowed_p = mips_elf_overflow_p (value, 16);
        }
       break;
 
     case R_MIPS_LO16:
+    case R_MIPS16_LO16:
       if (!gp_disp_p)
        value = (symbol + addend) & howto->dst_mask;
       else
        {
-         value = addend + gp - p + 4;
+         /* See the comment for R_MIPS16_HI16 above for the reason
+            for this conditional.  */
+         if (r_type == R_MIPS16_LO16)
+           value = addend + gp - p;
+         else
+           value = addend + gp - p + 4;
          /* The MIPS ABI requires checking the R_MIPS_LO16 relocation
             for overflow.  But, on, say, IRIX5, relocations against
             _gp_disp are normally generated from the .cpload
@@ -3487,12 +3598,16 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       value &= howto->dst_mask;
       break;
 
-    case R_MIPS_PJUMP:
     case R_MIPS_JALR:
-      /* Both of these may be ignored.  R_MIPS_JALR is an optimization
-        hint; we could improve performance by honoring that hint.  */
-      return bfd_reloc_continue;
+      /* This relocation is only a hint.  In some cases, we optimize
+        it into a bal instruction.  But we don't try to optimize
+        branches to the PLT; that will wind up wasting time.  */
+      if (h != NULL && h->root.plt.offset != (bfd_vma) -1)
+       return bfd_reloc_continue;
+      value = symbol + addend;
+      break;
 
+    case R_MIPS_PJUMP:
     case R_MIPS_GNU_VTINHERIT:
     case R_MIPS_GNU_VTENTRY:
       /* We don't do anything with these at present.  */
@@ -3511,11 +3626,9 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
 /* Obtain the field relocated by RELOCATION.  */
 
 static bfd_vma
-mips_elf_obtain_contents (howto, relocation, input_bfd, contents)
-     reloc_howto_type *howto;
-     const Elf_Internal_Rela *relocation;
-     bfd *input_bfd;
-     bfd_byte *contents;
+mips_elf_obtain_contents (reloc_howto_type *howto,
+                         const Elf_Internal_Rela *relocation,
+                         bfd *input_bfd, bfd_byte *contents)
 {
   bfd_vma x;
   bfd_byte *location = contents + relocation->r_offset;
@@ -3523,13 +3636,6 @@ mips_elf_obtain_contents (howto, relocation, input_bfd, contents)
   /* Obtain the bytes.  */
   x = bfd_get ((8 * bfd_get_reloc_size (howto)), input_bfd, location);
 
-  if ((ELF_R_TYPE (input_bfd, relocation->r_info) == R_MIPS16_26
-       || ELF_R_TYPE (input_bfd, relocation->r_info) == R_MIPS16_GPREL)
-      && bfd_little_endian (input_bfd))
-    /* The two 16-bit words will be reversed on a little-endian system.
-       See mips_elf_perform_relocation for more details.  */
-    x = (((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16));
-
   return x;
 }
 
@@ -3543,16 +3649,12 @@ mips_elf_obtain_contents (howto, relocation, input_bfd, contents)
    Returns FALSE if anything goes wrong.  */
 
 static bfd_boolean
-mips_elf_perform_relocation (info, howto, relocation, value, input_bfd,
-                            input_section, contents, require_jalx)
-     struct bfd_link_info *info;
-     reloc_howto_type *howto;
-     const Elf_Internal_Rela *relocation;
-     bfd_vma value;
-     bfd *input_bfd;
-     asection *input_section;
-     bfd_byte *contents;
-     bfd_boolean require_jalx;
+mips_elf_perform_relocation (struct bfd_link_info *info,
+                            reloc_howto_type *howto,
+                            const Elf_Internal_Rela *relocation,
+                            bfd_vma value, bfd *input_bfd,
+                            asection *input_section, bfd_byte *contents,
+                            bfd_boolean require_jalx)
 {
   bfd_vma x;
   bfd_byte *location;
@@ -3561,107 +3663,14 @@ mips_elf_perform_relocation (info, howto, relocation, value, input_bfd,
   /* Figure out where the relocation is occurring.  */
   location = contents + relocation->r_offset;
 
+  _bfd_mips16_elf_reloc_unshuffle (input_bfd, r_type, FALSE, location);
+
   /* Obtain the current value.  */
   x = mips_elf_obtain_contents (howto, relocation, input_bfd, contents);
 
   /* Clear the field we are setting.  */
   x &= ~howto->dst_mask;
 
-  /* If this is the R_MIPS16_26 relocation, we must store the
-     value in a funny way.  */
-  if (r_type == R_MIPS16_26)
-    {
-      /* R_MIPS16_26 is used for the mips16 jal and jalx instructions.
-        Most mips16 instructions are 16 bits, but these instructions
-        are 32 bits.
-
-        The format of these instructions is:
-
-        +--------------+--------------------------------+
-        !     JALX     ! X!   Imm 20:16  !   Imm 25:21  !
-        +--------------+--------------------------------+
-        !                Immediate  15:0                   !
-        +-----------------------------------------------+
-
-        JALX is the 5-bit value 00011.  X is 0 for jal, 1 for jalx.
-        Note that the immediate value in the first word is swapped.
-
-        When producing a relocatable object file, R_MIPS16_26 is
-        handled mostly like R_MIPS_26.  In particular, the addend is
-        stored as a straight 26-bit value in a 32-bit instruction.
-        (gas makes life simpler for itself by never adjusting a
-        R_MIPS16_26 reloc to be against a section, so the addend is
-        always zero).  However, the 32 bit instruction is stored as 2
-        16-bit values, rather than a single 32-bit value.  In a
-        big-endian file, the result is the same; in a little-endian
-        file, the two 16-bit halves of the 32 bit value are swapped.
-        This is so that a disassembler can recognize the jal
-        instruction.
-
-        When doing a final link, R_MIPS16_26 is treated as a 32 bit
-        instruction stored as two 16-bit values.  The addend A is the
-        contents of the targ26 field.  The calculation is the same as
-        R_MIPS_26.  When storing the calculated value, reorder the
-        immediate value as shown above, and don't forget to store the
-        value as two 16-bit values.
-
-        To put it in MIPS ABI terms, the relocation field is T-targ26-16,
-        defined as
-
-        big-endian:
-        +--------+----------------------+
-        |        |                      |
-        |        |    targ26-16         |
-        |31    26|25                   0|
-        +--------+----------------------+
-
-        little-endian:
-        +----------+------+-------------+
-        |          |      |             |
-        |  sub1    |      |     sub2    |
-        |0        9|10  15|16         31|
-        +----------+--------------------+
-        where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is
-        ((sub1 << 16) | sub2)).
-
-        When producing a relocatable object file, the calculation is
-        (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
-        When producing a fully linked file, the calculation is
-        let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
-        ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff)  */
-
-      if (!info->relocatable)
-       /* Shuffle the bits according to the formula above.  */
-       value = (((value & 0x1f0000) << 5)
-                | ((value & 0x3e00000) >> 5)
-                | (value & 0xffff));
-    }
-  else if (r_type == R_MIPS16_GPREL)
-    {
-      /* R_MIPS16_GPREL is used for GP-relative addressing in mips16
-        mode.  A typical instruction will have a format like this:
-
-        +--------------+--------------------------------+
-        !    EXTEND    !     Imm 10:5    !   Imm 15:11  !
-        +--------------+--------------------------------+
-        !    Major     !   rx   !   ry   !   Imm  4:0   !
-        +--------------+--------------------------------+
-
-        EXTEND is the five bit value 11110.  Major is the instruction
-        opcode.
-
-        This is handled exactly like R_MIPS_GPREL16, except that the
-        addend is retrieved and stored as shown in this diagram; that
-        is, the Imm fields above replace the V-rel16 field.
-
-         All we need to do here is shuffle the bits appropriately.  As
-        above, the two 16-bit halves must be swapped on a
-        little-endian system.  */
-      value = (((value & 0x7e0) << 16)
-              | ((value & 0xf800) << 5)
-              | (value & 0x1f));
-    }
-
   /* Set the field.  */
   x |= (value & howto->dst_mask);
 
@@ -3688,9 +3697,9 @@ mips_elf_perform_relocation (info, howto, relocation, value, input_bfd,
       if (!ok)
        {
          (*_bfd_error_handler)
-           (_("%s: %s+0x%lx: jump to stub routine which is not jal"),
-            bfd_archive_filename (input_bfd),
-            input_section->name,
+           (_("%B: %A+0x%lx: jump to stub routine which is not jal"),
+            input_bfd,
+            input_section,
             (unsigned long) relocation->r_offset);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
@@ -3700,23 +3709,46 @@ mips_elf_perform_relocation (info, howto, relocation, value, input_bfd,
       x = (x & ~(0x3f << 26)) | (jalx_opcode << 26);
     }
 
-  /* Swap the high- and low-order 16 bits on little-endian systems
-     when doing a MIPS16 relocation.  */
-  if ((r_type == R_MIPS16_GPREL || r_type == R_MIPS16_26)
-      && bfd_little_endian (input_bfd))
-    x = (((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16));
+  /* On the RM9000, bal is faster than jal, because bal uses branch
+     prediction hardware.  If we are linking for the RM9000, and we
+     see jal, and bal fits, use it instead.  Note that this
+     transformation should be safe for all architectures.  */
+  if (bfd_get_mach (input_bfd) == bfd_mach_mips9000
+      && !info->relocatable
+      && !require_jalx
+      && ((r_type == R_MIPS_26 && (x >> 26) == 0x3)        /* jal addr */
+         || (r_type == R_MIPS_JALR && x == 0x0320f809)))   /* jalr t9 */
+    {
+      bfd_vma addr;
+      bfd_vma dest;
+      bfd_signed_vma off;
+
+      addr = (input_section->output_section->vma
+             + input_section->output_offset
+             + relocation->r_offset
+             + 4);
+      if (r_type == R_MIPS_26)
+       dest = (value << 2) | ((addr >> 28) << 28);
+      else
+       dest = value;
+      off = dest - addr;
+      if (off <= 0x1ffff && off >= -0x20000)
+       x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff);   /* bal addr */
+    }
 
   /* Put the value into the output.  */
   bfd_put (8 * bfd_get_reloc_size (howto), input_bfd, x, location);
+
+  _bfd_mips16_elf_reloc_shuffle(input_bfd, r_type, !info->relocatable,
+                               location);
+
   return TRUE;
 }
 
 /* Returns TRUE if SECTION is a MIPS16 stub section.  */
 
 static bfd_boolean
-mips_elf_stub_section_p (abfd, section)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *section;
+mips_elf_stub_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
 {
   const char *name = bfd_get_section_name (abfd, section);
 
@@ -3728,22 +3760,20 @@ mips_elf_stub_section_p (abfd, section)
 /* Add room for N relocations to the .rel.dyn section in ABFD.  */
 
 static void
-mips_elf_allocate_dynamic_relocations (abfd, n)
-     bfd *abfd;
-     unsigned int n;
+mips_elf_allocate_dynamic_relocations (bfd *abfd, unsigned int n)
 {
   asection *s;
 
   s = mips_elf_rel_dyn_section (abfd, FALSE);
   BFD_ASSERT (s != NULL);
 
-  if (s->_raw_size == 0)
+  if (s->size == 0)
     {
       /* Make room for a null element.  */
-      s->_raw_size += MIPS_ELF_REL_SIZE (abfd);
+      s->size += MIPS_ELF_REL_SIZE (abfd);
       ++s->reloc_count;
     }
-  s->_raw_size += n * MIPS_ELF_REL_SIZE (abfd);
+  s->size += n * MIPS_ELF_REL_SIZE (abfd);
 }
 
 /* Create a rel.dyn relocation for the dynamic linker to resolve.  REL
@@ -3752,22 +3782,19 @@ mips_elf_allocate_dynamic_relocations (abfd, n)
    caller should store the result in place of the original addend.  */
 
 static bfd_boolean
-mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
-                                   symbol, addendp, input_section)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     const Elf_Internal_Rela *rel;
-     struct mips_elf_link_hash_entry *h;
-     asection *sec;
-     bfd_vma symbol;
-     bfd_vma *addendp;
-     asection *input_section;
+mips_elf_create_dynamic_relocation (bfd *output_bfd,
+                                   struct bfd_link_info *info,
+                                   const Elf_Internal_Rela *rel,
+                                   struct mips_elf_link_hash_entry *h,
+                                   asection *sec, bfd_vma symbol,
+                                   bfd_vma *addendp, asection *input_section)
 {
   Elf_Internal_Rela outrel[3];
-  bfd_boolean skip;
   asection *sreloc;
   bfd *dynobj;
   int r_type;
+  long indx;
+  bfd_boolean defined_p;
 
   r_type = ELF_R_TYPE (output_bfd, rel->r_info);
   dynobj = elf_hash_table (info)->dynobj;
@@ -3775,9 +3802,8 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
   BFD_ASSERT (sreloc != NULL);
   BFD_ASSERT (sreloc->contents != NULL);
   BFD_ASSERT (sreloc->reloc_count * MIPS_ELF_REL_SIZE (output_bfd)
-             < sreloc->_raw_size);
+             < sreloc->size);
 
-  skip = FALSE;
   outrel[0].r_offset =
     _bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset);
   outrel[1].r_offset =
@@ -3804,128 +3830,115 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
       outrel[2].r_offset = outrel[0].r_offset;
       /* If we didn't need the relocation at all, this value will be
         -1.  */
-      if (outrel[0].r_offset == (bfd_vma) -1)
+      if (outrel[0].r_offset == MINUS_ONE)
        skip = TRUE;
     }
 #endif
 
-  if (outrel[0].r_offset == (bfd_vma) -1)
+  if (outrel[0].r_offset == MINUS_ONE)
     /* The relocation field has been deleted.  */
-    skip = TRUE;
-  else if (outrel[0].r_offset == (bfd_vma) -2)
+    return TRUE;
+
+  if (outrel[0].r_offset == MINUS_TWO)
     {
       /* The relocation field has been converted into a relative value of
         some sort.  Functions like _bfd_elf_write_section_eh_frame expect
         the field to be fully relocated, so add in the symbol's value.  */
-      skip = TRUE;
       *addendp += symbol;
+      return TRUE;
     }
 
-  /* If we've decided to skip this relocation, just output an empty
-     record.  Note that R_MIPS_NONE == 0, so that this call to memset
-     is a way of setting R_TYPE to R_MIPS_NONE.  */
-  if (skip)
-    memset (outrel, 0, sizeof (Elf_Internal_Rela) * 3);
+  /* We must now calculate the dynamic symbol table index to use
+     in the relocation.  */
+  if (h != NULL
+      && (! info->symbolic || !h->root.def_regular)
+      /* h->root.dynindx may be -1 if this symbol was marked to
+        become local.  */
+      && h->root.dynindx != -1)
+    {
+      indx = h->root.dynindx;
+      if (SGI_COMPAT (output_bfd))
+       defined_p = h->root.def_regular;
+      else
+       /* ??? glibc's ld.so just adds the final GOT entry to the
+          relocation field.  It therefore treats relocs against
+          defined symbols in the same way as relocs against
+          undefined symbols.  */
+       defined_p = FALSE;
+    }
   else
     {
-      long indx;
-      bfd_boolean defined_p;
-
-      /* We must now calculate the dynamic symbol table index to use
-        in the relocation.  */
-      if (h != NULL
-         && (! info->symbolic || (h->root.elf_link_hash_flags
-                                  & ELF_LINK_HASH_DEF_REGULAR) == 0)
-         /* h->root.dynindx may be -1 if this symbol was marked to
-            become local.  */
-         && h->root.dynindx != -1)
+      if (sec != NULL && bfd_is_abs_section (sec))
+       indx = 0;
+      else if (sec == NULL || sec->owner == NULL)
        {
-         indx = h->root.dynindx;
-         if (SGI_COMPAT (output_bfd))
-           defined_p = ((h->root.elf_link_hash_flags
-                         & ELF_LINK_HASH_DEF_REGULAR) != 0);
-         else
-           /* ??? glibc's ld.so just adds the final GOT entry to the
-              relocation field.  It therefore treats relocs against
-              defined symbols in the same way as relocs against
-              undefined symbols.  */
-           defined_p = FALSE;
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
        }
       else
        {
-         if (sec != NULL && bfd_is_abs_section (sec))
-           indx = 0;
-         else if (sec == NULL || sec->owner == NULL)
-           {
-             bfd_set_error (bfd_error_bad_value);
-             return FALSE;
-           }
-         else
-           {
-             indx = elf_section_data (sec->output_section)->dynindx;
-             if (indx == 0)
-               abort ();
-           }
-
-         /* Instead of generating a relocation using the section
-            symbol, we may as well make it a fully relative
-            relocation.  We want to avoid generating relocations to
-            local symbols because we used to generate them
-            incorrectly, without adding the original symbol value,
-            which is mandated by the ABI for section symbols.  In
-            order to give dynamic loaders and applications time to
-            phase out the incorrect use, we refrain from emitting
-            section-relative relocations.  It's not like they're
-            useful, after all.  This should be a bit more efficient
-            as well.  */
-         /* ??? Although this behavior is compatible with glibc's ld.so,
-            the ABI says that relocations against STN_UNDEF should have
-            a symbol value of 0.  Irix rld honors this, so relocations
-            against STN_UNDEF have no effect.  */
-         if (!SGI_COMPAT (output_bfd))
-           indx = 0;
-         defined_p = TRUE;
+         indx = elf_section_data (sec->output_section)->dynindx;
+         if (indx == 0)
+           abort ();
        }
 
-      /* If the relocation was previously an absolute relocation and
-        this symbol will not be referred to by the relocation, we must
-        adjust it by the value we give it in the dynamic symbol table.
-        Otherwise leave the job up to the dynamic linker.  */
-      if (defined_p && r_type != R_MIPS_REL32)
-       *addendp += symbol;
-
-      /* The relocation is always an REL32 relocation because we don't
-        know where the shared library will wind up at load-time.  */
-      outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
-                                    R_MIPS_REL32);
-      /* For strict adherence to the ABI specification, we should
-        generate a R_MIPS_64 relocation record by itself before the
-        _REL32/_64 record as well, such that the addend is read in as
-        a 64-bit value (REL32 is a 32-bit relocation, after all).
-        However, since none of the existing ELF64 MIPS dynamic
-        loaders seems to care, we don't waste space with these
-        artificial relocations.  If this turns out to not be true,
-        mips_elf_allocate_dynamic_relocation() should be tweaked so
-        as to make room for a pair of dynamic relocations per
-        invocation if ABI_64_P, and here we should generate an
-        additional relocation record with R_MIPS_64 by itself for a
-        NULL symbol before this relocation record.  */
-      outrel[1].r_info = ELF_R_INFO (output_bfd, (unsigned long) 0,
-                                    ABI_64_P (output_bfd)
-                                    ? R_MIPS_64
-                                    : R_MIPS_NONE);
-      outrel[2].r_info = ELF_R_INFO (output_bfd, (unsigned long) 0,
-                                    R_MIPS_NONE);
-
-      /* Adjust the output offset of the relocation to reference the
-        correct location in the output file.  */
-      outrel[0].r_offset += (input_section->output_section->vma
-                            + input_section->output_offset);
-      outrel[1].r_offset += (input_section->output_section->vma
-                            + input_section->output_offset);
-      outrel[2].r_offset += (input_section->output_section->vma
-                            + input_section->output_offset);
-    }
+      /* Instead of generating a relocation using the section
+        symbol, we may as well make it a fully relative
+        relocation.  We want to avoid generating relocations to
+        local symbols because we used to generate them
+        incorrectly, without adding the original symbol value,
+        which is mandated by the ABI for section symbols.  In
+        order to give dynamic loaders and applications time to
+        phase out the incorrect use, we refrain from emitting
+        section-relative relocations.  It's not like they're
+        useful, after all.  This should be a bit more efficient
+        as well.  */
+      /* ??? Although this behavior is compatible with glibc's ld.so,
+        the ABI says that relocations against STN_UNDEF should have
+        a symbol value of 0.  Irix rld honors this, so relocations
+        against STN_UNDEF have no effect.  */
+      if (!SGI_COMPAT (output_bfd))
+       indx = 0;
+      defined_p = TRUE;
+    }
+
+  /* If the relocation was previously an absolute relocation and
+     this symbol will not be referred to by the relocation, we must
+     adjust it by the value we give it in the dynamic symbol table.
+     Otherwise leave the job up to the dynamic linker.  */
+  if (defined_p && r_type != R_MIPS_REL32)
+    *addendp += symbol;
+
+  /* The relocation is always an REL32 relocation because we don't
+     know where the shared library will wind up at load-time.  */
+  outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
+                                R_MIPS_REL32);
+  /* For strict adherence to the ABI specification, we should
+     generate a R_MIPS_64 relocation record by itself before the
+     _REL32/_64 record as well, such that the addend is read in as
+     a 64-bit value (REL32 is a 32-bit relocation, after all).
+     However, since none of the existing ELF64 MIPS dynamic
+     loaders seems to care, we don't waste space with these
+     artificial relocations.  If this turns out to not be true,
+     mips_elf_allocate_dynamic_relocation() should be tweaked so
+     as to make room for a pair of dynamic relocations per
+     invocation if ABI_64_P, and here we should generate an
+     additional relocation record with R_MIPS_64 by itself for a
+     NULL symbol before this relocation record.  */
+  outrel[1].r_info = ELF_R_INFO (output_bfd, 0,
+                                ABI_64_P (output_bfd)
+                                ? R_MIPS_64
+                                : R_MIPS_NONE);
+  outrel[2].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_NONE);
+
+  /* Adjust the output offset of the relocation to reference the
+     correct location in the output file.  */
+  outrel[0].r_offset += (input_section->output_section->vma
+                        + input_section->output_offset);
+  outrel[1].r_offset += (input_section->output_section->vma
+                        + input_section->output_offset);
+  outrel[2].r_offset += (input_section->output_section->vma
+                        + input_section->output_offset);
 
   /* Put the relocation back out.  We have to use the special
      relocation outputter in the 64-bit case since the 64-bit
@@ -3951,7 +3964,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
     |= SHF_WRITE;
 
   /* On IRIX5, make an entry of compact relocation info.  */
-  if (! skip && IRIX_COMPAT (output_bfd) == ict_irix5)
+  if (IRIX_COMPAT (output_bfd) == ict_irix5)
     {
       asection *scpt = bfd_get_section_by_name (dynobj, ".compact_rel");
       bfd_byte *cr;
@@ -3986,8 +3999,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
 /* Return the MACH for a MIPS e_flags value.  */
 
 unsigned long
-_bfd_elf_mips_mach (flags)
-     flagword flags;
+_bfd_elf_mips_mach (flagword flags)
 {
   switch (flags & EF_MIPS_MACH)
     {
@@ -4015,6 +4027,9 @@ _bfd_elf_mips_mach (flags)
     case E_MIPS_MACH_5500:
       return bfd_mach_mips5500;
 
+    case E_MIPS_MACH_9000:
+      return bfd_mach_mips9000;
+
     case E_MIPS_MACH_SB1:
       return bfd_mach_mips_sb1;
 
@@ -4053,6 +4068,10 @@ _bfd_elf_mips_mach (flags)
        case E_MIPS_ARCH_32R2:
          return bfd_mach_mipsisa32r2;
          break;
+
+       case E_MIPS_ARCH_64R2:
+         return bfd_mach_mipsisa64r2;
+         break;
        }
     }
 
@@ -4062,8 +4081,7 @@ _bfd_elf_mips_mach (flags)
 /* Return printable name for ABI.  */
 
 static INLINE char *
-elf_mips_abi_name (abfd)
-     bfd *abfd;
+elf_mips_abi_name (bfd *abfd)
 {
   flagword flags;
 
@@ -4110,9 +4128,7 @@ static asymbol *mips_elf_acom_symbol_ptr;
    This is used for both the 32-bit and the 64-bit ABI.  */
 
 void
-_bfd_mips_elf_symbol_processing (abfd, asym)
-     bfd *abfd;
-     asymbol *asym;
+_bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym)
 {
   elf_symbol_type *elfsym;
 
@@ -4170,27 +4186,133 @@ _bfd_mips_elf_symbol_processing (abfd, asym)
       asym->section = bfd_und_section_ptr;
       break;
 
-#if 0 /* for SGI_COMPAT */
     case SHN_MIPS_TEXT:
-      asym->section = mips_elf_text_section_ptr;
+      {
+       asection *section = bfd_get_section_by_name (abfd, ".text");
+
+       BFD_ASSERT (SGI_COMPAT (abfd));
+       if (section != NULL)
+         {
+           asym->section = section;
+           /* MIPS_TEXT is a bit special, the address is not an offset
+              to the base of the .text section.  So substract the section
+              base address to make it an offset.  */
+           asym->value -= section->vma;
+         }
+      }
       break;
 
     case SHN_MIPS_DATA:
-      asym->section = mips_elf_data_section_ptr;
+      {
+       asection *section = bfd_get_section_by_name (abfd, ".data");
+
+       BFD_ASSERT (SGI_COMPAT (abfd));
+       if (section != NULL)
+         {
+           asym->section = section;
+           /* MIPS_DATA is a bit special, the address is not an offset
+              to the base of the .data section.  So substract the section
+              base address to make it an offset.  */
+           asym->value -= section->vma;
+         }
+      }
       break;
-#endif
     }
 }
 \f
+/* Implement elf_backend_eh_frame_address_size.  This differs from
+   the default in the way it handles EABI64.
+
+   EABI64 was originally specified as an LP64 ABI, and that is what
+   -mabi=eabi normally gives on a 64-bit target.  However, gcc has
+   historically accepted the combination of -mabi=eabi and -mlong32,
+   and this ILP32 variation has become semi-official over time.
+   Both forms use elf32 and have pointer-sized FDE addresses.
+
+   If an EABI object was generated by GCC 4.0 or above, it will have
+   an empty .gcc_compiled_longXX section, where XX is the size of longs
+   in bits.  Unfortunately, ILP32 objects generated by earlier compilers
+   have no special marking to distinguish them from LP64 objects.
+
+   We don't want users of the official LP64 ABI to be punished for the
+   existence of the ILP32 variant, but at the same time, we don't want
+   to mistakenly interpret pre-4.0 ILP32 objects as being LP64 objects.
+   We therefore take the following approach:
+
+      - If ABFD contains a .gcc_compiled_longXX section, use it to
+        determine the pointer size.
+
+      - Otherwise check the type of the first relocation.  Assume that
+        the LP64 ABI is being used if the relocation is of type R_MIPS_64.
+
+      - Otherwise punt.
+
+   The second check is enough to detect LP64 objects generated by pre-4.0
+   compilers because, in the kind of output generated by those compilers,
+   the first relocation will be associated with either a CIE personality
+   routine or an FDE start address.  Furthermore, the compilers never
+   used a special (non-pointer) encoding for this ABI.
+
+   Checking the relocation type should also be safe because there is no
+   reason to use R_MIPS_64 in an ILP32 object.  Pre-4.0 compilers never
+   did so.  */
+
+unsigned int
+_bfd_mips_elf_eh_frame_address_size (bfd *abfd, asection *sec)
+{
+  if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
+    return 8;
+  if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64)
+    {
+      bfd_boolean long32_p, long64_p;
+
+      long32_p = bfd_get_section_by_name (abfd, ".gcc_compiled_long32") != 0;
+      long64_p = bfd_get_section_by_name (abfd, ".gcc_compiled_long64") != 0;
+      if (long32_p && long64_p)
+       return 0;
+      if (long32_p)
+       return 4;
+      if (long64_p)
+       return 8;
+
+      if (sec->reloc_count > 0
+         && elf_section_data (sec)->relocs != NULL
+         && (ELF32_R_TYPE (elf_section_data (sec)->relocs[0].r_info)
+             == R_MIPS_64))
+       return 8;
+
+      return 0;
+    }
+  return 4;
+}
+\f
+/* There appears to be a bug in the MIPSpro linker that causes GOT_DISP
+   relocations against two unnamed section symbols to resolve to the
+   same address.  For example, if we have code like:
+
+       lw      $4,%got_disp(.data)($gp)
+       lw      $25,%got_disp(.text)($gp)
+       jalr    $25
+
+   then the linker will resolve both relocations to .data and the program
+   will jump there rather than to .text.
+
+   We can work around this problem by giving names to local section symbols.
+   This is also what the MIPSpro tools do.  */
+
+bfd_boolean
+_bfd_mips_elf_name_local_section_symbols (bfd *abfd)
+{
+  return SGI_COMPAT (abfd);
+}
+\f
 /* Work over a section just before writing it out.  This routine is
    used by both the 32-bit and the 64-bit ABI.  FIXME: We recognize
    sections that need the SHF_MIPS_GPREL flag by name; there has to be
    a better way.  */
 
 bfd_boolean
-_bfd_mips_elf_section_processing (abfd, hdr)
-     bfd *abfd;
-     Elf_Internal_Shdr *hdr;
+_bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr)
 {
   if (hdr->sh_type == SHT_MIPS_REGINFO
       && hdr->sh_size > 0)
@@ -4205,7 +4327,7 @@ _bfd_mips_elf_section_processing (abfd, hdr)
                    SEEK_SET) != 0)
        return FALSE;
       H_PUT_32 (abfd, elf_gp (abfd), buf);
-      if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
+      if (bfd_bwrite (buf, 4, abfd) != 4)
        return FALSE;
     }
 
@@ -4244,7 +4366,7 @@ _bfd_mips_elf_section_processing (abfd, hdr)
                             SEEK_SET) != 0)
                return FALSE;
              H_PUT_64 (abfd, elf_gp (abfd), buf);
-             if (bfd_bwrite (buf, (bfd_size_type) 8, abfd) != 8)
+             if (bfd_bwrite (buf, 8, abfd) != 8)
                return FALSE;
            }
          else if (intopt.kind == ODK_REGINFO)
@@ -4259,7 +4381,7 @@ _bfd_mips_elf_section_processing (abfd, hdr)
                            SEEK_SET) != 0)
                return FALSE;
              H_PUT_32 (abfd, elf_gp (abfd), buf);
-             if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
+             if (bfd_bwrite (buf, 4, abfd) != 4)
                return FALSE;
            }
          l += intopt.size;
@@ -4316,10 +4438,8 @@ _bfd_mips_elf_section_processing (abfd, hdr)
    how to.  */
 
 bfd_boolean
-_bfd_mips_elf_section_from_shdr (abfd, hdr, name)
-     bfd *abfd;
-     Elf_Internal_Shdr *hdr;
-     const char *name;
+_bfd_mips_elf_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr,
+                                const char *name)
 {
   flagword flags = 0;
 
@@ -4414,9 +4534,8 @@ _bfd_mips_elf_section_from_shdr (abfd, hdr, name)
       Elf32_External_RegInfo ext;
       Elf32_RegInfo s;
 
-      if (! bfd_get_section_contents (abfd, hdr->bfd_section, (PTR) &ext,
-                                     (file_ptr) 0,
-                                     (bfd_size_type) sizeof ext))
+      if (! bfd_get_section_contents (abfd, hdr->bfd_section,
+                                     &ext, 0, sizeof ext))
        return FALSE;
       bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s);
       elf_gp (abfd) = s.ri_gp_value;
@@ -4430,11 +4549,11 @@ _bfd_mips_elf_section_from_shdr (abfd, hdr, name)
     {
       bfd_byte *contents, *l, *lend;
 
-      contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
+      contents = bfd_malloc (hdr->sh_size);
       if (contents == NULL)
        return FALSE;
       if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
-                                     (file_ptr) 0, hdr->sh_size))
+                                     0, hdr->sh_size))
        {
          free (contents);
          return FALSE;
@@ -4482,10 +4601,7 @@ _bfd_mips_elf_section_from_shdr (abfd, hdr, name)
    used by both the 32-bit and the 64-bit ABI.  */
 
 bfd_boolean
-_bfd_mips_elf_fake_sections (abfd, hdr, sec)
-     bfd *abfd;
-     Elf_Internal_Shdr *hdr;
-     asection *sec;
+_bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
 {
   register const char *name;
 
@@ -4494,7 +4610,7 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
   if (strcmp (name, ".liblist") == 0)
     {
       hdr->sh_type = SHT_MIPS_LIBLIST;
-      hdr->sh_info = sec->_raw_size / sizeof (Elf32_Lib);
+      hdr->sh_info = sec->size / sizeof (Elf32_Lib);
       /* The sh_link field is set in final_write_processing.  */
     }
   else if (strcmp (name, ".conflict") == 0)
@@ -4607,10 +4723,8 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
    the .scommon section.  */
 
 bfd_boolean
-_bfd_mips_elf_section_from_bfd_section (abfd, sec, retval)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *sec;
-     int *retval;
+_bfd_mips_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
+                                       asection *sec, int *retval)
 {
   if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
     {
@@ -4629,14 +4743,10 @@ _bfd_mips_elf_section_from_bfd_section (abfd, sec, retval)
    file.  We must handle the special MIPS section numbers here.  */
 
 bfd_boolean
-_bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     const Elf_Internal_Sym *sym;
-     const char **namep;
-     flagword *flagsp ATTRIBUTE_UNUSED;
-     asection **secp;
-     bfd_vma *valp;
+_bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
+                              Elf_Internal_Sym *sym, const char **namep,
+                              flagword *flagsp ATTRIBUTE_UNUSED,
+                              asection **secp, bfd_vma *valp)
 {
   if (SGI_COMPAT (abfd)
       && (abfd->flags & DYNAMIC) != 0
@@ -4758,17 +4868,16 @@ _bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
       /* Mark __rld_obj_head as dynamic.  */
       bh = NULL;
       if (! (_bfd_generic_link_add_one_symbol
-            (info, abfd, *namep, BSF_GLOBAL, *secp,
-             (bfd_vma) *valp, (const char *) NULL, FALSE,
+            (info, abfd, *namep, BSF_GLOBAL, *secp, *valp, NULL, FALSE,
              get_elf_backend_data (abfd)->collect, &bh)))
        return FALSE;
 
       h = (struct elf_link_hash_entry *) bh;
-      h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
-      h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+      h->non_elf = 0;
+      h->def_regular = 1;
       h->type = STT_OBJECT;
 
-      if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+      if (! bfd_elf_link_record_dynamic_symbol (info, h))
        return FALSE;
 
       mips_elf_hash_table (info)->use_rld_obj_head = TRUE;
@@ -4788,12 +4897,10 @@ _bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
    also where we undo the increment of the value for a mips16 symbol.  */
 
 bfd_boolean
-_bfd_mips_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     const char *name ATTRIBUTE_UNUSED;
-     Elf_Internal_Sym *sym;
-     asection *input_sec;
+_bfd_mips_elf_link_output_symbol_hook
+  (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+   const char *name ATTRIBUTE_UNUSED, Elf_Internal_Sym *sym,
+   asection *input_sec, struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
 {
   /* If we see a common symbol, which implies a relocatable link, then
      if a symbol was small common in an input file, mark it as small
@@ -4802,9 +4909,8 @@ _bfd_mips_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
       && strcmp (input_sec->name, ".scommon") == 0)
     sym->st_shndx = SHN_MIPS_SCOMMON;
 
-  if (sym->st_other == STO_MIPS16
-      && (sym->st_value & 1) != 0)
-    --sym->st_value;
+  if (sym->st_other == STO_MIPS16)
+    sym->st_value &= ~1;
 
   return TRUE;
 }
@@ -4814,9 +4920,7 @@ _bfd_mips_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
 /* Create dynamic sections when linking against a dynamic object.  */
 
 bfd_boolean
-_bfd_mips_elf_create_dynamic_sections (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 {
   struct elf_link_hash_entry *h;
   struct bfd_link_hash_entry *bh;
@@ -4876,17 +4980,16 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
        {
          bh = NULL;
          if (! (_bfd_generic_link_add_one_symbol
-                (info, abfd, *namep, BSF_GLOBAL, bfd_und_section_ptr,
-                 (bfd_vma) 0, (const char *) NULL, FALSE,
-                 get_elf_backend_data (abfd)->collect, &bh)))
+                (info, abfd, *namep, BSF_GLOBAL, bfd_und_section_ptr, 0,
+                 NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
            return FALSE;
 
          h = (struct elf_link_hash_entry *) bh;
-         h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
-         h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+         h->non_elf = 0;
+         h->def_regular = 1;
          h->type = STT_SECTION;
 
-         if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+         if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
        }
 
@@ -4922,17 +5025,16 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
       name = SGI_COMPAT (abfd) ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING";
       bh = NULL;
       if (!(_bfd_generic_link_add_one_symbol
-           (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr,
-            (bfd_vma) 0, (const char *) NULL, FALSE,
-            get_elf_backend_data (abfd)->collect, &bh)))
+           (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, 0,
+            NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
        return FALSE;
 
       h = (struct elf_link_hash_entry *) bh;
-      h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
-      h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+      h->non_elf = 0;
+      h->def_regular = 1;
       h->type = STT_SECTION;
 
-      if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+      if (! bfd_elf_link_record_dynamic_symbol (info, h))
        return FALSE;
 
       if (! mips_elf_hash_table (info)->use_rld_obj_head)
@@ -4947,17 +5049,16 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
          name = SGI_COMPAT (abfd) ? "__rld_map" : "__RLD_MAP";
          bh = NULL;
          if (!(_bfd_generic_link_add_one_symbol
-               (info, abfd, name, BSF_GLOBAL, s,
-                (bfd_vma) 0, (const char *) NULL, FALSE,
+               (info, abfd, name, BSF_GLOBAL, s, 0, NULL, FALSE,
                 get_elf_backend_data (abfd)->collect, &bh)))
            return FALSE;
 
          h = (struct elf_link_hash_entry *) bh;
-         h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
-         h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+         h->non_elf = 0;
+         h->def_regular = 1;
          h->type = STT_OBJECT;
 
-         if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+         if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
        }
     }
@@ -4969,11 +5070,8 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
    allocate space in the global offset table.  */
 
 bfd_boolean
-_bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+_bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
+                           asection *sec, const Elf_Internal_Rela *relocs)
 {
   const char *name;
   bfd *dynobj;
@@ -4985,7 +5083,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
   const Elf_Internal_Rela *rel_end;
   asection *sgot;
   asection *sreloc;
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
 
   if (info->relocatable)
     return TRUE;
@@ -5032,8 +5130,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
                continue;
 
              sec_relocs
-               = _bfd_elf_link_read_relocs (abfd, o, (PTR) NULL,
-                                            (Elf_Internal_Rela *) NULL,
+               = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
                                             info->keep_memory);
              if (sec_relocs == NULL)
                return FALSE;
@@ -5075,7 +5172,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
              else
                symcount = symtab_hdr->sh_info;
              amt = symcount * sizeof (asection *);
-             n = (asection **) bfd_zalloc (abfd, amt);
+             n = bfd_zalloc (abfd, amt);
              if (n == NULL)
                return FALSE;
              elf_tdata (abfd)->local_stubs = n;
@@ -5189,8 +5286,8 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
       else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
        {
          (*_bfd_error_handler)
-           (_("%s: Malformed reloc detected for section %s"),
-            bfd_archive_filename (abfd), name);
+           (_("%B: Malformed reloc detected for section %s"),
+            abfd, name);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
@@ -5263,8 +5360,8 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
          if (h == NULL)
            {
              (*_bfd_error_handler)
-               (_("%s: CALL16 reloc at 0x%lx not against global symbol"),
-                bfd_archive_filename (abfd), (unsigned long) rel->r_offset);
+               (_("%B: CALL16 reloc at 0x%lx not against global symbol"),
+                abfd, (unsigned long) rel->r_offset);
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
            }
@@ -5280,8 +5377,8 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
 
              /* We need a stub, not a plt entry for the undefined
                 function.  But we record it as if it needs plt.  See
-                elf_adjust_dynamic_symbol in elflink.h.  */
-             h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+                _bfd_elf_adjust_dynamic_symbol.  */
+             h->needs_plt = 1;
              h->type = STT_FUNC;
            }
          break;
@@ -5301,25 +5398,9 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
                hmips = (struct mips_elf_link_hash_entry *)
                  hmips->root.root.u.i.link;
 
-             if ((hmips->root.root.type == bfd_link_hash_defined
-                  || hmips->root.root.type == bfd_link_hash_defweak)
-                 && hmips->root.root.u.def.section
+             if (hmips->root.def_regular
                  && ! (info->shared && ! info->symbolic
-                       && ! (hmips->root.elf_link_hash_flags
-                             & ELF_LINK_FORCED_LOCAL))
-                 /* If we've encountered any other relocation
-                    referencing the symbol, we'll have marked it as
-                    dynamic, and, even though we might be able to get
-                    rid of the GOT entry should we know for sure all
-                    previous relocations were GOT_PAGE ones, at this
-                    point we can't tell, so just keep using the
-                    symbol as dynamic.  This is very important in the
-                    multi-got case, since we don't decide whether to
-                    decay GOT_PAGE to GOT_DISP on a per-GOT basis: if
-                    the symbol is dynamic, we'll need a GOT entry for
-                    every GOT in which the symbol is referenced with
-                    a GOT_PAGE relocation.  */
-                 && hmips->root.dynindx == -1)
+                       && ! hmips->root.forced_local))
                break;
            }
          /* Fall through.  */
@@ -5407,14 +5488,14 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
          /* This relocation describes the C++ object vtable hierarchy.
             Reconstruct it for later use during GC.  */
        case R_MIPS_GNU_VTINHERIT:
-         if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+         if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
            return FALSE;
          break;
 
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_MIPS_GNU_VTENTRY:
-         if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
            return FALSE;
          break;
 
@@ -5465,17 +5546,14 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
 }
 \f
 bfd_boolean
-_bfd_mips_relax_section (abfd, sec, link_info, again)
-     bfd *abfd;
-     asection *sec;
-     struct bfd_link_info *link_info;
-     bfd_boolean *again;
+_bfd_mips_relax_section (bfd *abfd, asection *sec,
+                        struct bfd_link_info *link_info,
+                        bfd_boolean *again)
 {
   Elf_Internal_Rela *internal_relocs;
   Elf_Internal_Rela *irel, *irelend;
   Elf_Internal_Shdr *symtab_hdr;
   bfd_byte *contents = NULL;
-  bfd_byte *free_contents = NULL;
   size_t extsymoff;
   bfd_boolean changed_contents = FALSE;
   bfd_vma sec_start = sec->output_section->vma + sec->output_offset;
@@ -5487,8 +5565,7 @@ _bfd_mips_relax_section (abfd, sec, link_info, again)
   if (link_info->relocatable)
     return TRUE;
 
-  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, (PTR) NULL,
-                                              (Elf_Internal_Rela *) NULL,
+  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
                                               link_info->keep_memory);
   if (internal_relocs == NULL)
     return TRUE;
@@ -5532,7 +5609,7 @@ _bfd_mips_relax_section (abfd, sec, link_info, again)
                  || h->root.root.type == bfd_link_hash_defweak)
                 && h->root.root.u.def.section)
              || (link_info->shared && ! link_info->symbolic
-                 && ! (h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)))
+                 && !h->root.forced_local))
            continue;
 
          sym_sec = h->root.root.u.def.section;
@@ -5597,13 +5674,7 @@ _bfd_mips_relax_section (abfd, sec, link_info, again)
            contents = elf_section_data (sec)->this_hdr.contents;
          else
            {
-             contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
-             if (contents == NULL)
-               goto relax_return;
-
-             free_contents = contents;
-             if (! bfd_get_section_contents (abfd, sec, contents,
-                                             (file_ptr) 0, sec->_raw_size))
+             if (!bfd_malloc_and_get_section (abfd, sec, &contents))
                goto relax_return;
            }
        }
@@ -5638,8 +5709,9 @@ _bfd_mips_relax_section (abfd, sec, link_info, again)
   return TRUE;
 
  relax_return:
-  if (free_contents != NULL)
-    free (free_contents);
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
   return FALSE;
 }
 \f
@@ -5650,9 +5722,8 @@ _bfd_mips_relax_section (abfd, sec, link_info, again)
    understand.  */
 
 bfd_boolean
-_bfd_mips_elf_adjust_dynamic_symbol (info, h)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
+_bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
+                                    struct elf_link_hash_entry *h)
 {
   bfd *dynobj;
   struct mips_elf_link_hash_entry *hmips;
@@ -5662,14 +5733,11 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
 
   /* Make sure we know what is going on here.  */
   BFD_ASSERT (dynobj != NULL
-             && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
-                 || h->weakdef != NULL
-                 || ((h->elf_link_hash_flags
-                      & ELF_LINK_HASH_DEF_DYNAMIC) != 0
-                     && (h->elf_link_hash_flags
-                         & ELF_LINK_HASH_REF_REGULAR) != 0
-                     && (h->elf_link_hash_flags
-                         & ELF_LINK_HASH_DEF_REGULAR) == 0)));
+             && (h->needs_plt
+                 || h->u.weakdef != NULL
+                 || (h->def_dynamic
+                     && h->ref_regular
+                     && !h->def_regular)));
 
   /* If this symbol is defined in a dynamic object, we need to copy
      any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
@@ -5678,8 +5746,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
   if (! info->relocatable
       && hmips->possibly_dynamic_relocs != 0
       && (h->root.type == bfd_link_hash_defweak
-         || (h->elf_link_hash_flags
-             & ELF_LINK_HASH_DEF_REGULAR) == 0))
+         || !h->def_regular))
     {
       mips_elf_allocate_dynamic_relocations (dynobj,
                                             hmips->possibly_dynamic_relocs);
@@ -5691,7 +5758,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
 
   /* For a function, create a stub, if allowed.  */
   if (! hmips->no_fn_stub
-      && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+      && h->needs_plt)
     {
       if (! elf_hash_table (info)->dynamic_sections_created)
        return TRUE;
@@ -5700,7 +5767,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
         the symbol to the stub location.  This is required to make
         function pointers compare as equal between the normal
         executable and the shared library.  */
-      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+      if (!h->def_regular)
        {
          /* We need .stub section.  */
          s = bfd_get_section_by_name (dynobj,
@@ -5708,13 +5775,13 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
          BFD_ASSERT (s != NULL);
 
          h->root.u.def.section = s;
-         h->root.u.def.value = s->_raw_size;
+         h->root.u.def.value = s->size;
 
          /* XXX Write this stub address somewhere.  */
-         h->plt.offset = s->_raw_size;
+         h->plt.offset = s->size;
 
          /* Make room for this stub code.  */
-         s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
+         s->size += MIPS_FUNCTION_STUB_SIZE;
 
          /* The last half word of the stub will be filled with the index
             of this symbol in .dynsym section.  */
@@ -5722,7 +5789,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
        }
     }
   else if ((h->type == STT_FUNC)
-          && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
+          && !h->needs_plt)
     {
       /* This will set the entry for this symbol in the GOT to 0, and
          the dynamic linker will take care of this.  */
@@ -5733,12 +5800,12 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->weakdef != NULL)
+  if (h->u.weakdef != NULL)
     {
-      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
-                 || h->weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->weakdef->root.u.def.section;
-      h->root.u.def.value = h->weakdef->root.u.def.value;
+      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+                 || h->u.weakdef->root.type == bfd_link_hash_defweak);
+      h->root.u.def.section = h->u.weakdef->root.u.def.section;
+      h->root.u.def.value = h->u.weakdef->root.u.def.value;
       return TRUE;
     }
 
@@ -5753,9 +5820,8 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
    check for any mips16 stub sections that we can discard.  */
 
 bfd_boolean
-_bfd_mips_elf_always_size_sections (output_bfd, info)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
+_bfd_mips_elf_always_size_sections (bfd *output_bfd,
+                                   struct bfd_link_info *info)
 {
   asection *ri;
 
@@ -5770,14 +5836,12 @@ _bfd_mips_elf_always_size_sections (output_bfd, info)
   /* The .reginfo section has a fixed size.  */
   ri = bfd_get_section_by_name (output_bfd, ".reginfo");
   if (ri != NULL)
-    bfd_set_section_size (output_bfd, ri,
-                         (bfd_size_type) sizeof (Elf32_External_RegInfo));
+    bfd_set_section_size (output_bfd, ri, sizeof (Elf32_External_RegInfo));
 
   if (! (info->relocatable
         || ! mips_elf_hash_table (info)->mips16_stubs_seen))
     mips_elf_link_hash_traverse (mips_elf_hash_table (info),
-                                mips_elf_check_mips16_stubs,
-                                (PTR) NULL);
+                                mips_elf_check_mips16_stubs, NULL);
 
   dynobj = elf_hash_table (info)->dynobj;
   if (dynobj == NULL)
@@ -5801,7 +5865,7 @@ _bfd_mips_elf_always_size_sections (output_bfd, info)
        {
          if ((subsection->flags & SEC_ALLOC) == 0)
            continue;
-         loadable_size += ((subsection->_raw_size + 0xf)
+         loadable_size += ((subsection->size + 0xf)
                            &~ (bfd_size_type) 0xf);
        }
     }
@@ -5831,12 +5895,12 @@ _bfd_mips_elf_always_size_sections (output_bfd, info)
   local_gotno = (loadable_size >> 16) + 5;
 
   g->local_gotno += local_gotno;
-  s->_raw_size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
+  s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
 
   g->global_gotno = i;
-  s->_raw_size += i * MIPS_ELF_GOT_SIZE (output_bfd);
+  s->size += i * MIPS_ELF_GOT_SIZE (output_bfd);
 
-  if (s->_raw_size > MIPS_ELF_GOT_MAX_SIZE (output_bfd)
+  if (s->size > MIPS_ELF_GOT_MAX_SIZE (output_bfd)
       && ! mips_elf_multi_got (output_bfd, info, g, s, local_gotno))
     return FALSE;
 
@@ -5846,9 +5910,8 @@ _bfd_mips_elf_always_size_sections (output_bfd, info)
 /* Set the sizes of the dynamic sections.  */
 
 bfd_boolean
-_bfd_mips_elf_size_dynamic_sections (output_bfd, info)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
+_bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
+                                    struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *s;
@@ -5860,11 +5923,11 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (! info->shared)
+      if (info->executable)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
-         s->_raw_size
+         s->size
            = strlen (ELF_DYNAMIC_INTERPRETER (output_bfd)) + 1;
          s->contents
            = (bfd_byte *) ELF_DYNAMIC_INTERPRETER (output_bfd);
@@ -5891,7 +5954,7 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
 
       if (strncmp (name, ".rel", 4) == 0)
        {
-         if (s->_raw_size == 0)
+         if (s->size == 0)
            {
              /* We only strip the section if the output section name
                  has the same name.  Otherwise, there might be several
@@ -5991,7 +6054,7 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
        {
          /* IRIX rld assumes that the function stub isn't at the end
             of .text section. So put a dummy. XXX  */
-         s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
+         s->size += MIPS_FUNCTION_STUB_SIZE;
        }
       else if (! info->shared
               && ! mips_elf_hash_table (info)->use_rld_obj_head
@@ -5999,11 +6062,11 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
        {
          /* We add a room for __rld_map. It will be filled in by the
             rtld to contain a pointer to the _r_debug structure.  */
-         s->_raw_size += 4;
+         s->size += 4;
        }
       else if (SGI_COMPAT (output_bfd)
               && strncmp (name, ".compact_rel", 12) == 0)
-       s->_raw_size += mips_elf_hash_table (info)->compact_rel_size;
+       s->size += mips_elf_hash_table (info)->compact_rel_size;
       else if (strncmp (name, ".init", 5) != 0)
        {
          /* It's not one of our sections, so don't allocate space.  */
@@ -6017,8 +6080,8 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
        }
 
       /* Allocate memory for the section contents.  */
-      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
-      if (s->contents == NULL && s->_raw_size != 0)
+      s->contents = bfd_zalloc (dynobj, s->size);
+      if (s->contents == NULL && s->size != 0)
        {
          bfd_set_error (bfd_error_no_memory);
          return FALSE;
@@ -6078,30 +6141,6 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
            return FALSE;
        }
 
-      if (SGI_COMPAT (output_bfd))
-       {
-         if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICTNO, 0))
-           return FALSE;
-       }
-
-      if (SGI_COMPAT (output_bfd))
-       {
-         if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLISTNO, 0))
-           return FALSE;
-       }
-
-      if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
-       {
-         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICT, 0))
-           return FALSE;
-
-         s = bfd_get_section_by_name (dynobj, ".liblist");
-         BFD_ASSERT (s != NULL);
-
-         if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLIST, 0))
-           return FALSE;
-       }
-
       if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0))
        return FALSE;
 
@@ -6156,22 +6195,17 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
 /* Relocate a MIPS ELF section.  */
 
 bfd_boolean
-_bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
-                               contents, relocs, local_syms, local_sections)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     asection *input_section;
-     bfd_byte *contents;
-     Elf_Internal_Rela *relocs;
-     Elf_Internal_Sym *local_syms;
-     asection **local_sections;
+_bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
+                               bfd *input_bfd, asection *input_section,
+                               bfd_byte *contents, Elf_Internal_Rela *relocs,
+                               Elf_Internal_Sym *local_syms,
+                               asection **local_sections)
 {
   Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *relend;
   bfd_vma addend = 0;
   bfd_boolean use_saved_addend_p = FALSE;
-  struct elf_backend_data *bed;
+  const struct elf_backend_data *bed;
 
   bed = get_elf_backend_data (output_bfd);
   relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
@@ -6185,7 +6219,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          REL relocation.  */
       bfd_boolean rela_relocation_p = TRUE;
       unsigned int r_type = ELF_R_TYPE (output_bfd, rel->r_info);
-      const char * msg = (const char *) NULL;
+      const char *msg;
 
       /* Find the relocation howto for this relocation.  */
       if (r_type == R_MIPS_64 && ! NEWABI_P (input_bfd))
@@ -6227,20 +6261,25 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            rel_hdr = elf_section_data (input_section)->rel_hdr2;
          if (rel_hdr->sh_entsize == MIPS_ELF_REL_SIZE (input_bfd))
            {
+             bfd_byte *location = contents + rel->r_offset;
+
              /* Note that this is a REL relocation.  */
              rela_relocation_p = FALSE;
 
              /* Get the addend, which is stored in the input file.  */
+             _bfd_mips16_elf_reloc_unshuffle (input_bfd, r_type, FALSE,
+                                              location);
              addend = mips_elf_obtain_contents (howto, rel, input_bfd,
                                                 contents);
+             _bfd_mips16_elf_reloc_shuffle(input_bfd, r_type, FALSE,
+                                           location);
+
              addend &= howto->src_mask;
-             addend <<= howto->rightshift;
 
              /* For some kinds of relocations, the ADDEND is a
                 combination of the addend stored in two different
                 relocations.   */
-             if (r_type == R_MIPS_HI16
-                 || r_type == R_MIPS_GNU_REL_HI16
+             if (r_type == R_MIPS_HI16 || r_type == R_MIPS16_HI16
                  || (r_type == R_MIPS_GOT16
                      && mips_elf_local_relocation_p (input_bfd, rel,
                                                      local_sections, FALSE)))
@@ -6248,7 +6287,13 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  bfd_vma l;
                  const Elf_Internal_Rela *lo16_relocation;
                  reloc_howto_type *lo16_howto;
-                 unsigned int lo;
+                 bfd_byte *lo16_location;
+                 int lo16_type;
+
+                 if (r_type == R_MIPS16_HI16)
+                   lo16_type = R_MIPS16_LO16;
+                 else
+                   lo16_type = R_MIPS_LO16;
 
                  /* The combined value is the sum of the HI16 addend,
                     left-shifted by sixteen bits, and the LO16
@@ -6256,20 +6301,33 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                     a `lui' of the HI16 value, and then an `addiu' of
                     the LO16 value.)
 
-                    Scan ahead to find a matching LO16 relocation.  */
-                 if (r_type == R_MIPS_GNU_REL_HI16)
-                   lo = R_MIPS_GNU_REL_LO16;
-                 else
-                   lo = R_MIPS_LO16;
-                 lo16_relocation = mips_elf_next_relocation (input_bfd, lo,
+                    Scan ahead to find a matching LO16 relocation.
+
+                    According to the MIPS ELF ABI, the R_MIPS_LO16
+                    relocation must be immediately following.
+                    However, for the IRIX6 ABI, the next relocation
+                    may be a composed relocation consisting of
+                    several relocations for the same address.  In
+                    that case, the R_MIPS_LO16 relocation may occur
+                    as one of these.  We permit a similar extension
+                    in general, as that is useful for GCC.  */
+                 lo16_relocation = mips_elf_next_relocation (input_bfd,
+                                                             lo16_type,
                                                              rel, relend);
                  if (lo16_relocation == NULL)
                    return FALSE;
 
+                 lo16_location = contents + lo16_relocation->r_offset;
+
                  /* Obtain the addend kept there.  */
-                 lo16_howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, lo, FALSE);
+                 lo16_howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd,
+                                                       lo16_type, FALSE);
+                 _bfd_mips16_elf_reloc_unshuffle (input_bfd, lo16_type, FALSE,
+                                                  lo16_location);
                  l = mips_elf_obtain_contents (lo16_howto, lo16_relocation,
                                                input_bfd, contents);
+                 _bfd_mips16_elf_reloc_shuffle (input_bfd, lo16_type, FALSE,
+                                                lo16_location);
                  l &= lo16_howto->src_mask;
                  l <<= lo16_howto->rightshift;
                  l = _bfd_mips_elf_sign_extend (l, 16);
@@ -6278,26 +6336,9 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
                  /* Compute the combined addend.  */
                  addend += l;
-
-                 /* If PC-relative, subtract the difference between the
-                    address of the LO part of the reloc and the address of
-                    the HI part.  The relocation is relative to the LO
-                    part, but mips_elf_calculate_relocation() doesn't
-                    know its address or the difference from the HI part, so
-                    we subtract that difference here.  See also the
-                    comment in mips_elf_calculate_relocation().  */
-                 if (r_type == R_MIPS_GNU_REL_HI16)
-                   addend -= (lo16_relocation->r_offset - rel->r_offset);
-               }
-             else if (r_type == R_MIPS16_GPREL)
-               {
-                 /* The addend is scrambled in the object file.  See
-                    mips_elf_perform_relocation for details on the
-                    format.  */
-                 addend = (((addend & 0x1f0000) >> 5)
-                           | ((addend & 0x7e00000) >> 16)
-                           | (addend & 0x1f));
                }
+             else
+               addend <<= howto->rightshift;
            }
          else
            addend = rel->r_addend;
@@ -6337,33 +6378,24 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            /* Adjust the addend appropriately.  */
            addend += local_sections[r_symndx]->output_offset;
 
-         if (howto->partial_inplace)
+         if (rela_relocation_p)
+           /* If this is a RELA relocation, just update the addend.  */
+           rel->r_addend = addend;
+         else
            {
-             /* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16,
-                then we only want to write out the high-order 16 bits.
-                The subsequent R_MIPS_LO16 will handle the low-order bits.
-              */
-             if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16
-                 || r_type == R_MIPS_GNU_REL_HI16)
+             if (r_type == R_MIPS_HI16
+                 || r_type == R_MIPS_GOT16)
                addend = mips_elf_high (addend);
              else if (r_type == R_MIPS_HIGHER)
                addend = mips_elf_higher (addend);
              else if (r_type == R_MIPS_HIGHEST)
                addend = mips_elf_highest (addend);
-           }
+             else
+               addend >>= howto->rightshift;
 
-         if (rela_relocation_p)
-           /* If this is a RELA relocation, just update the addend.
-              We have to cast away constness for REL.  */
-           rel->r_addend = addend;
-         else
-           {
-             /* Otherwise, we have to write the value back out.  Note
-                that we use the source mask, rather than the
-                destination mask because the place to which we are
-                writing will be source of the addend in the final
-                link.  */
-             addend >>= howto->rightshift;
+             /* We use the source mask, rather than the destination
+                mask because the place to which we are writing will be
+                source of the addend in the final link.  */
              addend &= howto->src_mask;
 
              if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd))
@@ -6427,8 +6459,6 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
       else
        use_saved_addend_p = FALSE;
 
-      addend >>= howto->rightshift;
-
       /* Figure out what value we are supposed to relocate.  */
       switch (mips_elf_calculate_relocation (output_bfd, input_bfd,
                                             input_section, info, rel,
@@ -6463,7 +6493,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            {
              BFD_ASSERT (name != NULL);
              if (! ((*info->callbacks->reloc_overflow)
-                    (info, name, howto->name, (bfd_vma) 0,
+                    (info, NULL, name, howto->name, (bfd_vma) 0,
                      input_bfd, input_section, rel->r_offset)))
                return FALSE;
            }
@@ -6544,10 +6574,8 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
    adjust it appropriately now.  */
 
 static void
-mips_elf_irix6_finish_dynamic_symbol (abfd, name, sym)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     const char *name;
-     Elf_Internal_Sym *sym;
+mips_elf_irix6_finish_dynamic_symbol (bfd *abfd ATTRIBUTE_UNUSED,
+                                     const char *name, Elf_Internal_Sym *sym)
 {
   /* The linker script takes care of providing names and values for
      these, but we must place them into the right sections.  */
@@ -6596,22 +6624,19 @@ mips_elf_irix6_finish_dynamic_symbol (abfd, name, sym)
    dynamic sections here.  */
 
 bfd_boolean
-_bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
-     Elf_Internal_Sym *sym;
+_bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
+                                    struct bfd_link_info *info,
+                                    struct elf_link_hash_entry *h,
+                                    Elf_Internal_Sym *sym)
 {
   bfd *dynobj;
-  bfd_vma gval;
   asection *sgot;
   struct mips_got_info *g, *gg;
   const char *name;
 
   dynobj = elf_hash_table (info)->dynobj;
-  gval = sym->st_value;
 
-  if (h->plt.offset != (bfd_vma) -1)
+  if (h->plt.offset != MINUS_ONE)
     {
       asection *s;
       bfd_byte stub[MIPS_FUNCTION_STUB_SIZE];
@@ -6634,7 +6659,7 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       bfd_put_32 (output_bfd, STUB_JALR, stub + 8);
       bfd_put_32 (output_bfd, STUB_LI16 (output_bfd) + h->dynindx, stub + 12);
 
-      BFD_ASSERT (h->plt.offset <= s->_raw_size);
+      BFD_ASSERT (h->plt.offset <= s->size);
       memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
 
       /* Mark the symbol as undefined.  plt.offset != -1 occurs
@@ -6644,12 +6669,12 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       /* The run-time linker uses the st_value field of the symbol
         to reset the global offset table entry for this external
         to its stub address when unlinking a shared object.  */
-      gval = s->output_section->vma + s->output_offset + h->plt.offset;
-      sym->st_value = gval;
+      sym->st_value = (s->output_section->vma + s->output_offset
+                      + h->plt.offset);
     }
 
   BFD_ASSERT (h->dynindx != -1
-             || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0);
+             || h->forced_local);
 
   sgot = mips_elf_got_section (dynobj, FALSE);
   BFD_ASSERT (sgot != NULL);
@@ -6673,10 +6698,8 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
   if (g->next && h->dynindx != -1)
     {
       struct mips_got_entry e, *p;
+      bfd_vma entry;
       bfd_vma offset;
-      bfd_vma value;
-      Elf_Internal_Rela rel[3];
-      bfd_vma addend = 0;
 
       gg = g;
 
@@ -6684,18 +6707,6 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       e.symndx = -1;
       e.d.h = (struct mips_elf_link_hash_entry *)h;
 
-      if (info->shared
-         || h->root.type == bfd_link_hash_undefined
-         || h->root.type == bfd_link_hash_undefweak)
-       value = 0;
-      else if (sym->st_value)
-       value = sym->st_value;
-      else
-       value = h->root.u.def.value;
-
-      memset (rel, 0, sizeof (rel));
-      rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_REL32);
-
       for (g = g->next; g->next != gg; g = g->next)
        {
          if (g->got_entries
@@ -6703,22 +6714,35 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
                                                           &e)))
            {
              offset = p->gotidx;
-             rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
-
-             MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
-
-             if ((info->shared
-                  || (elf_hash_table (info)->dynamic_sections_created
-                      && p->d.h != NULL
-                      && ((p->d.h->root.elf_link_hash_flags
-                           & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
-                      && ((p->d.h->root.elf_link_hash_flags
-                           & ELF_LINK_HASH_DEF_REGULAR) == 0)))
-                 && ! (mips_elf_create_dynamic_relocation
-                       (output_bfd, info, rel,
-                        e.d.h, NULL, value, &addend, sgot)))
-               return FALSE;
-             BFD_ASSERT (addend == 0);
+             if (info->shared
+                 || (elf_hash_table (info)->dynamic_sections_created
+                     && p->d.h != NULL
+                     && p->d.h->root.def_dynamic
+                     && !p->d.h->root.def_regular))
+               {
+                 /* Create an R_MIPS_REL32 relocation for this entry.  Due to
+                    the various compatibility problems, it's easier to mock
+                    up an R_MIPS_32 or R_MIPS_64 relocation and leave
+                    mips_elf_create_dynamic_relocation to calculate the
+                    appropriate addend.  */
+                 Elf_Internal_Rela rel[3];
+
+                 memset (rel, 0, sizeof (rel));
+                 if (ABI_64_P (output_bfd))
+                   rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_64);
+                 else
+                   rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_32);
+                 rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
+
+                 entry = 0;
+                 if (! (mips_elf_create_dynamic_relocation
+                        (output_bfd, info, rel,
+                         e.d.h, NULL, sym->st_value, &entry, sgot)))
+                   return FALSE;
+               }
+             else
+               entry = sym->st_value;
+             MIPS_ELF_PUT_WORD (output_bfd, entry, sgot->contents + offset);
            }
        }
     }
@@ -6780,7 +6804,7 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
          asection *s = bfd_get_section_by_name (dynobj, ".rld_map");
          BFD_ASSERT (s != NULL);
          sym->st_value = s->output_section->vma + s->output_offset;
-         bfd_put_32 (output_bfd, (bfd_vma) 0, s->contents);
+         bfd_put_32 (output_bfd, 0, s->contents);
          if (mips_elf_hash_table (info)->rld_value == 0)
            mips_elf_hash_table (info)->rld_value = sym->st_value;
        }
@@ -6797,9 +6821,8 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
     }
 
   /* If this is a mips16 symbol, force the value to be even.  */
-  if (sym->st_other == STO_MIPS16
-      && (sym->st_value & 1) != 0)
-    --sym->st_value;
+  if (sym->st_other == STO_MIPS16)
+    sym->st_value &= ~1;
 
   return TRUE;
 }
@@ -6807,9 +6830,8 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
 /* Finish up the dynamic sections.  */
 
 bfd_boolean
-_bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
+_bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
+                                      struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *sdyn;
@@ -6840,7 +6862,7 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
       BFD_ASSERT (g != NULL);
 
       for (b = sdyn->contents;
-          b < sdyn->contents + sdyn->_raw_size;
+          b < sdyn->contents + sdyn->size;
           b += MIPS_ELF_DYN_SIZE (dynobj))
        {
          Elf_Internal_Dyn dyn;
@@ -6871,13 +6893,6 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
 
            case DT_PLTGOT:
              name = ".got";
-             goto get_vma;
-           case DT_MIPS_CONFLICT:
-             name = ".conflict";
-             goto get_vma;
-           case DT_MIPS_LIBLIST:
-             name = ".liblist";
-           get_vma:
              s = bfd_get_section_by_name (output_bfd, name);
              BFD_ASSERT (s != NULL);
              dyn.d_un.d_ptr = s->vma;
@@ -6891,27 +6906,6 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
              dyn.d_un.d_val = RHF_NOTPOT; /* XXX */
              break;
 
-           case DT_MIPS_CONFLICTNO:
-             name = ".conflict";
-             elemsize = sizeof (Elf32_Conflict);
-             goto set_elemno;
-
-           case DT_MIPS_LIBLISTNO:
-             name = ".liblist";
-             elemsize = sizeof (Elf32_Lib);
-           set_elemno:
-             s = bfd_get_section_by_name (output_bfd, name);
-             if (s != NULL)
-               {
-                 if (s->_cooked_size != 0)
-                   dyn.d_un.d_val = s->_cooked_size / elemsize;
-                 else
-                   dyn.d_un.d_val = s->_raw_size / elemsize;
-               }
-             else
-               dyn.d_un.d_val = 0;
-             break;
-
            case DT_MIPS_TIME_STAMP:
              time ((time_t *) &dyn.d_un.d_val);
              break;
@@ -6959,10 +6953,7 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
              s = bfd_get_section_by_name (output_bfd, name);
              BFD_ASSERT (s != NULL);
 
-             if (s->_cooked_size != 0)
-               dyn.d_un.d_val = s->_cooked_size / elemsize;
-             else
-               dyn.d_un.d_val = s->_raw_size / elemsize;
+             dyn.d_un.d_val = s->size / elemsize;
              break;
 
            case DT_MIPS_HIPAGENO:
@@ -6979,9 +6970,16 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
              dyn.d_un.d_ptr = s->vma;
              break;
 
-           case DT_MIPS_MSYM:
-             s = (bfd_get_section_by_name (output_bfd, ".msym"));
-             dyn.d_un.d_ptr = s->vma;
+           case DT_RELSZ:
+             /* Reduce DT_RELSZ to account for any relocations we
+                decided not to make.  This is for the n64 irix rld,
+                which doesn't seem to apply any relocations if there
+                are trailing null entries.  */
+             s = mips_elf_rel_dyn_section (dynobj, FALSE);
+             dyn.d_un.d_val = (s->reloc_count
+                               * (ABI_64_P (output_bfd)
+                                  ? sizeof (Elf64_Mips_External_Rel)
+                                  : sizeof (Elf32_External_Rel)));
              break;
 
            default:
@@ -6998,10 +6996,10 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
   /* The first entry of the global offset table will be filled at
      runtime. The second entry will be used by some runtime loaders.
      This isn't the case of IRIX rld.  */
-  if (sgot != NULL && sgot->_raw_size > 0)
+  if (sgot != NULL && sgot->size > 0)
     {
-      MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents);
-      MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000,
+      MIPS_ELF_PUT_WORD (output_bfd, 0, sgot->contents);
+      MIPS_ELF_PUT_WORD (output_bfd, 0x80000000,
                         sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
     }
 
@@ -7022,9 +7020,9 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
        {
          bfd_vma index = g->next->local_gotno + g->next->global_gotno;
 
-         MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents
+         MIPS_ELF_PUT_WORD (output_bfd, 0, sgot->contents
                             + index++ * MIPS_ELF_GOT_SIZE (output_bfd));
-         MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000, sgot->contents
+         MIPS_ELF_PUT_WORD (output_bfd, 0x80000000, sgot->contents
                             + index++ * MIPS_ELF_GOT_SIZE (output_bfd));
 
          if (! info->shared)
@@ -7072,8 +7070,8 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
              {
                file_ptr dummy_offset;
 
-               BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE);
-               dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE;
+               BFD_ASSERT (s->size >= MIPS_FUNCTION_STUB_SIZE);
+               dummy_offset = s->size - MIPS_FUNCTION_STUB_SIZE;
                memset (s->contents + dummy_offset, 0,
                        MIPS_FUNCTION_STUB_SIZE);
              }
@@ -7085,17 +7083,15 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
     s = mips_elf_rel_dyn_section (dynobj, FALSE);
 
     if (s != NULL
-       && s->_raw_size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd))
+       && s->size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd))
       {
        reldyn_sorting_bfd = output_bfd;
 
        if (ABI_64_P (output_bfd))
-         qsort ((Elf64_External_Rel *) s->contents + 1,
-                (size_t) s->reloc_count - 1,
+         qsort ((Elf64_External_Rel *) s->contents + 1, s->reloc_count - 1,
                 sizeof (Elf64_Mips_External_Rel), sort_dynamic_relocs_64);
        else
-         qsort ((Elf32_External_Rel *) s->contents + 1,
-                (size_t) s->reloc_count - 1,
+         qsort ((Elf32_External_Rel *) s->contents + 1, s->reloc_count - 1,
                 sizeof (Elf32_External_Rel), sort_dynamic_relocs);
       }
   }
@@ -7107,8 +7103,7 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
 /* Set ABFD's EF_MIPS_ARCH and EF_MIPS_MACH flags.  */
 
 static void
-mips_set_isa_flags (abfd)
-     bfd *abfd;
+mips_set_isa_flags (bfd *abfd)
 {
   flagword val;
 
@@ -7162,6 +7157,10 @@ mips_set_isa_flags (abfd)
       val = E_MIPS_ARCH_4 | E_MIPS_MACH_5500;
       break;
 
+    case bfd_mach_mips9000:
+      val = E_MIPS_ARCH_4 | E_MIPS_MACH_9000;
+      break;
+
     case bfd_mach_mips5000:
     case bfd_mach_mips7000:
     case bfd_mach_mips8000:
@@ -7189,6 +7188,10 @@ mips_set_isa_flags (abfd)
     case bfd_mach_mipsisa32r2:
       val = E_MIPS_ARCH_32R2;
       break;
+
+    case bfd_mach_mipsisa64r2:
+      val = E_MIPS_ARCH_64R2;
+      break;
     }
   elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
   elf_elfheader (abfd)->e_flags |= val;
@@ -7201,9 +7204,8 @@ mips_set_isa_flags (abfd)
    number.  This is used by both the 32-bit and the 64-bit ABI.  */
 
 void
-_bfd_mips_elf_final_write_processing (abfd, linker)
-     bfd *abfd;
-     bfd_boolean linker ATTRIBUTE_UNUSED;
+_bfd_mips_elf_final_write_processing (bfd *abfd,
+                                     bfd_boolean linker ATTRIBUTE_UNUSED)
 {
   unsigned int i;
   Elf_Internal_Shdr **hdrpp;
@@ -7289,8 +7291,7 @@ _bfd_mips_elf_final_write_processing (abfd, linker)
    segments.  */
 
 int
-_bfd_mips_elf_additional_program_headers (abfd)
-     bfd *abfd;
+_bfd_mips_elf_additional_program_headers (bfd *abfd)
 {
   asection *s;
   int ret = 0;
@@ -7318,8 +7319,8 @@ _bfd_mips_elf_additional_program_headers (abfd)
 /* Modify the segment map for an IRIX5 executable.  */
 
 bfd_boolean
-_bfd_mips_elf_modify_segment_map (abfd)
-     bfd *abfd;
+_bfd_mips_elf_modify_segment_map (bfd *abfd,
+                                 struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   asection *s;
   struct elf_segment_map *m, **pm;
@@ -7336,7 +7337,7 @@ _bfd_mips_elf_modify_segment_map (abfd)
       if (m == NULL)
        {
          amt = sizeof *m;
-         m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+         m = bfd_zalloc (abfd, amt);
          if (m == NULL)
            return FALSE;
 
@@ -7358,7 +7359,7 @@ _bfd_mips_elf_modify_segment_map (abfd)
 
   /* For IRIX 6, we don't have .mdebug sections, nor does anything but
      .dynamic end up in PT_DYNAMIC.  However, we do have to insert a
-     PT_OPTIONS segment immediately following the program header
+     PT_MIPS_OPTIONS segment immediately following the program header
      table.  */
   if (NEWABI_P (abfd)
       /* On non-IRIX6 new abi, we'll have already created a segment
@@ -7375,15 +7376,11 @@ _bfd_mips_elf_modify_segment_map (abfd)
        {
          struct elf_segment_map *options_segment;
 
-         /* Usually, there's a program header table.  But, sometimes
-            there's not (like when running the `ld' testsuite).  So,
-            if there's no program header table, we just put the
-            options segment at the end.  */
-         for (pm = &elf_tdata (abfd)->segment_map;
-              *pm != NULL;
-              pm = &(*pm)->next)
-           if ((*pm)->p_type == PT_PHDR)
-             break;
+         pm = &elf_tdata (abfd)->segment_map;
+         while (*pm != NULL
+                && ((*pm)->p_type == PT_PHDR
+                    || (*pm)->p_type == PT_INTERP))
+           pm = &(*pm)->next;
 
          amt = sizeof (struct elf_segment_map);
          options_segment = bfd_zalloc (abfd, amt);
@@ -7412,7 +7409,7 @@ _bfd_mips_elf_modify_segment_map (abfd)
              if (m == NULL)
                {
                  amt = sizeof *m;
-                 m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+                 m = bfd_zalloc (abfd, amt);
                  if (m == NULL)
                    return FALSE;
 
@@ -7474,7 +7471,7 @@ _bfd_mips_elf_modify_segment_map (abfd)
          unsigned int i, c;
          struct elf_segment_map *n;
 
-         low = 0xffffffff;
+         low = ~(bfd_vma) 0;
          high = 0;
          for (i = 0; i < sizeof sec_names / sizeof sec_names[0]; i++)
            {
@@ -7485,9 +7482,7 @@ _bfd_mips_elf_modify_segment_map (abfd)
 
                  if (low > s->vma)
                    low = s->vma;
-                 sz = s->_cooked_size;
-                 if (sz == 0)
-                   sz = s->_raw_size;
+                 sz = s->size;
                  if (high < s->vma + sz)
                    high = s->vma + sz;
                }
@@ -7497,13 +7492,11 @@ _bfd_mips_elf_modify_segment_map (abfd)
          for (s = abfd->sections; s != NULL; s = s->next)
            if ((s->flags & SEC_LOAD) != 0
                && s->vma >= low
-               && ((s->vma
-                    + (s->_cooked_size !=
-                       0 ? s->_cooked_size : s->_raw_size)) <= high))
+               && s->vma + s->size <= high)
              ++c;
 
          amt = sizeof *n + (bfd_size_type) (c - 1) * sizeof (asection *);
-         n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+         n = bfd_zalloc (abfd, amt);
          if (n == NULL)
            return FALSE;
          *n = *m;
@@ -7514,9 +7507,7 @@ _bfd_mips_elf_modify_segment_map (abfd)
            {
              if ((s->flags & SEC_LOAD) != 0
                  && s->vma >= low
-                 && ((s->vma
-                      + (s->_cooked_size != 0 ?
-                         s->_cooked_size : s->_raw_size)) <= high))
+                 && s->vma + s->size <= high)
                {
                  n->sections[i] = s;
                  ++i;
@@ -7534,12 +7525,11 @@ _bfd_mips_elf_modify_segment_map (abfd)
    relocation.  */
 
 asection *
-_bfd_mips_elf_gc_mark_hook (sec, info, rel, h, sym)
-     asection *sec;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     Elf_Internal_Rela *rel;
-     struct elf_link_hash_entry *h;
-     Elf_Internal_Sym *sym;
+_bfd_mips_elf_gc_mark_hook (asection *sec,
+                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                           Elf_Internal_Rela *rel,
+                           struct elf_link_hash_entry *h,
+                           Elf_Internal_Sym *sym)
 {
   /* ??? Do mips16 stub sections need to be handled special?  */
 
@@ -7575,11 +7565,10 @@ _bfd_mips_elf_gc_mark_hook (sec, info, rel, h, sym)
 /* Update the got entry reference counts for the section being removed.  */
 
 bfd_boolean
-_bfd_mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     asection *sec ATTRIBUTE_UNUSED;
-     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
+_bfd_mips_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
+                            struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                            asection *sec ATTRIBUTE_UNUSED,
+                            const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
 {
 #if 0
   Elf_Internal_Shdr *symtab_hdr;
@@ -7625,9 +7614,9 @@ _bfd_mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
    _bfd_elf_link_hash_copy_indirect copy the flags for us.  */
 
 void
-_bfd_mips_elf_copy_indirect_symbol (bed, dir, ind)
-     struct elf_backend_data *bed;
-     struct elf_link_hash_entry *dir, *ind;
+_bfd_mips_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
+                                   struct elf_link_hash_entry *dir,
+                                   struct elf_link_hash_entry *ind)
 {
   struct mips_elf_link_hash_entry *dirmips, *indmips;
 
@@ -7646,10 +7635,9 @@ _bfd_mips_elf_copy_indirect_symbol (bed, dir, ind)
 }
 
 void
-_bfd_mips_elf_hide_symbol (info, entry, force_local)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *entry;
-     bfd_boolean force_local;
+_bfd_mips_elf_hide_symbol (struct bfd_link_info *info,
+                          struct elf_link_hash_entry *entry,
+                          bfd_boolean force_local)
 {
   bfd *dynobj;
   asection *got;
@@ -7721,10 +7709,8 @@ _bfd_mips_elf_hide_symbol (info, entry, force_local)
 #define PDR_SIZE 32
 
 bfd_boolean
-_bfd_mips_elf_discard_info (abfd, cookie, info)
-     bfd *abfd;
-     struct elf_reloc_cookie *cookie;
-     struct bfd_link_info *info;
+_bfd_mips_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
+                           struct bfd_link_info *info)
 {
   asection *o;
   bfd_boolean ret = FALSE;
@@ -7734,20 +7720,19 @@ _bfd_mips_elf_discard_info (abfd, cookie, info)
   o = bfd_get_section_by_name (abfd, ".pdr");
   if (! o)
     return FALSE;
-  if (o->_raw_size == 0)
+  if (o->size == 0)
     return FALSE;
-  if (o->_raw_size % PDR_SIZE != 0)
+  if (o->size % PDR_SIZE != 0)
     return FALSE;
   if (o->output_section != NULL
       && bfd_is_abs_section (o->output_section))
     return FALSE;
 
-  tdata = bfd_zmalloc (o->_raw_size / PDR_SIZE);
+  tdata = bfd_zmalloc (o->size / PDR_SIZE);
   if (! tdata)
     return FALSE;
 
-  cookie->rels = _bfd_elf_link_read_relocs (abfd, o, (PTR) NULL,
-                                           (Elf_Internal_Rela *) NULL,
+  cookie->rels = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
                                            info->keep_memory);
   if (!cookie->rels)
     {
@@ -7758,9 +7743,9 @@ _bfd_mips_elf_discard_info (abfd, cookie, info)
   cookie->rel = cookie->rels;
   cookie->relend = cookie->rels + o->reloc_count;
 
-  for (i = 0, skip = 0; i < o->_raw_size / PDR_SIZE; i ++)
+  for (i = 0, skip = 0; i < o->size / PDR_SIZE; i ++)
     {
-      if (MNAME(abfd,_bfd_elf,reloc_symbol_deleted_p) (i * PDR_SIZE, cookie))
+      if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
        {
          tdata[i] = 1;
          skip ++;
@@ -7770,7 +7755,7 @@ _bfd_mips_elf_discard_info (abfd, cookie, info)
   if (skip != 0)
     {
       mips_elf_section_data (o)->u.tdata = tdata;
-      o->_cooked_size = o->_raw_size - skip * PDR_SIZE;
+      o->size -= skip * PDR_SIZE;
       ret = TRUE;
     }
   else
@@ -7783,8 +7768,7 @@ _bfd_mips_elf_discard_info (abfd, cookie, info)
 }
 
 bfd_boolean
-_bfd_mips_elf_ignore_discarded_relocs (sec)
-     asection *sec;
+_bfd_mips_elf_ignore_discarded_relocs (asection *sec)
 {
   if (strcmp (sec->name, ".pdr") == 0)
     return TRUE;
@@ -7792,10 +7776,8 @@ _bfd_mips_elf_ignore_discarded_relocs (sec)
 }
 
 bfd_boolean
-_bfd_mips_elf_write_section (output_bfd, sec, contents)
-     bfd *output_bfd;
-     asection *sec;
-     bfd_byte *contents;
+_bfd_mips_elf_write_section (bfd *output_bfd, asection *sec,
+                            bfd_byte *contents)
 {
   bfd_byte *to, *from, *end;
   int i;
@@ -7807,7 +7789,7 @@ _bfd_mips_elf_write_section (output_bfd, sec, contents)
     return FALSE;
 
   to = contents;
-  end = contents + sec->_raw_size;
+  end = contents + sec->size;
   for (from = contents, i = 0;
        from < end;
        from += PDR_SIZE, i++)
@@ -7819,8 +7801,7 @@ _bfd_mips_elf_write_section (output_bfd, sec, contents)
       to += PDR_SIZE;
     }
   bfd_set_section_contents (output_bfd, sec->output_section, contents,
-                           (file_ptr) sec->output_offset,
-                           sec->_cooked_size);
+                           sec->output_offset, sec->size);
   return TRUE;
 }
 \f
@@ -7834,15 +7815,11 @@ struct mips_elf_find_line
 };
 
 bfd_boolean
-_bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
-                                functionname_ptr, line_ptr)
-     bfd *abfd;
-     asection *section;
-     asymbol **symbols;
-     bfd_vma offset;
-     const char **filename_ptr;
-     const char **functionname_ptr;
-     unsigned int *line_ptr;
+_bfd_mips_elf_find_nearest_line (bfd *abfd, asection *section,
+                                asymbol **symbols, bfd_vma offset,
+                                const char **filename_ptr,
+                                const char **functionname_ptr,
+                                unsigned int *line_ptr)
 {
   asection *msec;
 
@@ -7853,8 +7830,7 @@ _bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
 
   if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr,
-                                    (unsigned) (ABI_64_P (abfd) ? 8 : 0),
+                                    line_ptr, ABI_64_P (abfd) ? 8 : 0,
                                     &elf_tdata (abfd)->dwarf2_find_line_info))
     return TRUE;
 
@@ -7882,7 +7858,7 @@ _bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
          struct fdr *fdr_ptr;
          bfd_size_type amt = sizeof (struct mips_elf_find_line);
 
-         fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt);
+         fi = bfd_zalloc (abfd, amt);
          if (fi == NULL)
            {
              msec->flags = origflags;
@@ -7897,7 +7873,7 @@ _bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
 
          /* Swap in the FDR information.  */
          amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
-         fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt);
+         fi->d.fdr = bfd_alloc (abfd, amt);
          if (fi->d.fdr == NULL)
            {
              msec->flags = origflags;
@@ -7909,7 +7885,7 @@ _bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
          fraw_end = (fraw_src
                      + fi->d.symbolic_header.ifdMax * external_fdr_size);
          for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
-           (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
+           (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr);
 
          elf_tdata (abfd)->find_line_info = fi;
 
@@ -7944,12 +7920,9 @@ _bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
    GP value in the section_processing routine.  */
 
 bfd_boolean
-_bfd_mips_elf_set_section_contents (abfd, section, location, offset, count)
-     bfd *abfd;
-     sec_ptr section;
-     PTR location;
-     file_ptr offset;
-     bfd_size_type count;
+_bfd_mips_elf_set_section_contents (bfd *abfd, sec_ptr section,
+                                   const void *location,
+                                   file_ptr offset, bfd_size_type count)
 {
   if (strcmp (section->name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0)
     {
@@ -7958,26 +7931,20 @@ _bfd_mips_elf_set_section_contents (abfd, section, location, offset, count)
       if (elf_section_data (section) == NULL)
        {
          bfd_size_type amt = sizeof (struct bfd_elf_section_data);
-         section->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
+         section->used_by_bfd = bfd_zalloc (abfd, amt);
          if (elf_section_data (section) == NULL)
            return FALSE;
        }
       c = mips_elf_section_data (section)->u.tdata;
       if (c == NULL)
        {
-         bfd_size_type size;
-
-         if (section->_cooked_size != 0)
-           size = section->_cooked_size;
-         else
-           size = section->_raw_size;
-         c = (bfd_byte *) bfd_zalloc (abfd, size);
+         c = bfd_zalloc (abfd, section->size);
          if (c == NULL)
            return FALSE;
          mips_elf_section_data (section)->u.tdata = c;
        }
 
-      memcpy (c + offset, location, (size_t) count);
+      memcpy (c + offset, location, count);
     }
 
   return _bfd_elf_set_section_contents (abfd, section, location, offset,
@@ -7988,18 +7955,18 @@ _bfd_mips_elf_set_section_contents (abfd, section, location, offset, count)
    MIPS relocations need to be handled specially.  Sigh.  */
 
 bfd_byte *
-_bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
-                                             data, relocatable, symbols)
-     bfd *abfd;
-     struct bfd_link_info *link_info;
-     struct bfd_link_order *link_order;
-     bfd_byte *data;
-     bfd_boolean relocatable;
-     asymbol **symbols;
+_bfd_elf_mips_get_relocated_section_contents
+  (bfd *abfd,
+   struct bfd_link_info *link_info,
+   struct bfd_link_order *link_order,
+   bfd_byte *data,
+   bfd_boolean relocatable,
+   asymbol **symbols)
 {
   /* Get enough memory to hold the stuff */
   bfd *input_bfd = link_order->u.indirect.section->owner;
   asection *input_section = link_order->u.indirect.section;
+  bfd_size_type sz;
 
   long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
   arelent **reloc_vector = NULL;
@@ -8008,22 +7975,15 @@ _bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
   if (reloc_size < 0)
     goto error_return;
 
-  reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
+  reloc_vector = bfd_malloc (reloc_size);
   if (reloc_vector == NULL && reloc_size != 0)
     goto error_return;
 
   /* read in the section */
-  if (!bfd_get_section_contents (input_bfd,
-                                input_section,
-                                (PTR) data,
-                                (file_ptr) 0,
-                                input_section->_raw_size))
+  sz = input_section->rawsize ? input_section->rawsize : input_section->size;
+  if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
     goto error_return;
 
-  /* We're not relaxing the section, so just copy the size info */
-  input_section->_cooked_size = input_section->_raw_size;
-  input_section->reloc_done = TRUE;
-
   reloc_count = bfd_canonicalize_reloc (input_bfd,
                                        input_section,
                                        reloc_vector,
@@ -8079,10 +8039,9 @@ _bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
          gp_found = 0;
       }
       /* end mips */
-      for (parent = reloc_vector; *parent != (arelent *) NULL;
-          parent++)
+      for (parent = reloc_vector; *parent != NULL; parent++)
        {
-         char *error_message = (char *) NULL;
+         char *error_message = NULL;
          bfd_reloc_status_type r;
 
          /* Specific to MIPS: Deal with relocation types that require
@@ -8103,16 +8062,13 @@ _bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
              /* bypass special_function call */
              r = _bfd_mips_elf_gprel16_with_gp (input_bfd, sym, *parent,
                                                 input_section, relocatable,
-                                                (PTR) data, gp);
+                                                data, gp);
              goto skip_bfd_perform_relocation;
            }
          /* end mips specific stuff */
 
-         r = bfd_perform_relocation (input_bfd,
-                                     *parent,
-                                     (PTR) data,
-                                     input_section,
-                                     relocatable ? abfd : (bfd *) NULL,
+         r = bfd_perform_relocation (input_bfd, *parent, data, input_section,
+                                     relocatable ? abfd : NULL,
                                      &error_message);
        skip_bfd_perform_relocation:
 
@@ -8137,7 +8093,7 @@ _bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
                    goto error_return;
                  break;
                case bfd_reloc_dangerous:
-                 BFD_ASSERT (error_message != (char *) NULL);
+                 BFD_ASSERT (error_message != NULL);
                  if (!((*link_info->callbacks->reloc_dangerous)
                        (link_info, error_message, input_bfd, input_section,
                         (*parent)->address)))
@@ -8145,7 +8101,8 @@ _bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
                  break;
                case bfd_reloc_overflow:
                  if (!((*link_info->callbacks->reloc_overflow)
-                       (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
+                       (link_info, NULL,
+                        bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
                         (*parent)->howto->name, (*parent)->addend,
                         input_bfd, input_section, (*parent)->address)))
                    goto error_return;
@@ -8172,14 +8129,13 @@ error_return:
 /* Create a MIPS ELF linker hash table.  */
 
 struct bfd_link_hash_table *
-_bfd_mips_elf_link_hash_table_create (abfd)
-     bfd *abfd;
+_bfd_mips_elf_link_hash_table_create (bfd *abfd)
 {
   struct mips_elf_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct mips_elf_link_hash_table);
 
-  ret = (struct mips_elf_link_hash_table *) bfd_malloc (amt);
-  if (ret == (struct mips_elf_link_hash_table *) NULL)
+  ret = bfd_malloc (amt);
+  if (ret == NULL)
     return NULL;
 
   if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
@@ -8208,9 +8164,7 @@ _bfd_mips_elf_link_hash_table_create (abfd)
    sections together, not write them all out sequentially.  */
 
 bfd_boolean
-_bfd_mips_elf_final_link (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 {
   asection **secpp;
   asection *o;
@@ -8219,10 +8173,10 @@ _bfd_mips_elf_final_link (abfd, info)
   asection *rtproc_sec;
   Elf32_RegInfo reginfo;
   struct ecoff_debug_info debug;
-  const struct ecoff_debug_swap *swap
-    = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct ecoff_debug_swap *swap = bed->elf_backend_ecoff_debug_swap;
   HDRR *symhdr = &debug.symbolic_header;
-  PTR mdebug_handle = NULL;
+  void *mdebug_handle = NULL;
   asection *s;
   EXTR esym;
   unsigned int i;
@@ -8248,6 +8202,7 @@ _bfd_mips_elf_final_link (abfd, info)
       bfd *dynobj;
       asection *got;
       struct mips_got_info *g;
+      bfd_size_type dynsecsymcount;
 
       /* When we resort, we must tell mips_elf_sort_hash_table what
         the lowest index it may use is.  That's the number of section
@@ -8255,9 +8210,20 @@ _bfd_mips_elf_final_link (abfd, info)
         adds these symbols when building a shared object.  Note that
         we count the sections after (possibly) removing the .options
         section above.  */
-      if (! mips_elf_sort_hash_table (info, (info->shared
-                                            ? bfd_count_sections (abfd) + 1
-                                            : 1)))
+
+      dynsecsymcount = 0;
+      if (info->shared)
+       {
+         asection * p;
+
+         for (p = abfd->sections; p ; p = p->next)
+           if ((p->flags & SEC_EXCLUDE) == 0
+               && (p->flags & SEC_ALLOC) != 0
+               && !(*bed->elf_backend_omit_section_dynsym) (abfd, info, p))
+             ++ dynsecsymcount;
+       }
+      
+      if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
        return FALSE;
 
       /* Make sure we didn't grow the global .got region.  */
@@ -8318,8 +8284,7 @@ _bfd_mips_elf_final_link (abfd, info)
       struct bfd_link_hash_entry *h;
 
       h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
-      if (h != (struct bfd_link_hash_entry *) NULL
-         && h->type == bfd_link_hash_defined)
+      if (h != NULL && h->type == bfd_link_hash_defined)
        elf_gp (abfd) = (h->u.def.value
                         + h->u.def.section->output_section->vma
                         + h->u.def.section->output_offset);
@@ -8328,7 +8293,7 @@ _bfd_mips_elf_final_link (abfd, info)
          bfd_vma lo = MINUS_ONE;
 
          /* Find the GP-relative section with the lowest offset.  */
-         for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+         for (o = abfd->sections; o != NULL; o = o->next)
            if (o->vma < lo
                && (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
              lo = o->vma;
@@ -8350,7 +8315,7 @@ _bfd_mips_elf_final_link (abfd, info)
   mdebug_sec = NULL;
   gptab_data_sec = NULL;
   gptab_bss_sec = NULL;
-  for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+  for (o = abfd->sections; o != NULL; o = o->next)
     {
       if (strcmp (o->name, ".reginfo") == 0)
        {
@@ -8359,9 +8324,7 @@ _bfd_mips_elf_final_link (abfd, info)
          /* We have found the .reginfo section in the output file.
             Look through all the link_orders comprising it and merge
             the information together.  */
-         for (p = o->link_order_head;
-              p != (struct bfd_link_order *) NULL;
-              p = p->next)
+         for (p = o->link_order_head; p != NULL; p = p->next)
            {
              asection *input_section;
              bfd *input_bfd;
@@ -8378,15 +8341,8 @@ _bfd_mips_elf_final_link (abfd, info)
              input_section = p->u.indirect.section;
              input_bfd = input_section->owner;
 
-             /* The linker emulation code has probably clobbered the
-                 size to be zero bytes.  */
-             if (input_section->_raw_size == 0)
-               input_section->_raw_size = sizeof (Elf32_External_RegInfo);
-
              if (! bfd_get_section_contents (input_bfd, input_section,
-                                             (PTR) &ext,
-                                             (file_ptr) 0,
-                                             (bfd_size_type) sizeof ext))
+                                             &ext, 0, sizeof ext))
                return FALSE;
 
              bfd_mips_elf32_swap_reginfo_in (input_bfd, &ext, &sub);
@@ -8407,11 +8363,11 @@ _bfd_mips_elf_final_link (abfd, info)
            }
 
          /* Size has been set in _bfd_mips_elf_always_size_sections.  */
-         BFD_ASSERT(o->_raw_size == sizeof (Elf32_External_RegInfo));
+         BFD_ASSERT(o->size == sizeof (Elf32_External_RegInfo));
 
          /* Skip this section later on (I don't think this currently
             matters, but someday it might).  */
-         o->link_order_head = (struct bfd_link_order *) NULL;
+         o->link_order_head = NULL;
 
          reginfo_sec = o;
        }
@@ -8455,7 +8411,7 @@ _bfd_mips_elf_final_link (abfd, info)
          debug.external_ext = debug.external_ext_end = NULL;
 
          mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
-         if (mdebug_handle == (PTR) NULL)
+         if (mdebug_handle == NULL)
            return FALSE;
 
          esym.jmptbl = 0;
@@ -8475,7 +8431,7 @@ _bfd_mips_elf_final_link (abfd, info)
              if (s != NULL)
                {
                  esym.asym.value = s->vma;
-                 last = s->vma + s->_raw_size;
+                 last = s->vma + s->size;
                }
              else
                esym.asym.value = last;
@@ -8484,9 +8440,7 @@ _bfd_mips_elf_final_link (abfd, info)
                return FALSE;
            }
 
-         for (p = o->link_order_head;
-              p != (struct bfd_link_order *) NULL;
-              p = p->next)
+         for (p = o->link_order_head; p != NULL; p = p->next)
            {
              asection *input_section;
              bfd *input_bfd;
@@ -8518,7 +8472,7 @@ _bfd_mips_elf_final_link (abfd, info)
              input_swap = (get_elf_backend_data (input_bfd)
                            ->elf_backend_ecoff_debug_swap);
 
-             BFD_ASSERT (p->size == input_section->_raw_size);
+             BFD_ASSERT (p->size == input_section->size);
 
              /* The ECOFF linking code expects that we have already
                 read in the debugging information and set up an
@@ -8548,7 +8502,7 @@ _bfd_mips_elf_final_link (abfd, info)
                  const char *name;
                  struct mips_elf_link_hash_entry *h;
 
-                 (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
+                 (*input_swap->swap_ext_in) (input_bfd, eraw_src, &ext);
                  if (ext.asym.sc == scNil
                      || ext.asym.sc == scUndefined
                      || ext.asym.sc == scSUndefined)
@@ -8617,17 +8571,16 @@ _bfd_mips_elf_final_link (abfd, info)
          einfo.swap = swap;
          einfo.failed = FALSE;
          mips_elf_link_hash_traverse (mips_elf_hash_table (info),
-                                      mips_elf_output_extsym,
-                                      (PTR) &einfo);
+                                      mips_elf_output_extsym, &einfo);
          if (einfo.failed)
            return FALSE;
 
          /* Set the size of the .mdebug section.  */
-         o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap);
+         o->size = bfd_ecoff_debug_size (abfd, &debug, swap);
 
          /* Skip this section later on (I don't think this currently
             matters, but someday it might).  */
-         o->link_order_head = (struct bfd_link_order *) NULL;
+         o->link_order_head = NULL;
 
          mdebug_sec = o;
        }
@@ -8646,9 +8599,7 @@ _bfd_mips_elf_final_link (abfd, info)
             not used in executables files.  */
          if (! info->relocatable)
            {
-             for (p = o->link_order_head;
-                  p != (struct bfd_link_order *) NULL;
-                  p = p->next)
+             for (p = o->link_order_head; p != NULL; p = p->next)
                {
                  asection *input_section;
 
@@ -8668,7 +8619,7 @@ _bfd_mips_elf_final_link (abfd, info)
 
              /* Skip this section later on (I don't think this
                 currently matters, but someday it might).  */
-             o->link_order_head = (struct bfd_link_order *) NULL;
+             o->link_order_head = NULL;
 
              /* Really remove the section.  */
              for (secpp = &abfd->sections;
@@ -8715,16 +8666,14 @@ _bfd_mips_elf_final_link (abfd, info)
          /* Set up the first entry.  */
          c = 1;
          amt = c * sizeof (Elf32_gptab);
-         tab = (Elf32_gptab *) bfd_malloc (amt);
+         tab = bfd_malloc (amt);
          if (tab == NULL)
            return FALSE;
          tab[0].gt_header.gt_current_g_value = elf_gp_size (abfd);
          tab[0].gt_header.gt_unused = 0;
 
          /* Combine the input sections.  */
-         for (p = o->link_order_head;
-              p != (struct bfd_link_order *) NULL;
-              p = p->next)
+         for (p = o->link_order_head; p != NULL; p = p->next)
            {
              asection *input_section;
              bfd *input_bfd;
@@ -8745,7 +8694,7 @@ _bfd_mips_elf_final_link (abfd, info)
              /* Combine the gptab entries for this input section one
                 by one.  We know that the input gptab entries are
                 sorted by ascending -G value.  */
-             size = bfd_section_size (input_bfd, input_section);
+             size = input_section->size;
              last = 0;
              for (gpentry = sizeof (Elf32_External_gptab);
                   gpentry < size;
@@ -8759,9 +8708,8 @@ _bfd_mips_elf_final_link (abfd, info)
                  unsigned int look;
 
                  if (! (bfd_get_section_contents
-                        (input_bfd, input_section, (PTR) &ext_gptab,
-                         (file_ptr) gpentry,
-                         (bfd_size_type) sizeof (Elf32_External_gptab))))
+                        (input_bfd, input_section, &ext_gptab, gpentry,
+                         sizeof (Elf32_External_gptab))))
                    {
                      free (tab);
                      return FALSE;
@@ -8789,7 +8737,7 @@ _bfd_mips_elf_final_link (abfd, info)
 
                      /* We need a new table entry.  */
                      amt = (bfd_size_type) (c + 1) * sizeof (Elf32_gptab);
-                     new_tab = (Elf32_gptab *) bfd_realloc ((PTR) tab, amt);
+                     new_tab = bfd_realloc (tab, amt);
                      if (new_tab == NULL)
                        {
                          free (tab);
@@ -8832,7 +8780,7 @@ _bfd_mips_elf_final_link (abfd, info)
 
          /* Swap out the table.  */
          amt = (bfd_size_type) c * sizeof (Elf32_External_gptab);
-         ext_tab = (Elf32_External_gptab *) bfd_alloc (abfd, amt);
+         ext_tab = bfd_alloc (abfd, amt);
          if (ext_tab == NULL)
            {
              free (tab);
@@ -8843,33 +8791,31 @@ _bfd_mips_elf_final_link (abfd, info)
            bfd_mips_elf32_swap_gptab_out (abfd, tab + j, ext_tab + j);
          free (tab);
 
-         o->_raw_size = c * sizeof (Elf32_External_gptab);
+         o->size = c * sizeof (Elf32_External_gptab);
          o->contents = (bfd_byte *) ext_tab;
 
          /* Skip this section later on (I don't think this currently
             matters, but someday it might).  */
-         o->link_order_head = (struct bfd_link_order *) NULL;
+         o->link_order_head = NULL;
        }
     }
 
   /* Invoke the regular ELF backend linker to do all the work.  */
-  if (!MNAME(abfd,bfd_elf,bfd_final_link) (abfd, info))
+  if (!bfd_elf_final_link (abfd, info))
     return FALSE;
 
   /* Now write out the computed sections.  */
 
-  if (reginfo_sec != (asection *) NULL)
+  if (reginfo_sec != NULL)
     {
       Elf32_External_RegInfo ext;
 
       bfd_mips_elf32_swap_reginfo_out (abfd, &reginfo, &ext);
-      if (! bfd_set_section_contents (abfd, reginfo_sec, (PTR) &ext,
-                                     (file_ptr) 0,
-                                     (bfd_size_type) sizeof ext))
+      if (! bfd_set_section_contents (abfd, reginfo_sec, &ext, 0, sizeof ext))
        return FALSE;
     }
 
-  if (mdebug_sec != (asection *) NULL)
+  if (mdebug_sec != NULL)
     {
       BFD_ASSERT (abfd->output_has_begun);
       if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
@@ -8880,21 +8826,19 @@ _bfd_mips_elf_final_link (abfd, info)
       bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
     }
 
-  if (gptab_data_sec != (asection *) NULL)
+  if (gptab_data_sec != NULL)
     {
       if (! bfd_set_section_contents (abfd, gptab_data_sec,
                                      gptab_data_sec->contents,
-                                     (file_ptr) 0,
-                                     gptab_data_sec->_raw_size))
+                                     0, gptab_data_sec->size))
        return FALSE;
     }
 
-  if (gptab_bss_sec != (asection *) NULL)
+  if (gptab_bss_sec != NULL)
     {
       if (! bfd_set_section_contents (abfd, gptab_bss_sec,
                                      gptab_bss_sec->contents,
-                                     (file_ptr) 0,
-                                     gptab_bss_sec->_raw_size))
+                                     0, gptab_bss_sec->size))
        return FALSE;
     }
 
@@ -8905,8 +8849,7 @@ _bfd_mips_elf_final_link (abfd, info)
        {
          if (! bfd_set_section_contents (abfd, rtproc_sec,
                                          rtproc_sec->contents,
-                                         (file_ptr) 0,
-                                         rtproc_sec->_raw_size))
+                                         0, rtproc_sec->size))
            return FALSE;
        }
     }
@@ -8926,6 +8869,7 @@ struct mips_mach_extension {
 
 static const struct mips_mach_extension mips_mach_extensions[] = {
   /* MIPS64 extensions.  */
+  { bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
   { bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
 
   /* MIPS V extensions.  */
@@ -8947,6 +8891,7 @@ static const struct mips_mach_extension mips_mach_extensions[] = {
   { bfd_mach_mips10000, bfd_mach_mips8000 },
   { bfd_mach_mips5000, bfd_mach_mips8000 },
   { bfd_mach_mips7000, bfd_mach_mips8000 },
+  { bfd_mach_mips9000, bfd_mach_mips8000 },
 
   /* VR4100 extensions.  */
   { bfd_mach_mips4120, bfd_mach_mips4100 },
@@ -8977,8 +8922,7 @@ static const struct mips_mach_extension mips_mach_extensions[] = {
 /* Return true if bfd machine EXTENSION is an extension of machine BASE.  */
 
 static bfd_boolean
-mips_mach_extends_p (base, extension)
-     unsigned long base, extension;
+mips_mach_extends_p (unsigned long base, unsigned long extension)
 {
   size_t i;
 
@@ -8993,8 +8937,7 @@ mips_mach_extends_p (base, extension)
 /* Return true if the given ELF header flags describe a 32-bit binary.  */
 
 static bfd_boolean
-mips_32bit_flags_p (flags)
-     flagword flags;
+mips_32bit_flags_p (flagword flags)
 {
   return ((flags & EF_MIPS_32BITMODE) != 0
          || (flags & EF_MIPS_ABI) == E_MIPS_ABI_O32
@@ -9010,9 +8953,7 @@ mips_32bit_flags_p (flags)
    object file when linking.  */
 
 bfd_boolean
-_bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
-     bfd *ibfd;
-     bfd *obfd;
+_bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
   flagword old_flags;
   flagword new_flags;
@@ -9024,8 +8965,8 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
   if (! _bfd_generic_verify_endian_match (ibfd, obfd))
     {
       (*_bfd_error_handler)
-       (_("%s: endianness incompatible with that of the selected emulation"),
-        bfd_archive_filename (ibfd));
+       (_("%B: endianness incompatible with that of the selected emulation"),
+        ibfd);
       return FALSE;
     }
 
@@ -9036,8 +8977,8 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
   if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
     {
       (*_bfd_error_handler)
-       (_("%s: ABI is incompatible with that of the selected emulation"),
-        bfd_archive_filename (ibfd));
+       (_("%B: ABI is incompatible with that of the selected emulation"),
+        ibfd);
       return FALSE;
     }
 
@@ -9073,6 +9014,11 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
   new_flags &= ~EF_MIPS_XGOT;
   old_flags &= ~EF_MIPS_XGOT;
 
+  /* MIPSpro generates ucode info in n64 objects.  Again, we should
+     just be able to ignore this.  */
+  new_flags &= ~EF_MIPS_UCODE;
+  old_flags &= ~EF_MIPS_UCODE;
+
   if (new_flags == old_flags)
     return TRUE;
 
@@ -9085,10 +9031,10 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
          which are automatically generated by gas.  */
       if (strcmp (sec->name, ".reginfo")
          && strcmp (sec->name, ".mdebug")
-         && ((!strcmp (sec->name, ".text")
-              || !strcmp (sec->name, ".data")
-              || !strcmp (sec->name, ".bss"))
-             && sec->_raw_size != 0))
+         && (sec->size != 0
+             || (strcmp (sec->name, ".text")
+                 && strcmp (sec->name, ".data")
+                 && strcmp (sec->name, ".bss"))))
        {
          null_input_bfd = FALSE;
          break;
@@ -9103,8 +9049,8 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
       != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
     {
       (*_bfd_error_handler)
-       (_("%s: warning: linking PIC files with non-PIC files"),
-        bfd_archive_filename (ibfd));
+       (_("%B: warning: linking PIC files with non-PIC files"),
+        ibfd);
       ok = TRUE;
     }
 
@@ -9120,8 +9066,8 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
   if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags))
     {
       (*_bfd_error_handler)
-       (_("%s: linking 32-bit code with 64-bit code"),
-        bfd_archive_filename (ibfd));
+       (_("%B: linking 32-bit code with 64-bit code"),
+        ibfd);
       ok = FALSE;
     }
   else if (!mips_mach_extends_p (bfd_get_mach (ibfd), bfd_get_mach (obfd)))
@@ -9148,8 +9094,8 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
        {
          /* The ISAs aren't compatible.  */
          (*_bfd_error_handler)
-           (_("%s: linking %s module with previous %s modules"),
-            bfd_archive_filename (ibfd),
+           (_("%B: linking %s module with previous %s modules"),
+            ibfd,
             bfd_printable_name (ibfd),
             bfd_printable_name (obfd));
          ok = FALSE;
@@ -9171,8 +9117,8 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
              != elf_elfheader (obfd)->e_ident[EI_CLASS]))
        {
          (*_bfd_error_handler)
-           (_("%s: ABI mismatch: linking %s module with previous %s modules"),
-            bfd_archive_filename (ibfd),
+           (_("%B: ABI mismatch: linking %s module with previous %s modules"),
+            ibfd,
             elf_mips_abi_name (ibfd),
             elf_mips_abi_name (obfd));
          ok = FALSE;
@@ -9194,8 +9140,8 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
   if (new_flags != old_flags)
     {
       (*_bfd_error_handler)
-       (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
-        bfd_archive_filename (ibfd), (unsigned long) new_flags,
+       (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
+        ibfd, (unsigned long) new_flags,
         (unsigned long) old_flags);
       ok = FALSE;
     }
@@ -9212,9 +9158,7 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
 /* Function to keep MIPS specific file flags like as EF_MIPS_PIC.  */
 
 bfd_boolean
-_bfd_mips_elf_set_private_flags (abfd, flags)
-     bfd *abfd;
-     flagword flags;
+_bfd_mips_elf_set_private_flags (bfd *abfd, flagword flags)
 {
   BFD_ASSERT (!elf_flags_init (abfd)
              || elf_elfheader (abfd)->e_flags == flags);
@@ -9225,11 +9169,9 @@ _bfd_mips_elf_set_private_flags (abfd, flags)
 }
 
 bfd_boolean
-_bfd_mips_elf_print_private_bfd_data (abfd, ptr)
-     bfd *abfd;
-     PTR ptr;
+_bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
 {
-  FILE *file = (FILE *) ptr;
+  FILE *file = ptr;
 
   BFD_ASSERT (abfd != NULL && ptr != NULL);
 
@@ -9272,6 +9214,8 @@ _bfd_mips_elf_print_private_bfd_data (abfd, ptr)
     fprintf (file, _(" [mips64]"));
   else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2)
     fprintf (file, _(" [mips32r2]"));
+  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R2)
+    fprintf (file, _(" [mips64r2]"));
   else
     fprintf (file, _(" [unknown ISA]"));
 
@@ -9293,18 +9237,11 @@ _bfd_mips_elf_print_private_bfd_data (abfd, ptr)
 
 struct bfd_elf_special_section const _bfd_mips_elf_special_sections[]=
 {
-  { ".sdata",          0,      NULL,   0,
-    SHT_PROGBITS,      SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
-  { ".sbss",           0,      NULL,   0,
-    SHT_NOBITS,                SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
-  { ".lit4",           0,      NULL,   0,
-    SHT_PROGBITS,      SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
-  { ".lit8",           0,      NULL,   0,
-    SHT_PROGBITS,      SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
-  { ".ucode",          0,      NULL,   0,
-    SHT_MIPS_UCODE,    0 },
-  { ".mdebug",         0,      NULL,   0,
-    SHT_MIPS_DEBUG,    0 },
-  { NULL,              0,      NULL,   0,
-    0,                 0 }
+  { ".sdata",  6, -2, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
+  { ".sbss",   5, -2, SHT_NOBITS,     SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
+  { ".lit4",   5,  0, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
+  { ".lit8",   5,  0, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
+  { ".ucode",  6,  0, SHT_MIPS_UCODE, 0 },
+  { ".mdebug", 7,  0, SHT_MIPS_DEBUG, 0 },
+  { NULL,      0,  0, 0,              0 }
 };
This page took 0.090914 seconds and 4 git commands to generate.