* elf32-mips.c (mips_elf_next_lo16_addend): Rename to ...
[deliverable/binutils-gdb.git] / bfd / elf32-mips.c
index 8ac5dcffc1b165e640c36167fccc98d76b650726..9d963cca2b42deb0afb9d726a3ae9f3c83c79858 100644 (file)
@@ -165,8 +165,8 @@ static boolean mips_elf_record_global_got_symbol
           struct mips_got_info *));
 static bfd_vma mips_elf_got_page
   PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *));
-static boolean mips_elf_next_lo16_addend
-  PARAMS ((const Elf_Internal_Rela *, const Elf_Internal_Rela *, bfd_vma *));
+static const Elf_Internal_Rela *mips_elf_next_lo16_relocation
+  PARAMS ((const Elf_Internal_Rela *, const Elf_Internal_Rela *));
 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 *,
@@ -5563,15 +5563,13 @@ mips_elf_got16_entry (abfd, info, value)
   return index;
 }
 
-/* Sets *ADDENDP to the addend for the first R_MIPS_LO16 relocation
-   found, beginning with RELOCATION.  RELEND is one-past-the-end of
-   the relocation table.  */
+/* Returns the first R_MIPS_LO16 relocation found, beginning with
+   RELOCATION.  RELEND is one-past-the-end of the relocation table.  */
 
-static boolean
-mips_elf_next_lo16_addend (relocation, relend, addendp)
+static const Elf_Internal_Rela *
+mips_elf_next_lo16_relocation (relocation, relend)
      const Elf_Internal_Rela *relocation;
      const Elf_Internal_Rela *relend;
-     bfd_vma *addendp;
 {
   /* According to the MIPS ELF ABI, the R_MIPS_LO16 relocation must be
      immediately following.  However, for the IRIX6 ABI, the next
@@ -5582,17 +5580,14 @@ mips_elf_next_lo16_addend (relocation, relend, addendp)
   while (relocation < relend)
     {
       if (ELF32_R_TYPE (relocation->r_info) == R_MIPS_LO16)
-       {
-         *addendp = relocation->r_addend;
-         return true;
-       }
+       return relocation;
 
       ++relocation;
     }
 
   /* We didn't find it.  */
   bfd_set_error (bfd_error_bad_value);
-  return false;
+  return NULL;
 }
 
 /* Create a rel.dyn relocation for the dynamic linker to resolve.  The
@@ -5877,6 +5872,19 @@ mips_elf_calculate_relocation (abfd,
           and check to see if they exist by looking at their
           addresses.  */
        symbol = 0;
+      else if (info->shared && !info->symbolic && !info->no_undefined)
+       relocation = 0;
+      else if (strcmp (h->root.root.root.string, "_DYNAMIC_LINK") == 0)
+       {
+         /* If this is a dynamic link, we should have created a
+            _DYNAMIC_LINK symbol in mips_elf_create_dynamic_sections.
+            Otherwise, we should define the symbol with a value of 0.
+            FIXME: It should probably get into the symbol table
+            somehow as well.  */
+         BFD_ASSERT (! info->shared);
+         BFD_ASSERT (bfd_get_section_by_name (abfd, ".dynamic") == NULL);
+         relocation = 0;
+       }
       else
        {
          (*info->callbacks->undefined_symbol)
@@ -6516,13 +6524,24 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      && mips_elf_local_relocation_p (input_bfd, rel,
                                                      local_sections)))
                {
+                 bfd_vma l;
+                 const Elf_Internal_Rela *lo16_relocation;
+                 reloc_howto_type *lo16_howto;
+
                  /* Scan ahead to find a matching R_MIPS_LO16
                     relocation.  */
-                 bfd_vma l;
-                 
-                 if (!mips_elf_next_lo16_addend (rel, relend, &l))
+                 lo16_relocation 
+                   = mips_elf_next_lo16_relocation (rel, relend); 
+                 if (lo16_relocation == NULL)
                    return false;
 
+                 /* Obtain the addend kept there.  */
+                 lo16_howto = mips_rtype_to_howto (R_MIPS_LO16);
+                 l = mips_elf_obtain_contents (lo16_howto,
+                                               lo16_relocation,
+                                               input_bfd, contents);
+                 l &= lo16_howto->src_mask;
+
                  /* Save the high-order bit for later.  When we
                     encounter the R_MIPS_LO16 relocation we will need
                     them again.  */
@@ -6552,6 +6571,11 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                            | ((addend & 0x7e00000) >> 16)
                            | (addend & 0x1f));
                }
+             else if (r_type == R_MIPS16_26 
+                      || r_type == R_MIPS16_26)
+               /* The addend is stored without its two least
+                  significant bits (which are always zero.)  */
+               addend <<= 2;
            }
          else
            addend = rel->r_addend;
@@ -6589,7 +6613,12 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
             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)
-           addend >>= 16;
+           addend = mips_elf_high (addend);
+         /* If the relocation is for an R_MIPS_26 relocation, then
+            the two low-order bits are not stored in the object file;
+            they are implicitly zero.  */
+         else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26)
+           addend >>= 2;
 
          if (rela_relocation_p)
            /* If this is a RELA relocation, just update the addend.
@@ -7373,16 +7402,18 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
 
        case R_MIPS_CALL_HI16:
        case R_MIPS_CALL_LO16:
-         /* This symbol requires a global offset table entry.  */
-         if (!mips_elf_record_global_got_symbol (h, info, g))
-           return false;
-
-         /* 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;
-         h->type = STT_FUNC;
+         if (h != NULL)
+           {
+             /* This symbol requires a global offset table entry.  */
+             if (!mips_elf_record_global_got_symbol (h, info, g))
+               return false;
 
+             /* 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;
+             h->type = STT_FUNC;
+           }
          break;
 
        case R_MIPS_GOT16:
This page took 0.025484 seconds and 4 git commands to generate.