]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elfxx-mips.c
Correct spelling of "relocatable".
[thirdparty/binutils-gdb.git] / bfd / elfxx-mips.c
index 72516f71f1c3743de350754cb231be5d077581d0..3e85fc3b40ab727acdf3bd69f7235031d4d553f2 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.  */
@@ -435,7 +434,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));
@@ -518,11 +516,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) \
@@ -1082,18 +1080,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;
@@ -1106,35 +1104,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;
@@ -1664,7 +1663,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;
@@ -1719,15 +1718,15 @@ mips_elf_get_global_gotsym_index (abfd)
 
   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;
 }
 
@@ -1770,7 +1769,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);
@@ -1828,7 +1827,7 @@ mips_elf_got_page (abfd, ibfd, info, value, offsetp)
 
   if (!entry)
     return MINUS_ONE;
-  
+
   index = entry->gotidx;
 
   if (offsetp)
@@ -1886,7 +1885,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;
 }
 
@@ -1918,14 +1917,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)
@@ -1965,7 +1964,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
@@ -2079,7 +2078,7 @@ mips_elf_record_global_got_symbol (h, abfd, info, g)
 
   if (! *loc)
     return FALSE;
-             
+
   entry.gotidx = -1;
   memcpy (*loc, &entry, sizeof entry);
 
@@ -2121,7 +2120,7 @@ mips_elf_record_local_got_symbol (abfd, symndx, addend, g)
 
   if (! *loc)
     return FALSE;
-             
+
   memcpy (*loc, &entry, sizeof entry);
 
   return TRUE;
@@ -2187,7 +2186,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;
@@ -2239,7 +2238,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)
@@ -2268,7 +2267,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)
@@ -2336,7 +2335,7 @@ mips_elf_merge_gots (bfd2got_, p)
     {
       bfd2got->g->next = arg->current;
       arg->current = bfd2got->g;
-      
+
       arg->current_count = lcount + gcount;
     }
 
@@ -2417,7 +2416,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
@@ -2437,7 +2436,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;
 }
 
@@ -2478,7 +2477,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);
 }
 
@@ -2566,7 +2565,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));
 
@@ -2592,7 +2591,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
@@ -2665,10 +2664,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.  */
@@ -2742,8 +2741,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;
 {
@@ -2874,7 +2873,7 @@ mips_elf_create_got_section (abfd, info, maybe_exclude)
   s = bfd_make_section (abfd, ".got");
   if (s == NULL
       || ! bfd_set_section_flags (abfd, s, flags)
-      || ! bfd_set_section_alignment (abfd, s, 4))
+      || ! bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd)))
     return FALSE;
 
   /* Define the symbol _GLOBAL_OFFSET_TABLE_.  We don't do this in the
@@ -3152,7 +3151,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))
@@ -3173,7 +3172,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)
@@ -3209,7 +3208,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)));
 
@@ -3306,7 +3305,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;
 
@@ -3357,7 +3356,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;
@@ -3382,7 +3381,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;
 
@@ -3442,7 +3441,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
@@ -3491,7 +3490,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;
 
@@ -3651,7 +3650,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
@@ -3689,13 +3688,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)
@@ -3854,7 +3853,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;
@@ -4975,19 +4974,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)
@@ -5062,7 +5061,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;
@@ -5370,12 +5369,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
@@ -5558,7 +5557,7 @@ _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 = _bfd_elf_link_read_relocs (abfd, sec, (PTR) NULL,
@@ -5599,7 +5598,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
@@ -5662,7 +5661,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)
        {
@@ -5711,7 +5710,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;
@@ -5749,7 +5748,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
@@ -5847,7 +5846,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,
@@ -5857,7 +5856,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;
@@ -6022,7 +6021,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);
@@ -6354,7 +6353,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;
 
@@ -6385,7 +6384,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;
@@ -6399,7 +6398,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))
@@ -6782,7 +6781,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)
@@ -7800,10 +7799,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;
@@ -7899,7 +7898,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))
        {
@@ -8130,12 +8129,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 */
@@ -8243,7 +8242,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;
            }
@@ -8253,11 +8252,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;
 
@@ -8380,17 +8379,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
@@ -8475,7 +8463,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;
 
@@ -8796,7 +8784,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;
@@ -9250,25 +9238,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))