bfd/
[binutils-gdb.git] / bfd / elfxx-mips.c
index d2ba1cf8c2317205921759cc37e469d483a4a8a1..4c5496516a8e06d2e68a4cead8ce3a99ce9839a5 100644 (file)
@@ -163,8 +163,7 @@ struct mips_elf_hash_sort_data
   long min_got_dynindx;
   /* The greatest dynamic symbol table index corresponding to a symbol
      with a GOT entry that is not referenced (e.g., a dynamic symbol
-     with dynamic relocations pointing to it from non-primary
-     GOTs).  */
+     with dynamic relocations pointing to it from non-primary GOTs).  */
   long max_unref_got_dynindx;
   /* The greatest dynamic symbol table index not corresponding to a
      symbol without a GOT entry.  */
@@ -189,10 +188,6 @@ struct mips_elf_link_hash_entry
      a readonly section.  */
   bfd_boolean readonly_reloc;
 
-  /* The index of the first dynamic relocation (in the .rel.dyn
-     section) against this symbol.  */
-  unsigned int min_dyn_reloc_index;
-
   /* We must not create a stub for a symbol that has relocations
      related to taking the function's address, i.e. any but
      R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",
@@ -391,12 +386,6 @@ 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 *));
-#if 0
-static void bfd_mips_elf_swap_msym_in
-  PARAMS ((bfd *, const Elf32_External_Msym *, Elf32_Internal_Msym *));
-#endif
-static void bfd_mips_elf_swap_msym_out
-  PARAMS ((bfd *, const Elf32_Internal_Msym *, Elf32_External_Msym *));
 static int sort_dynamic_relocs
   PARAMS ((const void *, const void *));
 static int sort_dynamic_relocs_64
@@ -408,6 +397,7 @@ 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
@@ -434,7 +424,6 @@ static const Elf_Internal_Rela *mips_elf_next_relocation
           const Elf_Internal_Rela *));
 static bfd_boolean mips_elf_local_relocation_p
   PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, bfd_boolean));
-static bfd_vma mips_elf_sign_extend PARAMS ((bfd_vma, int));
 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));
@@ -443,8 +432,6 @@ 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 asection *mips_elf_create_msym_section
-  PARAMS ((bfd *));
 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 *,
@@ -517,11 +504,11 @@ static bfd *reldyn_sorting_bfd;
 
 /* The name of the options section.  */
 #define MIPS_ELF_OPTIONS_SECTION_NAME(abfd) \
-  (ABI_64_P (abfd) ? ".MIPS.options" : ".options")
+  (NEWABI_P (abfd) ? ".MIPS.options" : ".options")
 
 /* The name of the stub section.  */
 #define MIPS_ELF_STUB_SECTION_NAME(abfd) \
-  (ABI_64_P (abfd) ? ".MIPS.stubs" : ".stub")
+  (NEWABI_P (abfd) ? ".MIPS.stubs" : ".stub")
 
 /* The size of an external REL relocation.  */
 #define MIPS_ELF_REL_SIZE(abfd) \
@@ -541,7 +528,7 @@ static bfd *reldyn_sorting_bfd;
 
 /* The default alignment for sections, as a power of two.  */
 #define MIPS_ELF_LOG_FILE_ALIGN(abfd)                          \
-  (get_elf_backend_data (abfd)->s->file_align == 8 ? 3 : 2)
+  (get_elf_backend_data (abfd)->s->log_file_align)
 
 /* Get word-sized data.  */
 #define MIPS_ELF_GET_WORD(abfd, ptr) \
@@ -731,7 +718,6 @@ mips_elf_link_hash_newfunc (entry, table, string)
       ret->esym.ifd = -2;
       ret->possibly_dynamic_relocs = 0;
       ret->readonly_reloc = FALSE;
-      ret->min_dyn_reloc_index = 0;
       ret->no_fn_stub = FALSE;
       ret->fn_stub = NULL;
       ret->need_fn_stub = FALSE;
@@ -1081,18 +1067,18 @@ mips_elf_check_mips16_stubs (h, data)
 \f
 bfd_reloc_status_type
 _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
-                              relocateable, data, gp)
+                              relocatable, data, gp)
      bfd *abfd;
      asymbol *symbol;
      arelent *reloc_entry;
      asection *input_section;
-     bfd_boolean relocateable;
+     bfd_boolean relocatable;
      PTR data;
      bfd_vma gp;
 {
   bfd_vma relocation;
-  unsigned long insn;
-  unsigned long val;
+  unsigned long insn = 0;
+  bfd_signed_vma val;
 
   if (bfd_is_com_section (symbol->section))
     relocation = 0;
@@ -1105,35 +1091,36 @@ _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
   /* Set val to the offset into the section or symbol.  */
-  if (reloc_entry->howto->src_mask == 0)
-    {
-      /* This case occurs with the 64-bit MIPS ELF ABI.  */
-      val = reloc_entry->addend;
-    }
-  else
+  val = reloc_entry->addend;
+
+  if (reloc_entry->howto->partial_inplace)
     {
-      val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
-      if (val & 0x8000)
-       val -= 0x10000;
+      insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+      val += insn & 0xffff;
     }
 
+  _bfd_mips_elf_sign_extend(val, 16);
+
   /* Adjust val for the final section location and GP value.  If we
-     are producing relocateable output, we don't want to do this for
+     are producing relocatable output, we don't want to do this for
      an external symbol.  */
-  if (! relocateable
+  if (! relocatable
       || (symbol->flags & BSF_SECTION_SYM) != 0)
     val += relocation - gp;
 
-  insn = (insn & ~0xffff) | (val & 0xffff);
-  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+  if (reloc_entry->howto->partial_inplace)
+    {
+      insn = (insn & ~0xffff) | (val & 0xffff);
+      bfd_put_32 (abfd, (bfd_vma) insn,
+                 (bfd_byte *) data + reloc_entry->address);
+    }
+  else
+    reloc_entry->addend = val;
 
-  if (relocateable)
+  if (relocatable)
     reloc_entry->address += input_section->output_offset;
-
-  else if ((long) val >= 0x8000 || (long) val < -0x8000)
+  else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
     return bfd_reloc_overflow;
 
   return bfd_reloc_ok;
@@ -1192,31 +1179,6 @@ bfd_elf32_swap_crinfo_out (abfd, in, ex)
   H_PUT_32 (abfd, in->konst, ex->konst);
   H_PUT_32 (abfd, in->vaddr, ex->vaddr);
 }
-
-#if 0
-/* Swap in an MSYM entry.  */
-
-static void
-bfd_mips_elf_swap_msym_in (abfd, ex, in)
-     bfd *abfd;
-     const Elf32_External_Msym *ex;
-     Elf32_Internal_Msym *in;
-{
-  in->ms_hash_value = H_GET_32 (abfd, ex->ms_hash_value);
-  in->ms_info = H_GET_32 (abfd, ex->ms_info);
-}
-#endif
-/* Swap out an MSYM entry.  */
-
-static void
-bfd_mips_elf_swap_msym_out (abfd, in, ex)
-     bfd *abfd;
-     const Elf32_Internal_Msym *in;
-     Elf32_External_Msym *ex;
-{
-  H_PUT_32 (abfd, in->ms_hash_value, ex->ms_hash_value);
-  H_PUT_32 (abfd, in->ms_info, ex->ms_info);
-}
 \f
 /* A .reginfo section holds a single Elf32_RegInfo structure.  These
    routines swap this structure in and out.  They are used outside of
@@ -1663,7 +1625,7 @@ mips_elf_rel_dyn_section (dynobj, create_p)
                                       | SEC_LINKER_CREATED
                                       | SEC_READONLY))
          || ! bfd_set_section_alignment (dynobj, sreloc,
-                                         4))
+                                         MIPS_ELF_LOG_FILE_ALIGN (dynobj)))
        return NULL;
     }
   return sreloc;
@@ -1707,6 +1669,29 @@ 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.  */
@@ -1746,7 +1731,7 @@ mips_elf_global_got_index (abfd, ibfd, h)
   if (g->bfd2got && ibfd)
     {
       struct mips_got_entry e, *p;
-      
+
       BFD_ASSERT (h->dynindx >= 0);
 
       g = mips_elf_got_for_ibfd (g, ibfd);
@@ -1804,7 +1789,7 @@ mips_elf_got_page (abfd, ibfd, info, value, offsetp)
 
   if (!entry)
     return MINUS_ONE;
-  
+
   index = entry->gotidx;
 
   if (offsetp)
@@ -1862,7 +1847,7 @@ mips_elf_got_offset_from_index (dynobj, output_bfd, input_bfd, index)
   g = mips_elf_got_info (dynobj, &sgot);
   gp = _bfd_get_gp_value (output_bfd)
     + mips_elf_adjust_gp (output_bfd, g, input_bfd);
-  
+
   return sgot->output_section->vma + sgot->output_offset + index - gp;
 }
 
@@ -1894,14 +1879,14 @@ mips_elf_create_local_got_entry (abfd, ibfd, gg, sgot, value)
                                                   INSERT);
   if (*loc)
     return *loc;
-      
+
   entry.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
 
   *loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
 
   if (! *loc)
     return NULL;
-             
+
   memcpy (*loc, &entry, sizeof entry);
 
   if (g->assigned_gotno >= g->local_gotno)
@@ -1941,7 +1926,7 @@ mips_elf_sort_hash_table (info, max_local)
   g = mips_elf_got_info (dynobj, NULL);
 
   hsd.low = NULL;
-  hsd.max_unref_got_dynindx = 
+  hsd.max_unref_got_dynindx =
   hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount
     /* In the multi-got case, assigned_gotno of the master got_info
        indicate the number of entries that aren't referenced in the
@@ -2055,7 +2040,7 @@ mips_elf_record_global_got_symbol (h, abfd, info, g)
 
   if (! *loc)
     return FALSE;
-             
+
   entry.gotidx = -1;
   memcpy (*loc, &entry, sizeof entry);
 
@@ -2097,7 +2082,7 @@ mips_elf_record_local_got_symbol (abfd, symndx, addend, g)
 
   if (! *loc)
     return FALSE;
-             
+
   memcpy (*loc, &entry, sizeof entry);
 
   return TRUE;
@@ -2163,7 +2148,7 @@ mips_elf_make_got_per_bfd (entryp, p)
   struct mips_got_info *g;
   struct mips_elf_bfd2got_hash bfdgot_entry, *bfdgot;
   void **bfdgotp;
-  
+
   /* Find the got_info for this GOT entry's input bfd.  Create one if
      none exists.  */
   bfdgot_entry.bfd = entry->abfd;
@@ -2215,7 +2200,7 @@ mips_elf_make_got_per_bfd (entryp, p)
   entryp = htab_find_slot (g->got_entries, entry, INSERT);
   if (*entryp != NULL)
     return 1;
-  
+
   *entryp = entry;
 
   if (entry->symndx >= 0 || entry->d.h->forced_local)
@@ -2244,7 +2229,7 @@ mips_elf_merge_gots (bfd2got_, p)
   unsigned int lcount = bfd2got->g->local_gotno;
   unsigned int gcount = bfd2got->g->global_gotno;
   unsigned int maxcnt = arg->max_count;
-  
+
   /* If we don't have a primary GOT and this is not too big, use it as
      a starting point for the primary GOT.  */
   if (! arg->primary && lcount + gcount <= maxcnt)
@@ -2312,7 +2297,7 @@ mips_elf_merge_gots (bfd2got_, p)
     {
       bfd2got->g->next = arg->current;
       arg->current = bfd2got->g;
-      
+
       arg->current_count = lcount + gcount;
     }
 
@@ -2393,7 +2378,7 @@ mips_elf_resolve_final_got_entry (entryp, p)
 
       if (entry->d.h == h)
        return 1;
-      
+
       entry->d.h = h;
 
       /* If we can't find this entry with the new bfd hash, re-insert
@@ -2413,7 +2398,7 @@ mips_elf_resolve_final_got_entry (entryp, p)
       /* We might want to decrement the global_gotno count, but it's
         either too early or too late for that at this point.  */
     }
-  
+
   return 1;
 }
 
@@ -2454,7 +2439,7 @@ mips_elf_adjust_gp (abfd, g, ibfd)
   BFD_ASSERT (g->next);
 
   g = g->next;
-  
+
   return (g->local_gotno + g->global_gotno) * MIPS_ELF_GOT_SIZE (abfd);
 }
 
@@ -2542,7 +2527,7 @@ mips_elf_multi_got (abfd, info, g, got, pages)
   {
     struct mips_elf_bfd2got_hash *bfdgot;
     void **bfdgotp;
-  
+
     bfdgot = (struct mips_elf_bfd2got_hash *)bfd_alloc
       (abfd, sizeof (struct mips_elf_bfd2got_hash));
 
@@ -2568,7 +2553,7 @@ mips_elf_multi_got (abfd, info, g, got, pages)
      the cache.  Also, knowing that every external symbol has a GOT
      helps speed up the resolution of local symbols too, so GNU/Linux
      follows IRIX's practice.
-     
+
      The number 2 is used by mips_elf_sort_hash_table_f to count
      global GOT symbols that are unreferenced in the primary GOT, with
      an initial dynamic index computed from gg->assigned_gotno, where
@@ -2641,10 +2626,10 @@ mips_elf_multi_got (abfd, info, g, got, pages)
 
   got->_raw_size = (gg->next->local_gotno
                    + gg->next->global_gotno) * MIPS_ELF_GOT_SIZE (abfd);
-  
+
   return TRUE;
 }
-     
+
 \f
 /* Returns the first relocation of type r_type found, beginning with
    RELOCATION.  RELEND is one-past-the-end of the relocation table.  */
@@ -2718,8 +2703,8 @@ mips_elf_local_relocation_p (input_bfd, relocation, local_sections,
 \f
 /* Sign-extend VALUE, which has the indicated number of BITS.  */
 
-static bfd_vma
-mips_elf_sign_extend (value, bits)
+bfd_vma
+_bfd_mips_elf_sign_extend (value, bits)
      bfd_vma value;
      int bits;
 {
@@ -2847,6 +2832,8 @@ mips_elf_create_got_section (abfd, info, maybe_exclude)
   if (maybe_exclude)
     flags |= SEC_EXCLUDE;
 
+  /* We have to use an alignment of 2**4 here because this is hardcoded
+     in the function stub generation and in the linker script.  */
   s = bfd_make_section (abfd, ".got");
   if (s == NULL
       || ! bfd_set_section_flags (abfd, s, flags)
@@ -2892,34 +2879,6 @@ mips_elf_create_got_section (abfd, info, maybe_exclude)
 
   return TRUE;
 }
-
-/* Returns the .msym section for ABFD, creating it if it does not
-   already exist.  Returns NULL to indicate error.  */
-
-static asection *
-mips_elf_create_msym_section (abfd)
-     bfd *abfd;
-{
-  asection *s;
-
-  s = bfd_get_section_by_name (abfd, ".msym");
-  if (!s)
-    {
-      s = bfd_make_section (abfd, ".msym");
-      if (!s
-         || !bfd_set_section_flags (abfd, s,
-                                    SEC_ALLOC
-                                    | SEC_LOAD
-                                    | SEC_HAS_CONTENTS
-                                    | SEC_LINKER_CREATED
-                                    | SEC_READONLY)
-         || !bfd_set_section_alignment (abfd, s,
-                                        MIPS_ELF_LOG_FILE_ALIGN (abfd)))
-       return NULL;
-    }
-
-  return s;
-}
 \f
 /* Calculate the value produced by the RELOCATION (which comes from
    the INPUT_BFD).  The ADDEND is the addend to use for this
@@ -3128,7 +3087,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
   /* If this is a 32- or 64-bit call to a 16-bit function with a stub, we
      need to redirect the call to the stub, unless we're already *in*
      a stub.  */
-  if (r_type != R_MIPS16_26 && !info->relocateable
+  if (r_type != R_MIPS16_26 && !info->relocatable
       && ((h != NULL && h->fn_stub != NULL)
          || (local_p && elf_tdata (input_bfd)->local_stubs != NULL
              && elf_tdata (input_bfd)->local_stubs[r_symndx] != NULL))
@@ -3149,7 +3108,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
     }
   /* If this is a 16-bit call to a 32- or 64-bit function with a stub, we
      need to redirect the call to the stub.  */
-  else if (r_type == R_MIPS16_26 && !info->relocateable
+  else if (r_type == R_MIPS16_26 && !info->relocatable
           && h != NULL
           && (h->call_stub != NULL || h->call_fp_stub != NULL)
           && !target_is_16_bit_code_p)
@@ -3185,7 +3144,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
 
   /* Calls from 16-bit code to 32-bit code and vice versa require the
      special jalx instruction.  */
-  *require_jalxp = (!info->relocateable
+  *require_jalxp = (!info->relocatable
                     && (((r_type == R_MIPS16_26) && !target_is_16_bit_code_p)
                         || ((r_type == R_MIPS_26) && target_is_16_bit_code_p)));
 
@@ -3197,9 +3156,14 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
   switch (r_type)
     {
     case R_MIPS_GOT_PAGE:
-      /* If we didn't create a dynamic index for this symbol, it can
-        be regarded as local.  */
-      if (local_p || ! h || h->root.dynindx < 0)
+    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));
+      if (local_p || r_type == R_MIPS_GOT_OFST)
        break;
       /* Fall through.  */
 
@@ -3277,7 +3241,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       return bfd_reloc_continue;
 
     case R_MIPS_16:
-      value = symbol + mips_elf_sign_extend (addend, 16);
+      value = symbol + _bfd_mips_elf_sign_extend (addend, 16);
       overflowed_p = mips_elf_overflow_p (value, 16);
       break;
 
@@ -3328,7 +3292,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       break;
 
     case R_MIPS_GNU_REL16_S2:
-      value = symbol + mips_elf_sign_extend (addend << 2, 18) - p;
+      value = symbol + _bfd_mips_elf_sign_extend (addend << 2, 18) - p;
       overflowed_p = mips_elf_overflow_p (value, 18);
       value = (value >> 2) & howto->dst_mask;
       break;
@@ -3353,7 +3317,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       if (local_p)
        value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
       else
-       value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
+       value = (_bfd_mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
       value &= howto->dst_mask;
       break;
 
@@ -3413,7 +3377,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
         instruction.  If the addend was separate, leave it alone,
         otherwise we may lose significant bits.  */
       if (howto->partial_inplace)
-       addend = mips_elf_sign_extend (addend, 16);
+       addend = _bfd_mips_elf_sign_extend (addend, 16);
       value = symbol + addend - gp;
       /* If the symbol was local, any earlier relocatable links will
         have adjusted its addend with the gp offset, so compensate
@@ -3462,7 +3426,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       break;
 
     case R_MIPS_PC16:
-      value = mips_elf_sign_extend (addend, 16) + symbol - p;
+      value = _bfd_mips_elf_sign_extend (addend, 16) + symbol - p;
       overflowed_p = mips_elf_overflow_p (value, 16);
       break;
 
@@ -3485,7 +3449,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       /* GOT_PAGE relocations that reference non-local symbols decay
         to GOT_DISP.  The corresponding GOT_OFST relocation decays to
         0.  */
-      if (! (local_p || ! h || h->root.dynindx < 0))
+      if (! local_p)
        goto got_disp;
       value = mips_elf_got_page (abfd, input_bfd, info, symbol + addend, NULL);
       if (value == MINUS_ONE)
@@ -3496,7 +3460,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
       break;
 
     case R_MIPS_GOT_OFST:
-      if (local_p || ! h || h->root.dynindx < 0)
+      if (local_p)
        mips_elf_got_page (abfd, input_bfd, info, symbol + addend, &value);
       else
        value = addend;
@@ -3622,7 +3586,7 @@ mips_elf_perform_relocation (info, howto, relocation, value, input_bfd,
         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 relocateable object file, R_MIPS16_26 is
+        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
@@ -3660,13 +3624,13 @@ mips_elf_perform_relocation (info, howto, relocation, value, input_bfd,
         where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is
         ((sub1 << 16) | sub2)).
 
-        When producing a relocateable object file, the calculation is
+        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->relocateable)
+      if (!info->relocatable)
        /* Shuffle the bits according to the formula above.  */
        value = (((value & 0x1f0000) << 5)
                 | ((value & 0x3e00000) >> 5)
@@ -3825,7 +3789,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
   /* We begin by assuming that the offset for the dynamic relocation
      is the same as for the original relocation.  We'll adjust this
      later to reflect the correct output offsets.  */
-  if (elf_section_data (input_section)->sec_info_type != ELF_INFO_TYPE_STABS)
+  if (input_section->sec_info_type != ELF_INFO_TYPE_STABS)
     {
       outrel[1].r_offset = rel[1].r_offset;
       outrel[2].r_offset = rel[2].r_offset;
@@ -3845,9 +3809,17 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
     }
 #endif
 
-  if (outrel[0].r_offset == (bfd_vma) -1
-      || outrel[0].r_offset == (bfd_vma) -2)
+  if (outrel[0].r_offset == (bfd_vma) -1)
+    /* The relocation field has been deleted.  */
     skip = TRUE;
+  else if (outrel[0].r_offset == (bfd_vma) -2)
+    {
+      /* 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;
+    }
 
   /* 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
@@ -3857,18 +3829,27 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
   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))
-       {
-         indx = h->root.dynindx;
+                                  & ELF_LINK_HASH_DEF_REGULAR) == 0)
          /* h->root.dynindx may be -1 if this symbol was marked to
             become local.  */
-         if (indx == -1)
-           indx = 0;
+         && h->root.dynindx != -1)
+       {
+         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;
        }
       else
        {
@@ -3897,14 +3878,20 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
             section-relative relocations.  It's not like they're
             useful, after all.  This should be a bit more efficient
             as well.  */
-         indx = 0;
+         /* ??? 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 (!indx && r_type != R_MIPS_REL32)
+      if (defined_p && r_type != R_MIPS_REL32)
        *addendp += symbol;
 
       /* The relocation is always an REL32 relocation because we don't
@@ -3955,13 +3942,6 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
       (output_bfd, &outrel[0],
        (sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel)));
 
-  /* Record the index of the first relocation referencing H.  This
-     information is later emitted in the .msym section.  */
-  if (h != NULL
-      && (h->min_dyn_reloc_index == 0
-         || sreloc->reloc_count < h->min_dyn_reloc_index))
-    h->min_dyn_reloc_index = sreloc->reloc_count;
-
   /* We've now added another relocation.  */
   ++sreloc->reloc_count;
 
@@ -4611,30 +4591,11 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
       hdr->sh_entsize = 8;
     }
 
-  /* The generic elf_fake_sections will set up REL_HDR using the
-     default kind of relocations.  But, we may actually need both
-     kinds of relocations, so we set up the second header here.
-
-     This is not necessary for the O32 ABI since that only uses Elf32_Rel
-     relocations (cf. System V ABI, MIPS RISC Processor Supplement,
-     3rd Edition, p. 4-17).  It breaks the IRIX 5/6 32-bit ld, since one
-     of the resulting empty .rela.<section> sections starts with
-     sh_offset == object size, and ld doesn't allow that.  While the check
-     is arguably bogus for empty or SHT_NOBITS sections, it can easily be
-     avoided by not emitting those useless sections in the first place.  */
-  if (! SGI_COMPAT (abfd) && ! NEWABI_P(abfd)
-      && (sec->flags & SEC_RELOC) != 0)
-    {
-      struct bfd_elf_section_data *esd;
-      bfd_size_type amt = sizeof (Elf_Internal_Shdr);
-
-      esd = elf_section_data (sec);
-      BFD_ASSERT (esd->rel_hdr2 == NULL);
-      esd->rel_hdr2 = (Elf_Internal_Shdr *) bfd_zalloc (abfd, amt);
-      if (!esd->rel_hdr2)
-       return FALSE;
-      _bfd_elf_init_reloc_shdr (abfd, esd->rel_hdr2, sec, !sec->use_rela_p);
-    }
+  /* The generic elf_fake_sections will set up REL_HDR using the default
+   kind of relocations.  We used to set up a second header for the
+   non-default kind of relocations here, but only NewABI would use
+   these, and the IRIX ld doesn't like resulting empty RELA sections.
+   Thus we create those header only on demand now.  */
 
   return TRUE;
 }
@@ -4881,13 +4842,6 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
   if (! mips_elf_rel_dyn_section (elf_hash_table (info)->dynobj, TRUE))
     return FALSE;
 
-  /* Create the .msym section on IRIX6.  It is used by the dynamic
-     linker to speed up dynamic relocations, and to avoid computing
-     the ELF hash for symbols.  */
-  if (IRIX_COMPAT (abfd) == ict_irix6
-      && !mips_elf_create_msym_section (abfd))
-    return FALSE;
-
   /* Create .stub section.  */
   if (bfd_get_section_by_name (abfd,
                               MIPS_ELF_STUB_SECTION_NAME (abfd)) == NULL)
@@ -4946,19 +4900,19 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
       /* Change alignments of some sections.  */
       s = bfd_get_section_by_name (abfd, ".hash");
       if (s != NULL)
-       bfd_set_section_alignment (abfd, s, 4);
+       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
       s = bfd_get_section_by_name (abfd, ".dynsym");
       if (s != NULL)
-       bfd_set_section_alignment (abfd, s, 4);
+       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
       s = bfd_get_section_by_name (abfd, ".dynstr");
       if (s != NULL)
-       bfd_set_section_alignment (abfd, s, 4);
+       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
       s = bfd_get_section_by_name (abfd, ".reginfo");
       if (s != NULL)
-       bfd_set_section_alignment (abfd, s, 4);
+       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
       s = bfd_get_section_by_name (abfd, ".dynamic");
       if (s != NULL)
-       bfd_set_section_alignment (abfd, s, 4);
+       bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
     }
 
   if (!info->shared)
@@ -5033,7 +4987,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
   asection *sreloc;
   struct elf_backend_data *bed;
 
-  if (info->relocateable)
+  if (info->relocatable)
     return TRUE;
 
   dynobj = elf_hash_table (info)->dynobj;
@@ -5077,10 +5031,10 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
                              sizeof CALL_FP_STUB - 1) == 0)
                continue;
 
-             sec_relocs = (MNAME(abfd,_bfd_elf,link_read_relocs)
-                           (abfd, o, (PTR) NULL,
-                            (Elf_Internal_Rela *) NULL,
-                            info->keep_memory));
+             sec_relocs
+               = _bfd_elf_link_read_relocs (abfd, o, (PTR) NULL,
+                                            (Elf_Internal_Rela *) NULL,
+                                            info->keep_memory);
              if (sec_relocs == NULL)
                return FALSE;
 
@@ -5341,12 +5295,12 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
            {
              struct mips_elf_link_hash_entry *hmips =
                (struct mips_elf_link_hash_entry *) h;
-             
+
              while (hmips->root.root.type == bfd_link_hash_indirect
                     || hmips->root.root.type == bfd_link_hash_warning)
                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
@@ -5484,6 +5438,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
        case R_MIPS_CALL16:
        case R_MIPS_CALL_HI16:
        case R_MIPS_CALL_LO16:
+       case R_MIPS_JALR:
          break;
        }
 
@@ -5529,12 +5484,12 @@ _bfd_mips_relax_section (abfd, sec, link_info, again)
   /* We are not currently changing any sizes, so only one pass.  */
   *again = FALSE;
 
-  if (link_info->relocateable)
+  if (link_info->relocatable)
     return TRUE;
 
-  internal_relocs = (MNAME(abfd,_bfd_elf,link_read_relocs)
-                     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
-                      link_info->keep_memory));
+  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, (PTR) NULL,
+                                              (Elf_Internal_Rela *) NULL,
+                                              link_info->keep_memory);
   if (internal_relocs == NULL)
     return TRUE;
 
@@ -5570,7 +5525,7 @@ _bfd_mips_relax_section (abfd, sec, link_info, again)
          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 a symbol is undefined, or if it may be overridden,
             skip it.  */
          if (! ((h->root.root.type == bfd_link_hash_defined
@@ -5633,7 +5588,7 @@ _bfd_mips_relax_section (abfd, sec, link_info, again)
       /* Check that it's in range.  */
       if (sym_offset < -0x8000 || sym_offset >= 0x8000)
        continue;
-      
+
       /* Get the section contents if we haven't done so already.  */
       if (contents == NULL)
        {
@@ -5682,7 +5637,7 @@ _bfd_mips_relax_section (abfd, sec, link_info, again)
     }
   return TRUE;
 
- relax_return:  
+ relax_return:
   if (free_contents != NULL)
     free (free_contents);
   return FALSE;
@@ -5720,7 +5675,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
      any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
      file.  */
   hmips = (struct mips_elf_link_hash_entry *) h;
-  if (! info->relocateable
+  if (! info->relocatable
       && hmips->possibly_dynamic_relocs != 0
       && (h->root.type == bfd_link_hash_defweak
          || (h->elf_link_hash_flags
@@ -5818,7 +5773,7 @@ _bfd_mips_elf_always_size_sections (output_bfd, info)
     bfd_set_section_size (output_bfd, ri,
                          (bfd_size_type) sizeof (Elf32_External_RegInfo));
 
-  if (! (info->relocateable
+  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,
@@ -5828,7 +5783,7 @@ _bfd_mips_elf_always_size_sections (output_bfd, info)
   if (dynobj == NULL)
     /* Relocatable links don't have it.  */
     return TRUE;
-  
+
   g = mips_elf_got_info (dynobj, &s);
   if (s == NULL)
     return TRUE;
@@ -5993,7 +5948,7 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
          struct mips_got_info *g = gg;
          struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
          unsigned int needed_relocs = 0;
-         
+
          if (gg->next)
            {
              set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (output_bfd);
@@ -6049,10 +6004,6 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
       else if (SGI_COMPAT (output_bfd)
               && strncmp (name, ".compact_rel", 12) == 0)
        s->_raw_size += mips_elf_hash_table (info)->compact_rel_size;
-      else if (strcmp (name, ".msym") == 0)
-       s->_raw_size = (sizeof (Elf32_External_Msym)
-                       * (elf_hash_table (info)->dynsymcount
-                          + bfd_count_sections (output_bfd)));
       else if (strncmp (name, ".init", 5) != 0)
        {
          /* It's not one of our sections, so don't allocate space.  */
@@ -6197,10 +6148,6 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
              (dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj)))
          && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0))
        return FALSE;
-
-      if (bfd_get_section_by_name (dynobj, ".msym")
-         && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_MSYM, 0))
-       return FALSE;
     }
 
   return TRUE;
@@ -6325,7 +6272,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                                                input_bfd, contents);
                  l &= lo16_howto->src_mask;
                  l <<= lo16_howto->rightshift;
-                 l = mips_elf_sign_extend (l, 16);
+                 l = _bfd_mips_elf_sign_extend (l, 16);
 
                  addend <<= 16;
 
@@ -6356,7 +6303,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            addend = rel->r_addend;
        }
 
-      if (info->relocateable)
+      if (info->relocatable)
        {
          Elf_Internal_Sym *sym;
          unsigned long r_symndx;
@@ -6370,7 +6317,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
             they're against a section symbol, in which case we need
             to adjust by the section offset, or unless they're GP
             relative in which case we need to adjust by the amount
-            that we're adjusting GP in this relocateable object.  */
+            that we're adjusting GP in this relocatable object.  */
 
          if (! mips_elf_local_relocation_p (input_bfd, rel, local_sections,
                                             FALSE))
@@ -6633,6 +6580,7 @@ mips_elf_irix6_finish_dynamic_symbol (abfd, name, sym)
          /* All of these symbols are given type STT_SECTION by the
             IRIX6 linker.  */
          sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
+         sym->st_other = STO_PROTECTED;
 
          /* The IRIX linker puts these symbols in special sections.  */
          if (i == 0)
@@ -6657,14 +6605,11 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
   bfd *dynobj;
   bfd_vma gval;
   asection *sgot;
-  asection *smsym;
   struct mips_got_info *g, *gg;
   const char *name;
-  struct mips_elf_link_hash_entry *mh;
 
   dynobj = elf_hash_table (info)->dynobj;
   gval = sym->st_value;
-  mh = (struct mips_elf_link_hash_entry *) h;
 
   if (h->plt.offset != (bfd_vma) -1)
     {
@@ -6720,22 +6665,7 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       bfd_vma offset;
       bfd_vma value;
 
-      if (sym->st_value)
-       value = sym->st_value;
-      else
-       {
-         /* For an entity defined in a shared object, this will be
-            NULL.  (For functions in shared objects for
-            which we have created stubs, ST_VALUE will be non-NULL.
-            That's because such the functions are now no longer defined
-            in a shared object.)  */
-
-         if ((info->shared && h->root.type == bfd_link_hash_undefined)
-             || h->root.type == bfd_link_hash_undefweak)
-           value = 0;
-         else
-           value = h->root.u.def.value;
-       }
+      value = sym->st_value;
       offset = mips_elf_global_got_index (dynobj, output_bfd, h);
       MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
     }
@@ -6753,7 +6683,7 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       e.abfd = output_bfd;
       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)
@@ -6793,21 +6723,6 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
        }
     }
 
-  /* Create a .msym entry, if appropriate.  */
-  smsym = bfd_get_section_by_name (dynobj, ".msym");
-  if (smsym)
-    {
-      Elf32_Internal_Msym msym;
-
-      msym.ms_hash_value = bfd_elf_hash (h->root.root.string);
-      /* It is undocumented what the `1' indicates, but IRIX6 uses
-        this value.  */
-      msym.ms_info = ELF32_MS_INFO (mh->min_dyn_reloc_index, 1);
-      bfd_mips_elf_swap_msym_out
-       (dynobj, &msym,
-        ((Elf32_External_Msym *) smsym->contents) + h->dynindx);
-    }
-
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
   name = h->root.root.string;
   if (strcmp (name, "_DYNAMIC") == 0
@@ -7130,33 +7045,9 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
     }
 
   {
-    asection *smsym;
     asection *s;
     Elf32_compact_rel cpt;
 
-    /* ??? The section symbols for the output sections were set up in
-       _bfd_elf_final_link.  SGI sets the STT_NOTYPE attribute for these
-       symbols.  Should we do so?  */
-
-    smsym = bfd_get_section_by_name (dynobj, ".msym");
-    if (smsym != NULL)
-      {
-       Elf32_Internal_Msym msym;
-
-       msym.ms_hash_value = 0;
-       msym.ms_info = ELF32_MS_INFO (0, 1);
-
-       for (s = output_bfd->sections; s != NULL; s = s->next)
-         {
-           long dynindx = elf_section_data (s)->dynindx;
-
-           bfd_mips_elf_swap_msym_out
-             (output_bfd, &msym,
-              (((Elf32_External_Msym *) smsym->contents)
-               + dynindx));
-         }
-      }
-
     if (SGI_COMPAT (output_bfd))
       {
        /* Write .compact_rel section out.  */
@@ -7272,6 +7163,7 @@ mips_set_isa_flags (abfd)
       break;
 
     case bfd_mach_mips5000:
+    case bfd_mach_mips7000:
     case bfd_mach_mips8000:
     case bfd_mach_mips10000:
     case bfd_mach_mips12000:
@@ -7749,10 +7641,6 @@ _bfd_mips_elf_copy_indirect_symbol (bed, dir, ind)
   dirmips->possibly_dynamic_relocs += indmips->possibly_dynamic_relocs;
   if (indmips->readonly_reloc)
     dirmips->readonly_reloc = TRUE;
-  if (dirmips->min_dyn_reloc_index == 0
-      || (indmips->min_dyn_reloc_index != 0
-         && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
-    dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index;
   if (indmips->no_fn_stub)
     dirmips->no_fn_stub = TRUE;
 }
@@ -7771,10 +7659,10 @@ _bfd_mips_elf_hide_symbol (info, entry, force_local)
   h = (struct mips_elf_link_hash_entry *) entry;
   if (h->forced_local)
     return;
-  h->forced_local = TRUE;
+  h->forced_local = force_local;
 
   dynobj = elf_hash_table (info)->dynobj;
-  if (dynobj != NULL)
+  if (dynobj != NULL && force_local)
     {
       got = mips_elf_got_section (dynobj, FALSE);
       g = mips_elf_section_data (got)->u.got_info;
@@ -7858,10 +7746,9 @@ _bfd_mips_elf_discard_info (abfd, cookie, info)
   if (! tdata)
     return FALSE;
 
-  cookie->rels = (MNAME(abfd,_bfd_elf,link_read_relocs)
-                 (abfd, o, (PTR) NULL,
-                  (Elf_Internal_Rela *) NULL,
-                  info->keep_memory));
+  cookie->rels = _bfd_elf_link_read_relocs (abfd, o, (PTR) NULL,
+                                           (Elf_Internal_Rela *) NULL,
+                                           info->keep_memory);
   if (!cookie->rels)
     {
       free (tdata);
@@ -7871,7 +7758,7 @@ _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; i ++)
+  for (i = 0, skip = 0; i < o->_raw_size / PDR_SIZE; i ++)
     {
       if (MNAME(abfd,_bfd_elf,reloc_symbol_deleted_p) (i * PDR_SIZE, cookie))
        {
@@ -8102,12 +7989,12 @@ _bfd_mips_elf_set_section_contents (abfd, section, location, offset, count)
 
 bfd_byte *
 _bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
-                                             data, relocateable, symbols)
+                                             data, relocatable, symbols)
      bfd *abfd;
      struct bfd_link_info *link_info;
      struct bfd_link_order *link_order;
      bfd_byte *data;
-     bfd_boolean relocateable;
+     bfd_boolean relocatable;
      asymbol **symbols;
 {
   /* Get enough memory to hold the stuff */
@@ -8215,7 +8102,7 @@ _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, relocateable,
+                                                input_section, relocatable,
                                                 (PTR) data, gp);
              goto skip_bfd_perform_relocation;
            }
@@ -8225,11 +8112,11 @@ _bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
                                      *parent,
                                      (PTR) data,
                                      input_section,
-                                     relocateable ? abfd : (bfd *) NULL,
+                                     relocatable ? abfd : (bfd *) NULL,
                                      &error_message);
        skip_bfd_perform_relocation:
 
-         if (relocateable)
+         if (relocatable)
            {
              asection *os = input_section->output_section;
 
@@ -8352,17 +8239,6 @@ _bfd_mips_elf_final_link (abfd, info)
     scRData, scSData, scSBss, scBss
   };
 
-  /* If all the things we linked together were PIC, but we're
-     producing an executable (rather than a shared object), then the
-     resulting file is CPIC (i.e., it calls PIC code.)  */
-  if (!info->shared
-      && !info->relocateable
-      && elf_elfheader (abfd)->e_flags & EF_MIPS_PIC)
-    {
-      elf_elfheader (abfd)->e_flags &= ~EF_MIPS_PIC;
-      elf_elfheader (abfd)->e_flags |= EF_MIPS_CPIC;
-    }
-
   /* We'd carefully arranged the dynamic symbol indices, and then the
      generic size_dynamic_sections renumbered them out from under us.
      Rather than trying somehow to prevent the renumbering, just do
@@ -8447,7 +8323,7 @@ _bfd_mips_elf_final_link (abfd, info)
        elf_gp (abfd) = (h->u.def.value
                         + h->u.def.section->output_section->vma
                         + h->u.def.section->output_offset);
-      else if (info->relocateable)
+      else if (info->relocatable)
        {
          bfd_vma lo = MINUS_ONE;
 
@@ -8768,7 +8644,7 @@ _bfd_mips_elf_final_link (abfd, info)
             information describing how the small data area would
             change depending upon the -G switch.  These sections
             not used in executables files.  */
-         if (! info->relocateable)
+         if (! info->relocatable)
            {
              for (p = o->link_order_head;
                   p != (struct bfd_link_order *) NULL;
@@ -9070,6 +8946,7 @@ static const struct mips_mach_extension mips_mach_extensions[] = {
   { bfd_mach_mips5, bfd_mach_mips8000 },
   { bfd_mach_mips10000, bfd_mach_mips8000 },
   { bfd_mach_mips5000, bfd_mach_mips8000 },
+  { bfd_mach_mips7000, bfd_mach_mips8000 },
 
   /* VR4100 extensions.  */
   { bfd_mach_mips4120, bfd_mach_mips4100 },
@@ -9145,12 +9022,25 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
 
   /* Check if we have the same endianess */
   if (! _bfd_generic_verify_endian_match (ibfd, obfd))
-    return FALSE;
+    {
+      (*_bfd_error_handler)
+       (_("%s: endianness incompatible with that of the selected emulation"),
+        bfd_archive_filename (ibfd));
+      return FALSE;
+    }
 
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return TRUE;
 
+  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));
+      return FALSE;
+    }
+
   new_flags = elf_elfheader (ibfd)->e_flags;
   elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
   old_flags = elf_elfheader (obfd)->e_flags;
@@ -9209,25 +9099,22 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
 
   ok = TRUE;
 
-  if ((new_flags & EF_MIPS_PIC) != (old_flags & EF_MIPS_PIC))
+  if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)
+      != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
     {
-      new_flags &= ~EF_MIPS_PIC;
-      old_flags &= ~EF_MIPS_PIC;
       (*_bfd_error_handler)
-       (_("%s: linking PIC files with non-PIC files"),
+       (_("%s: warning: linking PIC files with non-PIC files"),
         bfd_archive_filename (ibfd));
-      ok = FALSE;
+      ok = TRUE;
     }
 
-  if ((new_flags & EF_MIPS_CPIC) != (old_flags & EF_MIPS_CPIC))
-    {
-      new_flags &= ~EF_MIPS_CPIC;
-      old_flags &= ~EF_MIPS_CPIC;
-      (*_bfd_error_handler)
-       (_("%s: linking abicalls files with non-abicalls files"),
-        bfd_archive_filename (ibfd));
-      ok = FALSE;
-    }
+  if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC))
+    elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC;
+  if (! (new_flags & EF_MIPS_PIC))
+    elf_elfheader (obfd)->e_flags &= ~EF_MIPS_PIC;
+
+  new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
+  old_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
 
   /* Compare the ISAs.  */
   if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags))
@@ -9403,3 +9290,21 @@ _bfd_mips_elf_print_private_bfd_data (abfd, ptr)
 
   return TRUE;
 }
+
+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 }
+};