/* MIPS-specific support for 64-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
Ian Lance Taylor, Cygnus Support
Linker support added by Mark Mitchell, CodeSourcery, LLC.
<mark@codesourcery.com>
static bfd_boolean elf64_mips_grok_psinfo
(bfd *, Elf_Internal_Note *);
-extern const bfd_target bfd_elf64_bigmips_vec;
-extern const bfd_target bfd_elf64_littlemips_vec;
+extern const bfd_target mips_elf64_be_vec;
+extern const bfd_target mips_elf64_le_vec;
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
from smaller values. Start with zero, widen, *then* decrement. */
/* No relocation. */
HOWTO (R_MIPS_NONE, /* type */
0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
0x0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ EMPTY_HOWTO (52),
+ EMPTY_HOWTO (53),
+ EMPTY_HOWTO (54),
+ EMPTY_HOWTO (55),
+ EMPTY_HOWTO (56),
+ EMPTY_HOWTO (57),
+ EMPTY_HOWTO (58),
+ EMPTY_HOWTO (59),
+
+ HOWTO (R_MIPS_PC21_S2, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 21, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC21_S2", /* name */
+ TRUE, /* partial_inplace */
+ 0x001fffff, /* src_mask */
+ 0x001fffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PC26_S2, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC26_S2", /* name */
+ TRUE, /* partial_inplace */
+ 0x03ffffff, /* src_mask */
+ 0x03ffffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PC18_S3, /* type */
+ 3, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 18, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC18_S3", /* name */
+ TRUE, /* partial_inplace */
+ 0x0003ffff, /* src_mask */
+ 0x0003ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PC19_S2, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 19, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC19_S2", /* name */
+ TRUE, /* partial_inplace */
+ 0x0007ffff, /* src_mask */
+ 0x0007ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PCHI16, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PCHI16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PCLO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PCLO16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
};
/* The relocation table used for SHT_RELA sections. */
/* No relocation. */
HOWTO (R_MIPS_NONE, /* type */
0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
0x0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ EMPTY_HOWTO (52),
+ EMPTY_HOWTO (53),
+ EMPTY_HOWTO (54),
+ EMPTY_HOWTO (55),
+ EMPTY_HOWTO (56),
+ EMPTY_HOWTO (57),
+ EMPTY_HOWTO (58),
+ EMPTY_HOWTO (59),
+
+ HOWTO (R_MIPS_PC21_S2, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 21, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC21_S2", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x001fffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PC26_S2, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC26_S2", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x03ffffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PC18_S3, /* type */
+ 3, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 18, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC18_S3", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0003ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PC19_S2, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 19, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC19_S2", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0007ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PCHI16, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PCHI16", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_PCLO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_PCLO16", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
};
static reloc_howto_type mips16_elf64_howto_table_rel[] =
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ /* MIPS16 16-bit PC-relative branch offset. */
+ HOWTO (R_MIPS16_PC16_S1, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS16_PC16_S1", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
};
static reloc_howto_type mips16_elf64_howto_table_rela[] =
0, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ /* MIPS16 16-bit PC-relative branch offset. */
+ HOWTO (R_MIPS16_PC16_S1, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS16_PC16_S1", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
};
static reloc_howto_type micromips_elf64_howto_table_rel[] =
0x0, /* src_mask */
0x0, /* dst_mask */
FALSE); /* pcrel_offset */
+
+/* Used in EH tables. */
+static reloc_howto_type elf_mips_eh_howto =
+ HOWTO (R_MIPS_EH, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_EH", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE); /* pcrel_offset */
+
\f
/* Swap in a MIPS 64-bit Rel reloc. */
{ BFD_RELOC_MIPS_TLS_TPREL32, R_MIPS_TLS_TPREL32 },
{ BFD_RELOC_MIPS_TLS_TPREL64, R_MIPS_TLS_TPREL64 },
{ BFD_RELOC_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_TPREL_HI16 },
- { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 }
+ { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 },
+ { BFD_RELOC_MIPS_21_PCREL_S2, R_MIPS_PC21_S2 },
+ { BFD_RELOC_MIPS_26_PCREL_S2, R_MIPS_PC26_S2 },
+ { BFD_RELOC_MIPS_18_PCREL_S3, R_MIPS_PC18_S3 },
+ { BFD_RELOC_MIPS_19_PCREL_S2, R_MIPS_PC19_S2 },
+ { BFD_RELOC_HI16_S_PCREL, R_MIPS_PCHI16 },
+ { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 }
};
static const struct elf_reloc_map mips16_reloc_map[] =
R_MIPS16_TLS_DTPREL_LO16 - R_MIPS16_min },
{ BFD_RELOC_MIPS16_TLS_GOTTPREL, R_MIPS16_TLS_GOTTPREL - R_MIPS16_min },
{ BFD_RELOC_MIPS16_TLS_TPREL_HI16, R_MIPS16_TLS_TPREL_HI16 - R_MIPS16_min },
- { BFD_RELOC_MIPS16_TLS_TPREL_LO16, R_MIPS16_TLS_TPREL_LO16 - R_MIPS16_min }
+ { BFD_RELOC_MIPS16_TLS_TPREL_LO16, R_MIPS16_TLS_TPREL_LO16 - R_MIPS16_min },
+ { BFD_RELOC_MIPS16_16_PCREL_S1, R_MIPS16_PC16_S1 - R_MIPS16_min }
};
static const struct elf_reloc_map micromips_reloc_map[] =
return &elf_mips_gnu_vtentry_howto;
case BFD_RELOC_32_PCREL:
return &elf_mips_gnu_pcrel32;
+ case BFD_RELOC_MIPS_EH:
+ return &elf_mips_eh_howto;
case BFD_RELOC_MIPS_COPY:
return &elf_mips_copy_howto;
case BFD_RELOC_MIPS_JUMP_SLOT:
return &elf_mips_gnu_rela16_s2;
if (strcasecmp (elf_mips_gnu_pcrel32.name, r_name) == 0)
return &elf_mips_gnu_pcrel32;
+ if (strcasecmp (elf_mips_eh_howto.name, r_name) == 0)
+ return &elf_mips_eh_howto;
if (strcasecmp (elf_mips_copy_howto.name, r_name) == 0)
return &elf_mips_copy_howto;
if (strcasecmp (elf_mips_jump_slot_howto.name, r_name) == 0)
return &elf_mips_gnu_rel16_s2;
case R_MIPS_PC32:
return &elf_mips_gnu_pcrel32;
+ case R_MIPS_EH:
+ return &elf_mips_eh_howto;
case R_MIPS_COPY:
return &elf_mips_copy_howto;
case R_MIPS_JUMP_SLOT:
else
return &mips16_elf64_howto_table_rel[r_type - R_MIPS16_min];
}
- BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
+ if (r_type >= R_MIPS_max)
+ {
+ _bfd_error_handler (_("unrecognised MIPS reloc number: %d"), r_type);
+ bfd_set_error (bfd_error_bad_value);
+ r_type = R_MIPS_NONE;
+ }
if (rela_p)
return &mips_elf64_howto_table_rela[r_type];
else
static irix_compat_t
elf64_mips_irix_compat (bfd *abfd)
{
- if ((abfd->xvec == &bfd_elf64_bigmips_vec)
- || (abfd->xvec == &bfd_elf64_littlemips_vec))
+ if ((abfd->xvec == &mips_elf64_be_vec)
+ || (abfd->xvec == &mips_elf64_le_vec))
return ict_irix6;
else
return ict_none;
#define elf_backend_collect TRUE
#define elf_backend_type_change_ok TRUE
#define elf_backend_can_gc_sections TRUE
+#define elf_backend_gc_mark_extra_sections \
+ _bfd_mips_elf_gc_mark_extra_sections
#define elf_info_to_howto mips_elf64_info_to_howto_rela
#define elf_info_to_howto_rel mips_elf64_info_to_howto_rel
#define elf_backend_object_p mips_elf64_object_p
#define elf_backend_grok_psinfo elf64_mips_grok_psinfo
#define elf_backend_got_header_size (8 * MIPS_RESERVED_GOTNO)
+#define elf_backend_want_dynrelro 1
/* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
work better/work only in RELA, so we default to this. */
#define elf_backend_sign_extend_vma TRUE
#define elf_backend_write_section _bfd_mips_elf_write_section
+#define elf_backend_sort_relocs_p _bfd_mips_elf_sort_relocs_p
/* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit
MIPS-specific function only applies to IRIX5, which had no 64-bit
#define bfd_elf64_bfd_relax_section _bfd_mips_relax_section
#define bfd_elf64_mkobject _bfd_mips_elf_mkobject
-/* MIPS ELF64 archive functions. */
-#define bfd_elf64_archive_functions
-extern bfd_boolean bfd_elf64_archive_slurp_armap
- (bfd *);
-extern bfd_boolean bfd_elf64_archive_write_armap
- (bfd *, unsigned int, struct orl *, unsigned int, int);
-#define bfd_elf64_archive_slurp_extended_name_table \
- _bfd_archive_coff_slurp_extended_name_table
-#define bfd_elf64_archive_construct_extended_name_table \
- _bfd_archive_coff_construct_extended_name_table
-#define bfd_elf64_archive_truncate_arname \
- _bfd_archive_coff_truncate_arname
-#define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
-#define bfd_elf64_archive_write_ar_hdr _bfd_archive_coff_write_ar_hdr
-#define bfd_elf64_archive_openr_next_archived_file \
- _bfd_archive_coff_openr_next_archived_file
-#define bfd_elf64_archive_get_elt_at_index \
- _bfd_archive_coff_get_elt_at_index
-#define bfd_elf64_archive_generic_stat_arch_elt \
- _bfd_archive_coff_generic_stat_arch_elt
-#define bfd_elf64_archive_update_armap_timestamp \
- _bfd_archive_coff_update_armap_timestamp
-
/* The SGI style (n)64 NewABI. */
-#define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
+#define TARGET_LITTLE_SYM mips_elf64_le_vec
#define TARGET_LITTLE_NAME "elf64-littlemips"
-#define TARGET_BIG_SYM bfd_elf64_bigmips_vec
+#define TARGET_BIG_SYM mips_elf64_be_vec
#define TARGET_BIG_NAME "elf64-bigmips"
#define ELF_MAXPAGESIZE 0x10000
#undef ELF_MAXPAGESIZE
#undef ELF_COMMONPAGESIZE
-#define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec
+#define TARGET_LITTLE_SYM mips_elf64_trad_le_vec
#define TARGET_LITTLE_NAME "elf64-tradlittlemips"
-#define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec
+#define TARGET_BIG_SYM mips_elf64_trad_be_vec
#define TARGET_BIG_NAME "elf64-tradbigmips"
#define ELF_MAXPAGESIZE 0x10000
#undef TARGET_BIG_SYM
#undef TARGET_BIG_NAME
-#define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_freebsd_vec
+#define TARGET_LITTLE_SYM mips_elf64_tradfbsd_le_vec
#define TARGET_LITTLE_NAME "elf64-tradlittlemips-freebsd"
-#define TARGET_BIG_SYM bfd_elf64_tradbigmips_freebsd_vec
+#define TARGET_BIG_SYM mips_elf64_tradfbsd_be_vec
#define TARGET_BIG_NAME "elf64-tradbigmips-freebsd"
#undef ELF_OSABI
#define ELF_OSABI ELFOSABI_FREEBSD
-/* The kernel recognizes executables as valid only if they carry a
- "FreeBSD" label in the ELF header. So we put this label on all
- executables and (for simplicity) also all other object files. */
-
-static void
-elf_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
-{
- _bfd_elf_set_osabi (abfd, info);
-}
-
-#undef elf_backend_post_process_headers
-#define elf_backend_post_process_headers elf_fbsd_post_process_headers
#undef elf64_bed
#define elf64_bed elf64_fbsd_tradbed