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 *,
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
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
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)
&& 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. */
| ((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;
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.
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: