static struct bfd_hash_entry *mips_elf_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
static int gptab_compare PARAMS ((const void *, const void *));
-static void mips_elf_relocate_hi16
- PARAMS ((bfd *, Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_byte *,
- bfd_vma));
-static boolean mips_elf_relocate_got_local
- PARAMS ((bfd *, bfd *, asection *, Elf_Internal_Rela *,
- Elf_Internal_Rela *, bfd_byte *, bfd_vma));
-static void mips_elf_relocate_global_got
- PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
static bfd_reloc_status_type mips16_jump_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type mips16_gprel_reloc
return true;
}
-/* Handle a MIPS ELF HI16 reloc. */
-
-static void
-mips_elf_relocate_hi16 (input_bfd, relhi, rello, contents, addend)
- bfd *input_bfd;
- Elf_Internal_Rela *relhi;
- Elf_Internal_Rela *rello;
- bfd_byte *contents;
- bfd_vma addend;
-{
- bfd_vma insn;
- bfd_vma addlo;
-
- insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
-
- addlo = bfd_get_32 (input_bfd, contents + rello->r_offset);
- addlo &= 0xffff;
-
- addend += ((insn & 0xffff) << 16) + addlo;
-
- if ((addlo & 0x8000) != 0)
- addend -= 0x10000;
- if ((addend & 0x8000) != 0)
- addend += 0x10000;
-
- bfd_put_32 (input_bfd,
- (insn & 0xffff0000) | ((addend >> 16) & 0xffff),
- contents + relhi->r_offset);
-}
-
-/* Handle a MIPS ELF local GOT16 reloc. */
-
-static boolean
-mips_elf_relocate_got_local (output_bfd, input_bfd, sgot, relhi, rello,
- contents, addend)
- bfd *output_bfd;
- bfd *input_bfd;
- asection *sgot;
- Elf_Internal_Rela *relhi;
- Elf_Internal_Rela *rello;
- bfd_byte *contents;
- bfd_vma addend;
-{
- unsigned int assigned_gotno;
- unsigned int i;
- bfd_vma insn;
- bfd_vma addlo;
- bfd_vma address;
- bfd_vma hipage;
- bfd_byte *got_contents;
- struct mips_got_info *g;
-
- insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
-
- addlo = bfd_get_32 (input_bfd, contents + rello->r_offset);
- addlo &= 0xffff;
-
- addend += ((insn & 0xffff) << 16) + addlo;
-
- if ((addlo & 0x8000) != 0)
- addend -= 0x10000;
- if ((addend & 0x8000) != 0)
- addend += 0x10000;
-
- /* Get a got entry representing requested hipage. */
- BFD_ASSERT (elf_section_data (sgot) != NULL);
- g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
- BFD_ASSERT (g != NULL);
-
- assigned_gotno = g->assigned_gotno;
- got_contents = sgot->contents;
- hipage = addend & 0xffff0000;
-
- for (i = MIPS_RESERVED_GOTNO; i < assigned_gotno; i++)
- {
- address = bfd_get_32 (input_bfd, got_contents + i * 4);
- if (hipage == (address & 0xffff0000))
- break;
- }
-
- if (i == assigned_gotno)
- {
- if (assigned_gotno >= g->local_gotno)
- {
- (*_bfd_error_handler)
- (_("more got entries are needed for hipage relocations"));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- bfd_put_32 (input_bfd, hipage, got_contents + assigned_gotno * 4);
- ++g->assigned_gotno;
- }
-
- i = - ELF_MIPS_GP_OFFSET (output_bfd) + i * 4;
- bfd_put_32 (input_bfd, (insn & 0xffff0000) | (i & 0xffff),
- contents + relhi->r_offset);
-
- return true;
-}
-
-/* Handle MIPS ELF CALL16 reloc and global GOT16 reloc. */
-
-static void
-mips_elf_relocate_global_got (input_bfd, rel, contents, offset)
- bfd *input_bfd;
- Elf_Internal_Rela *rel;
- bfd_byte *contents;
- bfd_vma offset;
-{
- bfd_vma insn;
-
- insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
- bfd_put_32 (input_bfd,
- (insn & 0xffff0000) | (offset & 0xffff),
- contents + rel->r_offset);
-}
-
/* Returns the GOT section for ABFD. */
static asection *
bfd_vma value;
int bits;
{
- if (value & (1 << (bits - 1)))
+ if (value & ((bfd_vma)1 << (bits - 1)))
/* VALUE is negative. */
value |= ((bfd_vma) - 1) << bits;
bfd_vma value ATTRIBUTE_UNUSED;
{
#ifdef BFD64
- return ((value + (bfd_vma) 0x800080008000) > 48) & 0xffff;
+ return ((value + (bfd_vma) 0x800080008000) >> 48) & 0xffff;
#else
abort ();
return (bfd_vma) -1;
case R_MIPS_LO16:
case R_MIPS_GPREL16:
case R_MIPS_GPREL32:
+ case R_MIPS_LITERAL:
gp0 = _bfd_get_gp_value (input_bfd);
gp = _bfd_get_gp_value (abfd);
break;
case R_MIPS_PC16:
value = mips_elf_sign_extend (addend, 16) + symbol - p;
+ value = (bfd_vma) ((bfd_signed_vma) value / 4);
overflowed_p = mips_elf_overflow_p (value, 16);
break;
Elf_Internal_Rela *rel;
const Elf_Internal_Rela *relend;
bfd_vma addend;
- bfd_vma last_hi16_addend;
boolean use_saved_addend_p = false;
- boolean last_hi16_addend_valid_p = false;
struct elf_backend_data *bed;
bed = get_elf_backend_data (output_bfd);
/* Find the relocation howto for this relocation. */
if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
- /* Some 32-bit code uses R_MIPS_64. In particular, people use
- 64-bit code, but make sure all their addresses are in the
- lowermost or uppermost 32-bit section of the 64-bit address
- space. Thus, when they use an R_MIPS_64 they mean what is
- usually meant by R_MIPS_32, with the exception that the
- stored value is sign-extended to 64 bits. */
- howto = elf_mips_howto_table + R_MIPS_32;
+ {
+ /* Some 32-bit code uses R_MIPS_64. In particular, people use
+ 64-bit code, but make sure all their addresses are in the
+ lowermost or uppermost 32-bit section of the 64-bit address
+ space. Thus, when they use an R_MIPS_64 they mean what is
+ usually meant by R_MIPS_32, with the exception that the
+ stored value is sign-extended to 64 bits. */
+ howto = elf_mips_howto_table + R_MIPS_32;
+
+ /* On big-endian systems, we need to lie about the position
+ of the reloc. */
+ if (bfd_big_endian (input_bfd))
+ rel->r_offset += 4;
+ }
else
howto = mips_rtype_to_howto (r_type);
l &= lo16_howto->src_mask;
l = mips_elf_sign_extend (l, 16);
- /* Save the high-order bit for later. When we
- encounter the R_MIPS_LO16 relocation we will need
- them again. */
addend <<= 16;
- last_hi16_addend = addend;
- last_hi16_addend_valid_p = true;
/* Compute the combined addend. */
addend += l;
}
- else if (r_type == R_MIPS_LO16)
- {
- /* Used the saved HI16 addend. */
- if (!last_hi16_addend_valid_p)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- addend |= last_hi16_addend;
- }
else if (r_type == R_MIPS16_GPREL)
{
/* The addend is scrambled in the object file. See
if (r_type == R_MIPS16_GPREL
|| r_type == R_MIPS_GPREL16
- || r_type == R_MIPS_GPREL32)
+ || r_type == R_MIPS_GPREL32
+ || r_type == R_MIPS_LITERAL)
addend -= (_bfd_get_gp_value (output_bfd)
- _bfd_get_gp_value (input_bfd));
else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26)
go to extreme lengths to support this usage on systems with
only a 32-bit VMA. */
{
-#ifdef BFD64
- /* Just sign-extend the value, and then fall through to the
- normal case, using the R_MIPS_64 howto. That will store
- the 64-bit value into a 64-bit area. */
- value = mips_elf_sign_extend (value, 64);
- howto = elf_mips_howto_table + R_MIPS_64;
-#else /* !BFD64 */
- /* In the 32-bit VMA case, we must handle sign-extension and
- endianness manually. */
bfd_vma sign_bits;
bfd_vma low_bits;
bfd_vma high_bits;
stores. */
if (bfd_big_endian (input_bfd))
{
+ /* Undo what we did above. */
+ rel->r_offset -= 4;
/* Store the sign-bits (which are most significant)
first. */
low_bits = sign_bits;
bfd_put_32 (input_bfd, high_bits,
contents + rel->r_offset + 4);
continue;
-#endif /* !BFD64 */
}
/* Actually perform the relocation. */
if (!h && (r_type == R_MIPS_CALL_LO16
|| r_type == R_MIPS_GOT_LO16
- || r_type == R_MIPS_GOT_DISP
- || r_type == R_MIPS_GOT16))
+ || r_type == R_MIPS_GOT_DISP))
{
/* We may need a local GOT entry for this relocation. We
don't count R_MIPS_GOT_PAGE because we can estimate the
maximum number of pages needed by looking at the size of
- the segment. We don't count R_MIPS_GOT_HI16, or
- R_MIPS_CALL_HI16 because these are always followed by an
- R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16.
+ the segment. Similar comments apply to R_MIPS_GOT16. We
+ don't count R_MIPS_GOT_HI16, or R_MIPS_CALL_HI16 because
+ these are always followed by an R_MIPS_GOT_LO16 or
+ R_MIPS_CALL_LO16.
This estimation is very conservative since we can merge
duplicate entries in the GOT. In order to be less
loadable_size += MIPS_FUNCTION_STUB_SIZE;
/* Assume there are two loadable segments consisting of
- contiguous sections. Is 5 enough? */
+ contiguous sections. Is 5 enough? */
local_gotno = (loadable_size >> 16) + 5;
+ if (IRIX_COMPAT (output_bfd) == ict_irix6)
+ /* It's possible we will need GOT_PAGE entries as well as
+ GOT16 entries. Often, these will be able to share GOT
+ entries, but not always. */
+ local_gotno *= 2;
+
g->local_gotno += local_gotno;
s->_raw_size += local_gotno * MIPS_ELF_GOT_SIZE (dynobj);
if (strip)
{
- _bfd_strip_section_from_output (s);
+ _bfd_strip_section_from_output (info, s);
continue;
}
#define elf_backend_collect true
#define elf_backend_type_change_ok true
#define elf_backend_can_gc_sections true
+#define elf_backend_sign_extend_vma true
#define elf_info_to_howto mips_info_to_howto_rela
#define elf_info_to_howto_rel mips_info_to_howto_rel
#define elf_backend_sym_is_global mips_elf_sym_is_global