summaryrefslogtreecommitdiffstats
path: root/binutils-2.24/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-2.24/bfd')
-rw-r--r--binutils-2.24/bfd/ChangeLog66
-rw-r--r--binutils-2.24/bfd/aoutx.h6
-rw-r--r--binutils-2.24/bfd/archures.c6
-rw-r--r--binutils-2.24/bfd/bfd-in2.h12
-rw-r--r--binutils-2.24/bfd/config.bfd2
-rw-r--r--binutils-2.24/bfd/cpu-mips.c12
-rw-r--r--binutils-2.24/bfd/elf32-mips.c104
-rw-r--r--binutils-2.24/bfd/elf64-mips.c198
-rw-r--r--binutils-2.24/bfd/elfn32-mips.c198
-rw-r--r--binutils-2.24/bfd/elfxx-mips.c1396
-rw-r--r--binutils-2.24/bfd/elfxx-mips.h4
-rw-r--r--binutils-2.24/bfd/libbfd.h4
-rw-r--r--binutils-2.24/bfd/reloc.c11
13 files changed, 1695 insertions, 324 deletions
diff --git a/binutils-2.24/bfd/ChangeLog b/binutils-2.24/bfd/ChangeLog
index 2c4719c..b225e10 100644
--- a/binutils-2.24/bfd/ChangeLog
+++ b/binutils-2.24/bfd/ChangeLog
@@ -1,3 +1,55 @@
+2014-05-07 Andrew Bennett <andrew.bennett@imgtec.com>
+
+ * aoutx.h (NAME (aout, machine_type)): Add mips32r3, mips64r3,
+ mips32r5 and mips64r5.
+ * archures.c (bfd_architecture): Likewise.
+ * bfd-in2.h (bfd_architecture): Likewise.
+ * cpu-mips.c (arch_info_struct): Likewise.
+ * elfxx-mips.c (mips_set_isa_flags): Likewise.
+
+2014-05-06 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * elfxx-mips.h (elfxx-mips.h): Declare.
+ * elfxx-mips.c (mips_elf_merge_obj_attributes): Use it to report
+ Tag_GNU_MIPS_ABI_FP mismatches.
+ (_bfd_mips_fp_abi_string): New function.
+
+2014-04-17 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * elfxx-mips.c (struct mips_got_info): Delete assigned_gotno
+ field. Add assigned_low_gotno and assigned_high_gotno fields.
+ (mips_elf_create_local_got_entry): Update out-of-space condition.
+ Set index of new GOT entry to assigned_low_gotno if required by
+ the current relocation, else set it to assigned_high_gotno.
+ (mips_elf_set_global_gotidx): Replace uses of assigned_gotno
+ with assigned_low_gotno.
+ (mips_elf_multi_got): Initialize assigned_low_gotno and
+ assigned_high_gotno in secondary GOTs. Use assigned_low_gotno
+ in place of assigned_gotno when handling global GOT entries.
+ (mips_elf_lay_out_got): Initialize assigned_low_gotno and
+ assigned_high_gotno.
+ (_bfd_mips_elf_finish_dynamic_sections): Account for a possible
+ gap in the middle of local GOT space.
+
+2014-03-04 Heiher <r@hev.cc>
+
+ * elfxx-mips.c (mips_set_isa_flags): Use E_MIPS_ARCH_64R2 for
+ Loongson-3A.
+ (mips_mach_extensions): Make bfd_mach_mips_loongson_3a an
+ extension of bfd_mach_mipsisa64r2.
+
+2014-02-18 Jack Carter <jack.carter@imgtec.com>
+
+ * elfxx-mips.c(_bfd_mips_elf_modify_segment_map): Deleted hard coding of
+ PT_DYNAMIC segment flags.
+
+2014-01-16 Alan Modra <amodra@gmail.com>
+
+ * elfxx-mips.c (mips_elf_record_got_page_entry): Pass in a
+ mips_elf_traverse_got_arg* rather than mips_got_info*.
+ Adjust caller. Alloc on output_bfd rather than symbol section
+ owner.
+
2013-12-02 Tristan Gingold <gingold@adacore.com>
* configure.in: Bump version to 2.24
@@ -219,6 +271,20 @@
* elf.c (copy_elf_program_header): Only consider SEC_ALLOC sections
when finding lowest_section.
+2013-10-14 Chao-ying Fu <Chao-ying.Fu@imgtec.com>
+
+ * elfxx-mips.c (mips_elf_obj_tdata): Add abi_msa_bfd.
+ (mips_elf_merge_obj_attributes): Set abi_msa_bfd to the first object
+ file that has a Tag_GNU_MIPS_ABI_MSA attribute.
+ Merge Tag_GNU_MIPS_ABI_MSA attributes.
+
+2013-10-13 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * elfxx-mips.c (mips_use_local_got_p): New function.
+ (mips_elf_count_got_symbols, mips_elf_calculate_relocation): Use it.
+ (_bfd_mips_elf_check_relocs): Set pointer_equality_needed for
+ GOT and absolute references.
+
2013-10-09 Roland McGrath <mcgrathr@google.com>
* elf64-alpha.c (elf64_alpha_relax_tls_get_addr): Cast switch
diff --git a/binutils-2.24/bfd/aoutx.h b/binutils-2.24/bfd/aoutx.h
index 1e0ad38..e54366c 100644
--- a/binutils-2.24/bfd/aoutx.h
+++ b/binutils-2.24/bfd/aoutx.h
@@ -793,9 +793,15 @@ NAME (aout, machine_type) (enum bfd_architecture arch,
case bfd_mach_mips16:
case bfd_mach_mipsisa32:
case bfd_mach_mipsisa32r2:
+ case bfd_mach_mipsisa32r3:
+ case bfd_mach_mipsisa32r5:
+ case bfd_mach_mipsisa32r6:
case bfd_mach_mips5:
case bfd_mach_mipsisa64:
case bfd_mach_mipsisa64r2:
+ case bfd_mach_mipsisa64r3:
+ case bfd_mach_mipsisa64r5:
+ case bfd_mach_mipsisa64r6:
case bfd_mach_mips_sb1:
case bfd_mach_mips_xlr:
/* FIXME: These should be MIPS3, MIPS4, MIPS16, MIPS32, etc. */
diff --git a/binutils-2.24/bfd/archures.c b/binutils-2.24/bfd/archures.c
index 97c540a..be78a22 100644
--- a/binutils-2.24/bfd/archures.c
+++ b/binutils-2.24/bfd/archures.c
@@ -180,8 +180,14 @@ DESCRIPTION
.#define bfd_mach_mips_xlr 887682 {* decimal 'XLR' *}
.#define bfd_mach_mipsisa32 32
.#define bfd_mach_mipsisa32r2 33
+.#define bfd_mach_mipsisa32r3 34
+.#define bfd_mach_mipsisa32r5 36
+.#define bfd_mach_mipsisa32r6 37
.#define bfd_mach_mipsisa64 64
.#define bfd_mach_mipsisa64r2 65
+.#define bfd_mach_mipsisa64r3 66
+.#define bfd_mach_mipsisa64r5 68
+.#define bfd_mach_mipsisa64r6 69
.#define bfd_mach_mips_micromips 96
. bfd_arch_i386, {* Intel 386 *}
.#define bfd_mach_i386_intel_syntax (1 << 0)
diff --git a/binutils-2.24/bfd/bfd-in2.h b/binutils-2.24/bfd/bfd-in2.h
index 756af87..3097f04 100644
--- a/binutils-2.24/bfd/bfd-in2.h
+++ b/binutils-2.24/bfd/bfd-in2.h
@@ -1935,8 +1935,14 @@ enum bfd_architecture
#define bfd_mach_mips_xlr 887682 /* decimal 'XLR' */
#define bfd_mach_mipsisa32 32
#define bfd_mach_mipsisa32r2 33
+#define bfd_mach_mipsisa32r3 34
+#define bfd_mach_mipsisa32r5 36
+#define bfd_mach_mipsisa32r6 37
#define bfd_mach_mipsisa64 64
#define bfd_mach_mipsisa64r2 65
+#define bfd_mach_mipsisa64r3 66
+#define bfd_mach_mipsisa64r5 68
+#define bfd_mach_mipsisa64r6 69
#define bfd_mach_mips_micromips 96
bfd_arch_i386, /* Intel 386 */
#define bfd_mach_i386_intel_syntax (1 << 0)
@@ -2896,6 +2902,12 @@ to compensate for the borrow when the low bits are added. */
BFD_RELOC_MICROMIPS_10_PCREL_S1,
BFD_RELOC_MICROMIPS_16_PCREL_S1,
+/* MIPS PC-relative relocations. */
+ BFD_RELOC_MIPS_21_PCREL_S2,
+ BFD_RELOC_MIPS_26_PCREL_S2,
+ BFD_RELOC_MIPS_18_PCREL_S3,
+ BFD_RELOC_MIPS_19_PCREL_S2,
+
/* microMIPS versions of generic BFD relocs. */
BFD_RELOC_MICROMIPS_GPREL16,
BFD_RELOC_MICROMIPS_HI16,
diff --git a/binutils-2.24/bfd/config.bfd b/binutils-2.24/bfd/config.bfd
index 5324d39..d1643cc 100644
--- a/binutils-2.24/bfd/config.bfd
+++ b/binutils-2.24/bfd/config.bfd
@@ -1024,7 +1024,7 @@ case "${targ}" in
targ_defvec=bfd_elf32_tradlittlemips_vec
targ_selvecs="bfd_elf32_tradbigmips_vec bfd_elf32_ntradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf64_tradbigmips_vec bfd_elf64_tradlittlemips_vec"
;;
- mips*-sde-elf* | mips*-mti-elf*)
+ mips*-sde-elf* | mips*-mti-elf* | mips*-img-elf*)
targ_defvec=bfd_elf32_tradbigmips_vec
targ_selvecs="bfd_elf32_tradlittlemips_vec bfd_elf32_ntradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf64_tradbigmips_vec bfd_elf64_tradlittlemips_vec"
;;
diff --git a/binutils-2.24/bfd/cpu-mips.c b/binutils-2.24/bfd/cpu-mips.c
index 59a7c16..fc37cbe 100644
--- a/binutils-2.24/bfd/cpu-mips.c
+++ b/binutils-2.24/bfd/cpu-mips.c
@@ -89,8 +89,14 @@ enum
I_mips5,
I_mipsisa32,
I_mipsisa32r2,
+ I_mipsisa32r3,
+ I_mipsisa32r5,
+ I_mipsisa32r6,
I_mipsisa64,
I_mipsisa64r2,
+ I_mipsisa64r3,
+ I_mipsisa64r5,
+ I_mipsisa64r6,
I_sb1,
I_loongson_2e,
I_loongson_2f,
@@ -133,8 +139,14 @@ static const bfd_arch_info_type arch_info_struct[] =
N (64, 64, bfd_mach_mips5, "mips:mips5", FALSE, NN(I_mips5)),
N (32, 32, bfd_mach_mipsisa32, "mips:isa32", FALSE, NN(I_mipsisa32)),
N (32, 32, bfd_mach_mipsisa32r2,"mips:isa32r2", FALSE, NN(I_mipsisa32r2)),
+ N (32, 32, bfd_mach_mipsisa32r3,"mips:isa32r3", FALSE, NN(I_mipsisa32r3)),
+ N (32, 32, bfd_mach_mipsisa32r5,"mips:isa32r5", FALSE, NN(I_mipsisa32r5)),
+ N (32, 32, bfd_mach_mipsisa32r6,"mips:isa32r6", FALSE, NN(I_mipsisa32r6)),
N (64, 64, bfd_mach_mipsisa64, "mips:isa64", FALSE, NN(I_mipsisa64)),
N (64, 64, bfd_mach_mipsisa64r2,"mips:isa64r2", FALSE, NN(I_mipsisa64r2)),
+ N (64, 64, bfd_mach_mipsisa64r3,"mips:isa64r3", FALSE, NN(I_mipsisa64r3)),
+ N (64, 64, bfd_mach_mipsisa64r5,"mips:isa64r5", FALSE, NN(I_mipsisa64r5)),
+ N (64, 64, bfd_mach_mipsisa64r6,"mips:isa64r6", FALSE, NN(I_mipsisa64r6)),
N (64, 64, bfd_mach_mips_sb1, "mips:sb1", FALSE, NN(I_sb1)),
N (64, 64, bfd_mach_mips_loongson_2e, "mips:loongson_2e", FALSE, NN(I_loongson_2e)),
N (64, 64, bfd_mach_mips_loongson_2f, "mips:loongson_2f", FALSE, NN(I_loongson_2f)),
diff --git a/binutils-2.24/bfd/elf32-mips.c b/binutils-2.24/bfd/elf32-mips.c
index eec2ef7..c9c4cc3 100644
--- a/binutils-2.24/bfd/elf32-mips.c
+++ b/binutils-2.24/bfd/elf32-mips.c
@@ -717,6 +717,100 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
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_signed, /* 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 reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This
@@ -1906,7 +2000,13 @@ static const struct elf_reloc_map mips_reloc_map[] =
{ 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[] =
@@ -2316,6 +2416,8 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
#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_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
diff --git a/binutils-2.24/bfd/elf64-mips.c b/binutils-2.24/bfd/elf64-mips.c
index a0c5cc5..c090fb7 100644
--- a/binutils-2.24/bfd/elf64-mips.c
+++ b/binutils-2.24/bfd/elf64-mips.c
@@ -807,6 +807,100 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
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_signed, /* 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. */
@@ -1494,6 +1588,100 @@ static reloc_howto_type mips_elf64_howto_table_rela[] =
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_signed, /* 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[] =
@@ -3204,7 +3392,13 @@ static const struct elf_reloc_map mips_reloc_map[] =
{ 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[] =
@@ -4187,6 +4381,8 @@ const struct elf_size_info mips_elf64_size_info =
#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
diff --git a/binutils-2.24/bfd/elfn32-mips.c b/binutils-2.24/bfd/elfn32-mips.c
index 2daf79e..2fb019f 100644
--- a/binutils-2.24/bfd/elfn32-mips.c
+++ b/binutils-2.24/bfd/elfn32-mips.c
@@ -771,6 +771,100 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
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_signed, /* 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. */
@@ -1459,6 +1553,100 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
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_signed, /* 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 elf_mips16_howto_table_rel[] =
@@ -3019,7 +3207,13 @@ static const struct elf_reloc_map mips_reloc_map[] =
{ 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[] =
@@ -3411,6 +3605,8 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
#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_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
diff --git a/binutils-2.24/bfd/elfxx-mips.c b/binutils-2.24/bfd/elfxx-mips.c
index d7498e1..4b8bca7 100644
--- a/binutils-2.24/bfd/elfxx-mips.c
+++ b/binutils-2.24/bfd/elfxx-mips.c
@@ -168,8 +168,10 @@ struct mips_got_info
unsigned int page_gotno;
/* The number of relocations needed for the GOT entries. */
unsigned int relocs;
- /* The number of local .got entries we have used. */
- unsigned int assigned_gotno;
+ /* The first unused local .got entry. */
+ unsigned int assigned_low_gotno;
+ /* The last unused local .got entry. */
+ unsigned int assigned_high_gotno;
/* A hash table holding members of the got. */
struct htab *got_entries;
/* A hash table holding mips_got_page_ref structures. */
@@ -542,6 +544,13 @@ struct mips_elf_obj_tdata
/* Input BFD providing Tag_GNU_MIPS_ABI_FP attribute for output. */
bfd *abi_fp_bfd;
+ /* Input BFD providing Tag_GNU_MIPS_ABI_MSA attribute for output. */
+ bfd *abi_msa_bfd;
+
+ /* The abiflags for this object. */
+ Elf_Internal_ABIFlags_v0 abiflags;
+ bfd_boolean abiflags_valid;
+
/* The GOT requirements of input bfds. */
struct mips_got_info *got;
@@ -771,6 +780,10 @@ static bfd *reldyn_sorting_bfd;
#define PIC_OBJECT_P(abfd) \
((elf_elfheader (abfd)->e_flags & EF_MIPS_PIC) != 0)
+/* Nonzero if ABFD is using the O32 ABI. */
+#define ABI_O32_P(abfd) \
+ ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_O32)
+
/* Nonzero if ABFD is using the N32 ABI. */
#define ABI_N32_P(abfd) \
((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
@@ -786,6 +799,11 @@ static bfd *reldyn_sorting_bfd;
#define MICROMIPS_P(abfd) \
((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
+/* Nonzero if ABFD is MIPS R6. */
+#define MIPSR6_P(abfd) \
+ ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6 \
+ || (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R6)
+
/* The IRIX compatibility level we are striving for. */
#define IRIX_COMPAT(abfd) \
(get_elf_backend_data (abfd)->elf_backend_mips_irix_compat (abfd))
@@ -803,6 +821,10 @@ static bfd *reldyn_sorting_bfd;
#define MIPS_ELF_OPTIONS_SECTION_NAME_P(NAME) \
(strcmp (NAME, ".MIPS.options") == 0 || strcmp (NAME, ".options") == 0)
+/* True if NAME is the recognized name of any SHT_MIPS_ABIFLAGS section. */
+#define MIPS_ELF_ABIFLAGS_SECTION_NAME_P(NAME) \
+ (strcmp (NAME, ".MIPS.abiflags") == 0)
+
/* Whether the section is readonly. */
#define MIPS_ELF_READONLY_SECTION(sec) \
((sec->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY)) \
@@ -1083,6 +1105,14 @@ static const bfd_vma mips_exec_plt_entry[] =
0x03200008 /* jr $25 */
};
+static const bfd_vma mipsr6_exec_plt_entry[] =
+{
+ 0x3c0f0000, /* lui $15, %hi(.got.plt entry) */
+ 0x01f90000, /* l[wd] $25, %lo(.got.plt entry)($15) */
+ 0x25f80000, /* addiu $24, $15, %lo(.got.plt entry) */
+ 0x03200009 /* jr $25 */
+};
+
/* The format of subsequent MIPS16 o32 PLT entries. We use v0 ($2)
and v1 ($3) as temporaries because t8 ($24) and t9 ($25) are not
directly addressable. */
@@ -2163,7 +2193,8 @@ hi16_reloc_p (int r_type)
{
return (r_type == R_MIPS_HI16
|| r_type == R_MIPS16_HI16
- || r_type == R_MICROMIPS_HI16);
+ || r_type == R_MICROMIPS_HI16
+ || r_type == R_MIPS_PCHI16);
}
static inline bfd_boolean
@@ -2171,7 +2202,8 @@ lo16_reloc_p (int r_type)
{
return (r_type == R_MIPS_LO16
|| r_type == R_MIPS16_LO16
- || r_type == R_MICROMIPS_LO16);
+ || r_type == R_MICROMIPS_LO16
+ || r_type == R_MIPS_PCLO16);
}
static inline bfd_boolean
@@ -2189,6 +2221,13 @@ jal_reloc_p (int r_type)
}
static inline bfd_boolean
+aligned_pcrel_reloc_p (int r_type)
+{
+ return (r_type == R_MIPS_PC18_S3
+ || r_type == R_MIPS_PC19_S2);
+}
+
+static inline bfd_boolean
micromips_branch_reloc_p (int r_type)
{
return (r_type == R_MICROMIPS_26_S1
@@ -2659,6 +2698,46 @@ bfd_mips_elf_swap_options_out (bfd *abfd, const Elf_Internal_Options *in,
H_PUT_16 (abfd, in->section, ex->section);
H_PUT_32 (abfd, in->info, ex->info);
}
+
+/* Swap in an abiflags structure. */
+
+void
+bfd_mips_elf_swap_abiflags_v0_in (bfd *abfd,
+ const Elf_External_ABIFlags_v0 *ex,
+ Elf_Internal_ABIFlags_v0 *in)
+{
+ in->version = H_GET_16 (abfd, ex->version);
+ in->isa_level = H_GET_8 (abfd, ex->isa_level);
+ in->isa_rev = H_GET_8 (abfd, ex->isa_rev);
+ in->gpr_size = H_GET_8 (abfd, ex->gpr_size);
+ in->cpr1_size = H_GET_8 (abfd, ex->cpr1_size);
+ in->cpr2_size = H_GET_8 (abfd, ex->cpr2_size);
+ in->fp_abi = H_GET_8 (abfd, ex->fp_abi);
+ in->isa_ext = H_GET_32 (abfd, ex->isa_ext);
+ in->ases = H_GET_32 (abfd, ex->ases);
+ in->flags1 = H_GET_32 (abfd, ex->flags1);
+ in->flags2 = H_GET_32 (abfd, ex->flags2);
+}
+
+/* Swap out an abiflags structure. */
+
+void
+bfd_mips_elf_swap_abiflags_v0_out (bfd *abfd,
+ const Elf_Internal_ABIFlags_v0 *in,
+ Elf_External_ABIFlags_v0 *ex)
+{
+ H_PUT_16 (abfd, in->version, ex->version);
+ H_PUT_8 (abfd, in->isa_level, ex->isa_level);
+ H_PUT_8 (abfd, in->isa_rev, ex->isa_rev);
+ H_PUT_8 (abfd, in->gpr_size, ex->gpr_size);
+ H_PUT_8 (abfd, in->cpr1_size, ex->cpr1_size);
+ H_PUT_8 (abfd, in->cpr2_size, ex->cpr2_size);
+ H_PUT_8 (abfd, in->fp_abi, ex->fp_abi);
+ H_PUT_32 (abfd, in->isa_ext, ex->isa_ext);
+ H_PUT_32 (abfd, in->ases, ex->ases);
+ H_PUT_32 (abfd, in->flags1, ex->flags1);
+ H_PUT_32 (abfd, in->flags2, ex->flags2);
+}
/* This function is called via qsort() to sort the dynamic relocation
entries by increasing r_symndx value. */
@@ -3632,7 +3711,7 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
if (entry)
return entry;
- if (g->assigned_gotno >= g->local_gotno)
+ if (g->assigned_low_gotno > g->assigned_high_gotno)
{
/* We didn't allocate enough space in the GOT. */
(*_bfd_error_handler)
@@ -3645,7 +3724,14 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
if (!entry)
return NULL;
- lookup.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
+ if (got16_reloc_p (r_type)
+ || call16_reloc_p (r_type)
+ || got_page_reloc_p (r_type)
+ || got_disp_reloc_p (r_type))
+ lookup.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_low_gotno++;
+ else
+ lookup.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_high_gotno--;
+
*entry = lookup;
*loc = entry;
@@ -4086,9 +4172,10 @@ mips_elf_pages_for_range (const struct mips_got_page_range *range)
/* Record that G requires a page entry that can reach SEC + ADDEND. */
static bfd_boolean
-mips_elf_record_got_page_entry (struct mips_got_info *g,
+mips_elf_record_got_page_entry (struct mips_elf_traverse_got_arg *arg,
asection *sec, bfd_signed_vma addend)
{
+ struct mips_got_info *g = arg->g;
struct mips_got_page_entry lookup, *entry;
struct mips_got_page_range **range_ptr, *range;
bfd_vma old_pages, new_pages;
@@ -4105,7 +4192,7 @@ mips_elf_record_got_page_entry (struct mips_got_info *g,
entry = (struct mips_got_page_entry *) *loc;
if (!entry)
{
- entry = bfd_zalloc (sec->owner, sizeof (*entry));
+ entry = bfd_zalloc (arg->info->output_bfd, sizeof (*entry));
if (!entry)
return FALSE;
@@ -4125,7 +4212,7 @@ mips_elf_record_got_page_entry (struct mips_got_info *g,
range = *range_ptr;
if (!range || addend < range->min_addend - 0xffff)
{
- range = bfd_zalloc (sec->owner, sizeof (*range));
+ range = bfd_zalloc (arg->info->output_bfd, sizeof (*range));
if (!range)
return FALSE;
@@ -4245,7 +4332,7 @@ mips_elf_resolve_got_page_ref (void **refp, void *data)
else
addend = isym->st_value + ref->addend;
}
- if (!mips_elf_record_got_page_entry (arg->g, sec, addend))
+ if (!mips_elf_record_got_page_entry (arg, sec, addend))
{
arg->g = NULL;
return 0;
@@ -4299,6 +4386,36 @@ mips_elf_resolve_final_got_entries (struct bfd_link_info *info,
return TRUE;
}
+/* Return true if a GOT entry for H should live in the local rather than
+ global GOT area. */
+
+static bfd_boolean
+mips_use_local_got_p (struct bfd_link_info *info,
+ struct mips_elf_link_hash_entry *h)
+{
+ /* Symbols that aren't in the dynamic symbol table must live in the
+ local GOT. This includes symbols that are completely undefined
+ and which therefore don't bind locally. We'll report undefined
+ symbols later if appropriate. */
+ if (h->root.dynindx == -1)
+ return TRUE;
+
+ /* Symbols that bind locally can (and in the case of forced-local
+ symbols, must) live in the local GOT. */
+ if (h->got_only_for_calls
+ ? SYMBOL_CALLS_LOCAL (info, &h->root)
+ : SYMBOL_REFERENCES_LOCAL (info, &h->root))
+ return TRUE;
+
+ /* If this is an executable that must provide a definition of the symbol,
+ either though PLTs or copy relocations, then that address should go in
+ the local rather than global GOT. */
+ if (info->executable && h->has_static_relocs)
+ return TRUE;
+
+ return FALSE;
+}
+
/* A mips_elf_link_hash_traverse callback for which DATA points to the
link_info structure. Decide whether the hash entry needs an entry in
the global part of the primary GOT, setting global_got_area accordingly.
@@ -4318,18 +4435,8 @@ mips_elf_count_got_symbols (struct mips_elf_link_hash_entry *h, void *data)
if (h->global_got_area != GGA_NONE)
{
/* Make a final decision about whether the symbol belongs in the
- local or global GOT. Symbols that bind locally can (and in the
- case of forced-local symbols, must) live in the local GOT.
- Those that are aren't in the dynamic symbol table must also
- live in the local GOT.
-
- Note that the former condition does not always imply the
- latter: symbols do not bind locally if they are completely
- undefined. We'll report undefined symbols later if appropriate. */
- if (h->root.dynindx == -1
- || (h->got_only_for_calls
- ? SYMBOL_CALLS_LOCAL (info, &h->root)
- : SYMBOL_REFERENCES_LOCAL (info, &h->root)))
+ local or global GOT. */
+ if (mips_use_local_got_p (info, h))
/* The symbol belongs in the local GOT. We no longer need this
entry if it was only used for relocations; those relocations
will be against the null or section symbol instead of H. */
@@ -4604,12 +4711,12 @@ mips_elf_set_global_gotidx (void **entryp, void *data)
&& entry->symndx == -1
&& entry->d.h->global_got_area != GGA_NONE)
{
- if (!mips_elf_set_gotidx (entryp, arg->value * arg->g->assigned_gotno))
+ if (!mips_elf_set_gotidx (entryp, arg->value * arg->g->assigned_low_gotno))
{
arg->g = NULL;
return 0;
}
- arg->g->assigned_gotno += 1;
+ arg->g->assigned_low_gotno += 1;
if (arg->info->shared
|| (elf_hash_table (arg->info)->dynamic_sections_created
@@ -4742,7 +4849,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
htab_traverse (g->got_entries, mips_elf_set_global_got_area, &tga);
/* Now go through the GOTs assigning them offset ranges.
- [assigned_gotno, local_gotno[ will be set to the range of local
+ [assigned_low_gotno, local_gotno[ will be set to the range of local
entries in each GOT. We can then compute the end of a GOT by
adding local_gotno to global_gotno. We reverse the list and make
it circular since then we'll be able to quickly compute the
@@ -4765,9 +4872,10 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
struct mips_got_info *gn;
assign += htab->reserved_gotno;
- g->assigned_gotno = assign;
+ g->assigned_low_gotno = assign;
g->local_gotno += assign;
g->local_gotno += (pages < g->page_gotno ? pages : g->page_gotno);
+ g->assigned_high_gotno = g->local_gotno - 1;
assign = g->local_gotno + g->global_gotno + g->tls_gotno;
/* Take g out of the direct list, and push it onto the reversed
@@ -4806,21 +4914,21 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
/* Assign offsets to global GOT entries and count how many
relocations they need. */
- save_assign = g->assigned_gotno;
- g->assigned_gotno = g->local_gotno;
+ save_assign = g->assigned_low_gotno;
+ g->assigned_low_gotno = g->local_gotno;
tga.info = info;
tga.value = MIPS_ELF_GOT_SIZE (abfd);
tga.g = g;
htab_traverse (g->got_entries, mips_elf_set_global_gotidx, &tga);
if (!tga.g)
return FALSE;
- BFD_ASSERT (g->assigned_gotno == g->local_gotno + g->global_gotno);
- g->assigned_gotno = save_assign;
+ BFD_ASSERT (g->assigned_low_gotno == g->local_gotno + g->global_gotno);
+ g->assigned_low_gotno = save_assign;
if (info->shared)
{
- g->relocs += g->local_gotno - g->assigned_gotno;
- BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
+ g->relocs += g->local_gotno - g->assigned_low_gotno;
+ BFD_ASSERT (g->assigned_low_gotno == g->next->local_gotno
+ g->next->global_gotno
+ g->next->tls_gotno
+ htab->reserved_gotno);
@@ -5075,6 +5183,8 @@ mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type,
{
case R_MIPS_26:
case R_MIPS_PC16:
+ case R_MIPS_PC21_S2:
+ case R_MIPS_PC26_S2:
case R_MICROMIPS_26_S1:
case R_MICROMIPS_PC7_S1:
case R_MICROMIPS_PC10_S1:
@@ -5468,10 +5578,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
&& (target_is_16_bit_code_p
|| target_is_micromips_code_p))));
- local_p = (h == NULL
- || (h->got_only_for_calls
- ? SYMBOL_CALLS_LOCAL (info, &h->root)
- : SYMBOL_REFERENCES_LOCAL (info, &h->root)));
+ local_p = (h == NULL || mips_use_local_got_p (info, h));
gp0 = _bfd_get_gp_value (input_bfd);
gp = _bfd_get_gp_value (abfd);
@@ -5862,12 +5969,74 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
case R_MIPS_PC16:
case R_MIPS_GNU_REL16_S2:
- value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
+ if (howto->partial_inplace)
+ addend = _bfd_mips_elf_sign_extend (addend, 18);
+ value = symbol + addend - p;
overflowed_p = mips_elf_overflow_p (value, 18);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
+ case R_MIPS_PC21_S2:
+ if (howto->partial_inplace)
+ addend = _bfd_mips_elf_sign_extend (addend, 23);
+ value = symbol + addend - p;
+ overflowed_p = mips_elf_overflow_p (value, 23);
+ value >>= howto->rightshift;
+ value &= howto->dst_mask;
+ break;
+
+ case R_MIPS_PC26_S2:
+ if (howto->partial_inplace)
+ addend = _bfd_mips_elf_sign_extend (addend, 28);
+ value = symbol + addend - p;
+ overflowed_p = mips_elf_overflow_p (value, 28);
+ value >>= howto->rightshift;
+ value &= howto->dst_mask;
+ break;
+
+ case R_MIPS_PC18_S3:
+ if (howto->partial_inplace)
+ addend = _bfd_mips_elf_sign_extend (addend, 21);
+
+ if ((symbol + addend) & 7)
+ return bfd_reloc_outofrange;
+
+ value = symbol + addend - ((p | 7) ^ 7);
+ overflowed_p = mips_elf_overflow_p (value, 21);
+ value >>= howto->rightshift;
+ value &= howto->dst_mask;
+ break;
+
+ case R_MIPS_PC19_S2:
+ if (howto->partial_inplace)
+ addend = _bfd_mips_elf_sign_extend (addend, 21);
+
+ if ((symbol + addend) & 3)
+ return bfd_reloc_outofrange;
+
+ value = symbol + addend - p;
+ overflowed_p = mips_elf_overflow_p (value, 21);
+ value >>= howto->rightshift;
+ value &= howto->dst_mask;
+ break;
+
+ case R_MIPS_PCHI16:
+ if (howto->partial_inplace)
+ addend = _bfd_mips_elf_sign_extend (addend, 16);
+ value = mips_elf_high (symbol + addend - p);
+ BFD_ASSERT (howto->rightshift == 16);
+ overflowed_p = mips_elf_overflow_p (value, 16);
+ value &= howto->dst_mask;
+ break;
+
+ case R_MIPS_PCLO16:
+ if (howto->partial_inplace)
+ addend = _bfd_mips_elf_sign_extend (addend, 16);
+ value = symbol + _bfd_mips_elf_sign_extend (addend, 16) - p;
+ value &= howto->dst_mask;
+ break;
+
case R_MICROMIPS_PC7_S1:
value = symbol + _bfd_mips_elf_sign_extend (addend, 8) - p;
overflowed_p = mips_elf_overflow_p (value, 8);
@@ -6434,6 +6603,12 @@ _bfd_elf_mips_mach (flagword flags)
case E_MIPS_ARCH_64R2:
return bfd_mach_mipsisa64r2;
+
+ case E_MIPS_ARCH_32R6:
+ return bfd_mach_mipsisa32r6;
+
+ case E_MIPS_ARCH_64R6:
+ return bfd_mach_mipsisa64r6;
}
}
@@ -6879,6 +7054,11 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd,
if (!MIPS_ELF_OPTIONS_SECTION_NAME_P (name))
return FALSE;
break;
+ case SHT_MIPS_ABIFLAGS:
+ if (!MIPS_ELF_ABIFLAGS_SECTION_NAME_P (name))
+ return FALSE;
+ flags = (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_SIZE);
+ break;
case SHT_MIPS_DWARF:
if (! CONST_STRNEQ (name, ".debug_")
&& ! CONST_STRNEQ (name, ".zdebug_"))
@@ -6909,6 +7089,20 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd,
return FALSE;
}
+ if (hdr->sh_type == SHT_MIPS_ABIFLAGS)
+ {
+ Elf_External_ABIFlags_v0 ext;
+
+ if (! bfd_get_section_contents (abfd, hdr->bfd_section,
+ &ext, 0, sizeof ext))
+ return FALSE;
+ bfd_mips_elf_swap_abiflags_v0_in (abfd, &ext,
+ &mips_elf_tdata (abfd)->abiflags);
+ if (mips_elf_tdata (abfd)->abiflags.version != 0)
+ return FALSE;
+ mips_elf_tdata (abfd)->abiflags_valid = TRUE;
+ }
+
/* FIXME: We should record sh_info for a .gptab section. */
/* For a .reginfo section, set the gp value in the tdata information
@@ -7075,6 +7269,11 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
hdr->sh_entsize = 1;
hdr->sh_flags |= SHF_MIPS_NOSTRIP;
}
+ else if (CONST_STRNEQ (name, ".MIPS.abiflags"))
+ {
+ hdr->sh_type = SHT_MIPS_ABIFLAGS;
+ hdr->sh_entsize = sizeof (Elf_External_ABIFlags_v0);
+ }
else if (CONST_STRNEQ (name, ".debug_")
|| CONST_STRNEQ (name, ".zdebug_"))
{
@@ -7586,6 +7785,8 @@ mips_elf_add_lo16_rel_addend (bfd *abfd,
lo16_type = R_MIPS16_LO16;
else if (micromips_reloc_p (r_type))
lo16_type = R_MICROMIPS_LO16;
+ else if (r_type == R_MIPS_PCHI16)
+ lo16_type = R_MIPS_PCLO16;
else
lo16_type = R_MIPS_LO16;
@@ -7955,6 +8156,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
unsigned int r_type;
struct elf_link_hash_entry *h;
bfd_boolean can_make_dynamic_p;
+ bfd_boolean call_reloc_p;
+ bfd_boolean constrain_symbol_p;
r_symndx = ELF_R_SYM (abfd, rel->r_info);
r_type = ELF_R_TYPE (abfd, rel->r_info);
@@ -7987,12 +8190,30 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
/* Set CAN_MAKE_DYNAMIC_P to true if we can convert this
relocation into a dynamic one. */
can_make_dynamic_p = FALSE;
+
+ /* Set CALL_RELOC_P to true if the relocation is for a call,
+ and if pointer equality therefore doesn't matter. */
+ call_reloc_p = FALSE;
+
+ /* Set CONSTRAIN_SYMBOL_P if we need to take the relocation
+ into account when deciding how to define the symbol.
+ Relocations in nonallocatable sections such as .pdr and
+ .debug* should have no effect. */
+ constrain_symbol_p = ((sec->flags & SEC_ALLOC) != 0);
+
switch (r_type)
{
- case R_MIPS_GOT16:
case R_MIPS_CALL16:
case R_MIPS_CALL_HI16:
case R_MIPS_CALL_LO16:
+ case R_MIPS16_CALL16:
+ case R_MICROMIPS_CALL16:
+ case R_MICROMIPS_CALL_HI16:
+ case R_MICROMIPS_CALL_LO16:
+ call_reloc_p = TRUE;
+ /* Fall through. */
+
+ case R_MIPS_GOT16:
case R_MIPS_GOT_HI16:
case R_MIPS_GOT_LO16:
case R_MIPS_GOT_PAGE:
@@ -8002,14 +8223,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_MIPS_TLS_GD:
case R_MIPS_TLS_LDM:
case R_MIPS16_GOT16:
- case R_MIPS16_CALL16:
case R_MIPS16_TLS_GOTTPREL:
case R_MIPS16_TLS_GD:
case R_MIPS16_TLS_LDM:
case R_MICROMIPS_GOT16:
- case R_MICROMIPS_CALL16:
- case R_MICROMIPS_CALL_HI16:
- case R_MICROMIPS_CALL_LO16:
case R_MICROMIPS_GOT_HI16:
case R_MICROMIPS_GOT_LO16:
case R_MICROMIPS_GOT_PAGE:
@@ -8030,12 +8247,27 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
+ can_make_dynamic_p = TRUE;
break;
- /* This is just a hint; it can safely be ignored. Don't set
- has_static_relocs for the corresponding symbol. */
+ case R_MIPS_NONE:
case R_MIPS_JALR:
case R_MICROMIPS_JALR:
+ /* These relocations have empty fields and are purely there to
+ provide link information. The symbol value doesn't matter. */
+ constrain_symbol_p = FALSE;
+ break;
+
+ case R_MIPS_GPREL16:
+ case R_MIPS_GPREL32:
+ case R_MIPS16_GPREL:
+ case R_MICROMIPS_GPREL16:
+ /* GP-relative relocations always resolve to a definition in a
+ regular input file, ignoring the one-definition rule. This is
+ important for the GP setup sequence in NewABI code, which
+ always resolves to a local function even if other relocations
+ against the symbol wouldn't. */
+ constrain_symbol_p = FALSE;
break;
case R_MIPS_32:
@@ -8062,51 +8294,41 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
can_make_dynamic_p = TRUE;
if (dynobj == NULL)
elf_hash_table (info)->dynobj = dynobj = abfd;
- break;
}
- /* For sections that are not SEC_ALLOC a copy reloc would be
- output if possible (implying questionable semantics for
- read-only data objects) or otherwise the final link would
- fail as ld.so will not process them and could not therefore
- handle any outstanding dynamic relocations.
-
- For such sections that are also SEC_DEBUGGING, we can avoid
- these problems by simply ignoring any relocs as these
- sections have a predefined use and we know it is safe to do
- so.
-
- This is needed in cases such as a global symbol definition
- in a shared library causing a common symbol from an object
- file to be converted to an undefined reference. If that
- happens, then all the relocations against this symbol from
- SEC_DEBUGGING sections in the object file will resolve to
- nil. */
- if ((sec->flags & SEC_DEBUGGING) != 0)
- break;
- /* Fall through. */
-
- default:
- /* Most static relocations require pointer equality, except
- for branches. */
- if (h)
- h->pointer_equality_needed = TRUE;
- /* Fall through. */
+ break;
case R_MIPS_26:
case R_MIPS_PC16:
+ case R_MIPS_PC21_S2:
+ case R_MIPS_PC26_S2:
case R_MIPS16_26:
case R_MICROMIPS_26_S1:
case R_MICROMIPS_PC7_S1:
case R_MICROMIPS_PC10_S1:
case R_MICROMIPS_PC16_S1:
case R_MICROMIPS_PC23_S2:
- if (h)
- ((struct mips_elf_link_hash_entry *) h)->has_static_relocs = TRUE;
+ call_reloc_p = TRUE;
break;
}
if (h)
{
+ if (constrain_symbol_p)
+ {
+ if (!can_make_dynamic_p)
+ ((struct mips_elf_link_hash_entry *) h)->has_static_relocs = 1;
+
+ if (!call_reloc_p)
+ h->pointer_equality_needed = 1;
+
+ /* We must not create a stub for a symbol that has
+ relocations related to taking the function's address.
+ This doesn't apply to VxWorks, where CALL relocs refer
+ to a .got.plt entry instead of a normal .got entry. */
+ if (!htab->is_vxworks && (!can_make_dynamic_p || !call_reloc_p))
+ ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE;
+ }
+
/* Relocations against the special VxWorks __GOTT_BASE__ and
__GOTT_INDEX__ symbols must be left to the loader. Allocate
room for them in .rela.dyn. */
@@ -8387,28 +8609,6 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
h->plt.plist->need_comp = TRUE;
}
- /* We must not create a stub for a symbol that has relocations
- related to taking the function's address. This doesn't apply to
- VxWorks, where CALL relocs refer to a .got.plt entry instead of
- a normal .got entry. */
- if (!htab->is_vxworks && h != NULL)
- switch (r_type)
- {
- default:
- ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE;
- break;
- case R_MIPS16_CALL16:
- case R_MIPS_CALL16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- case R_MIPS_JALR:
- case R_MICROMIPS_CALL16:
- case R_MICROMIPS_CALL_HI16:
- case R_MICROMIPS_CALL_LO16:
- case R_MICROMIPS_JALR:
- break;
- }
-
/* See if this reloc would need to refer to a MIPS16 hard-float stub,
if there is one. We only need to handle global symbols here;
we decide whether to keep or delete stubs for local symbols
@@ -8997,7 +9197,7 @@ bfd_boolean
_bfd_mips_elf_always_size_sections (bfd *output_bfd,
struct bfd_link_info *info)
{
- asection *ri;
+ asection *sect;
struct mips_elf_link_hash_table *htab;
struct mips_htab_traverse_info hti;
@@ -9005,9 +9205,14 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
BFD_ASSERT (htab != NULL);
/* The .reginfo section has a fixed size. */
- ri = bfd_get_section_by_name (output_bfd, ".reginfo");
- if (ri != NULL)
- bfd_set_section_size (output_bfd, ri, sizeof (Elf32_External_RegInfo));
+ sect = bfd_get_section_by_name (output_bfd, ".reginfo");
+ if (sect != NULL)
+ bfd_set_section_size (output_bfd, sect, sizeof (Elf32_External_RegInfo));
+
+ /* The .MIPS.abiflags section has a fixed size. */
+ sect = bfd_get_section_by_name (output_bfd, ".MIPS.abiflags");
+ if (sect != NULL)
+ bfd_set_section_size (output_bfd, sect, sizeof (Elf_External_ABIFlags_v0));
hti.info = info;
hti.output_bfd = output_bfd;
@@ -9046,13 +9251,13 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
/* Allocate room for the reserved entries. VxWorks always reserves
3 entries; other objects only reserve 2 entries. */
- BFD_ASSERT (g->assigned_gotno == 0);
+ BFD_ASSERT (g->assigned_low_gotno == 0);
if (htab->is_vxworks)
htab->reserved_gotno = 3;
else
htab->reserved_gotno = 2;
g->local_gotno += htab->reserved_gotno;
- g->assigned_gotno = htab->reserved_gotno;
+ g->assigned_low_gotno = htab->reserved_gotno;
/* Decide which symbols need to go in the global part of the GOT and
count the number of reloc-only GOT symbols. */
@@ -9095,6 +9300,7 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
page_gotno = g->page_gotno;
g->local_gotno += page_gotno;
+ g->assigned_high_gotno = g->local_gotno - 1;
s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
s->size += g->global_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
@@ -10019,6 +10225,13 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
(info, msg, name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
+ if (aligned_pcrel_reloc_p (howto->type))
+ {
+ msg = _("PC-relative load from unaligned address");
+ info->callbacks->warning
+ (info, msg, name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
/* Fall through. */
default:
@@ -10308,7 +10521,11 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
load = MIPS_ELF_LOAD_WORD (output_bfd);
/* Fill in the PLT entry itself. */
- plt_entry = mips_exec_plt_entry;
+
+ if (MIPSR6_P (output_bfd))
+ plt_entry = mipsr6_exec_plt_entry;
+ else
+ plt_entry = mips_exec_plt_entry;
bfd_put_32 (output_bfd, plt_entry[0] | got_address_high, loc);
bfd_put_32 (output_bfd, plt_entry[1] | got_address_low | load,
loc + 4);
@@ -11369,10 +11586,14 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
if (! info->shared)
continue;
- while (got_index < g->assigned_gotno)
+ for (; got_index < g->local_gotno; got_index++)
{
+ if (got_index >= g->assigned_low_gotno
+ && got_index <= g->assigned_high_gotno)
+ continue;
+
rel[0].r_offset = rel[1].r_offset = rel[2].r_offset
- = got_index++ * MIPS_ELF_GOT_SIZE (output_bfd);
+ = got_index * MIPS_ELF_GOT_SIZE (output_bfd);
if (!(mips_elf_create_dynamic_relocation
(output_bfd, info, rel, NULL,
bfd_abs_section_ptr,
@@ -11606,7 +11827,7 @@ mips_set_isa_flags (bfd *abfd)
break;
case bfd_mach_mips_loongson_3a:
- val = E_MIPS_ARCH_64 | E_MIPS_MACH_LS3A;
+ val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_LS3A;
break;
case bfd_mach_mips_octeon:
@@ -11631,12 +11852,24 @@ mips_set_isa_flags (bfd *abfd)
break;
case bfd_mach_mipsisa32r2:
+ case bfd_mach_mipsisa32r3:
+ case bfd_mach_mipsisa32r5:
val = E_MIPS_ARCH_32R2;
break;
case bfd_mach_mipsisa64r2:
+ case bfd_mach_mipsisa64r3:
+ case bfd_mach_mipsisa64r5:
val = E_MIPS_ARCH_64R2;
break;
+
+ case bfd_mach_mipsisa32r6:
+ val = E_MIPS_ARCH_32R6;
+ break;
+
+ case bfd_mach_mipsisa64r6:
+ val = E_MIPS_ARCH_64R6;
+ break;
}
elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
elf_elfheader (abfd)->e_flags |= val;
@@ -11745,6 +11978,10 @@ _bfd_mips_elf_additional_program_headers (bfd *abfd,
if (s && (s->flags & SEC_LOAD))
++ret;
+ /* See if we need a PT_MIPS_ABIFLAGS segment. */
+ if (bfd_get_section_by_name (abfd, ".MIPS.abiflags"))
+ ++ret;
+
/* See if we need a PT_MIPS_OPTIONS segment. */
if (IRIX_COMPAT (abfd) == ict_irix6
&& bfd_get_section_by_name (abfd,
@@ -11807,6 +12044,37 @@ _bfd_mips_elf_modify_segment_map (bfd *abfd,
}
}
+ /* If there is a .MIPS.abiflags section, we need a PT_MIPS_ABIFLAGS
+ segment. */
+ s = bfd_get_section_by_name (abfd, ".MIPS.abiflags");
+ if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ {
+ for (m = elf_seg_map (abfd); m != NULL; m = m->next)
+ if (m->p_type == PT_MIPS_ABIFLAGS)
+ break;
+ if (m == NULL)
+ {
+ amt = sizeof *m;
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ return FALSE;
+
+ m->p_type = PT_MIPS_ABIFLAGS;
+ m->count = 1;
+ m->sections[0] = s;
+
+ /* We want to put it after the PHDR and INTERP segments. */
+ pm = &elf_seg_map (abfd);
+ while (*pm != NULL
+ && ((*pm)->p_type == PT_PHDR
+ || (*pm)->p_type == PT_INTERP))
+ pm = &(*pm)->next;
+
+ m->next = *pm;
+ *pm = m;
+ }
+ }
+
/* For IRIX 6, we don't have .mdebug sections, nor does anything but
.dynamic end up in PT_DYNAMIC. However, we do have to insert a
PT_MIPS_OPTIONS segment immediately following the program header
@@ -11901,18 +12169,6 @@ _bfd_mips_elf_modify_segment_map (bfd *abfd,
if ((*pm)->p_type == PT_DYNAMIC)
break;
m = *pm;
- if (m != NULL && IRIX_COMPAT (abfd) == ict_none)
- {
- /* For a normal mips executable the permissions for the PT_DYNAMIC
- segment are read, write and execute. We do that here since
- the code in elf.c sets only the read permission. This matters
- sometimes for the dynamic linker. */
- if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
- {
- m->p_flags = PF_R | PF_W | PF_X;
- m->p_flags_valid = 1;
- }
- }
/* GNU/Linux binaries do not need the extended PT_DYNAMIC section.
glibc's dynamic linker has traditionally derived the number of
tags from the p_filesz field, and sometimes allocates stack
@@ -12102,6 +12358,36 @@ _bfd_mips_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
return TRUE;
}
+
+/* Prevent .MIPS.abiflags from being discarded with --gc-sections. */
+
+bfd_boolean
+_bfd_mips_elf_gc_mark_extra_sections (struct bfd_link_info *info,
+ elf_gc_mark_hook_fn gc_mark_hook)
+{
+ bfd *sub;
+
+ _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
+
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ asection *o;
+
+ if (! is_mips_elf (sub))
+ continue;
+
+ for (o = sub->sections; o != NULL; o = o->next)
+ if (!o->gc_mark
+ && MIPS_ELF_ABIFLAGS_SECTION_NAME_P
+ (bfd_get_section_name (sub, o)))
+ {
+ if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
/* Copy data from a MIPS ELF indirect symbol to its direct symbol,
hiding the old indirect symbol. Process additional relocation
@@ -13552,6 +13838,177 @@ _bfd_mips_elf_insn32 (struct bfd_link_info *info, bfd_boolean on)
mips_elf_hash_table (info)->insn32 = on;
}
+/* Return the .MIPS.abiflags value representing each ISA Extension. */
+
+unsigned int
+bfd_mips_isa_ext (bfd *abfd)
+{
+ switch (bfd_get_mach (abfd))
+ {
+ case bfd_mach_mips3900:
+ return AFL_EXT_3900;
+ case bfd_mach_mips4010:
+ return AFL_EXT_4010;
+ case bfd_mach_mips4100:
+ return AFL_EXT_4100;
+ case bfd_mach_mips4111:
+ return AFL_EXT_4111;
+ case bfd_mach_mips4120:
+ return AFL_EXT_4120;
+ case bfd_mach_mips4650:
+ return AFL_EXT_4650;
+ case bfd_mach_mips5400:
+ return AFL_EXT_5400;
+ case bfd_mach_mips5500:
+ return AFL_EXT_5500;
+ case bfd_mach_mips5900:
+ return AFL_EXT_5900;
+ case bfd_mach_mips10000:
+ return AFL_EXT_10000;
+ case bfd_mach_mips_loongson_2e:
+ return AFL_EXT_LOONGSON_2E;
+ case bfd_mach_mips_loongson_2f:
+ return AFL_EXT_LOONGSON_2F;
+ case bfd_mach_mips_loongson_3a:
+ return AFL_EXT_LOONGSON_3A;
+ case bfd_mach_mips_sb1:
+ return AFL_EXT_SB1;
+ case bfd_mach_mips_octeon:
+ return AFL_EXT_OCTEON;
+ case bfd_mach_mips_octeonp:
+ return AFL_EXT_OCTEONP;
+ case bfd_mach_mips_octeon2:
+ return AFL_EXT_OCTEON2;
+ case bfd_mach_mips_xlr:
+ return AFL_EXT_XLR;
+ }
+ return 0;
+}
+
+/* Update the isa_level, isa_rev, isa_ext fields of abiflags. */
+
+static void
+update_mips_abiflags_isa (bfd *abfd, Elf_Internal_ABIFlags_v0 *abiflags)
+{
+ switch (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH)
+ {
+ case E_MIPS_ARCH_1:
+ abiflags->isa_level = 1;
+ abiflags->isa_rev = 0;
+ break;
+ case E_MIPS_ARCH_2:
+ abiflags->isa_level = 2;
+ abiflags->isa_rev = 0;
+ break;
+ case E_MIPS_ARCH_3:
+ abiflags->isa_level = 3;
+ abiflags->isa_rev = 0;
+ break;
+ case E_MIPS_ARCH_4:
+ abiflags->isa_level = 4;
+ abiflags->isa_rev = 0;
+ break;
+ case E_MIPS_ARCH_5:
+ abiflags->isa_level = 5;
+ abiflags->isa_rev = 0;
+ break;
+ case E_MIPS_ARCH_32:
+ abiflags->isa_level = 32;
+ abiflags->isa_rev = 1;
+ break;
+ case E_MIPS_ARCH_32R2:
+ abiflags->isa_level = 32;
+ /* Handle MIPS32r3 and MIPS32r5 which do not have a header flag. */
+ if (abiflags->isa_rev < 2)
+ abiflags->isa_rev = 2;
+ break;
+ case E_MIPS_ARCH_32R6:
+ abiflags->isa_level = 32;
+ abiflags->isa_rev = 6;
+ break;
+ case E_MIPS_ARCH_64:
+ abiflags->isa_level = 64;
+ abiflags->isa_rev = 1;
+ break;
+ case E_MIPS_ARCH_64R2:
+ /* Handle MIPS64r3 and MIPS64r5 which do not have a header flag. */
+ abiflags->isa_level = 64;
+ if (abiflags->isa_rev < 2)
+ abiflags->isa_rev = 2;
+ break;
+ case E_MIPS_ARCH_64R6:
+ abiflags->isa_level = 64;
+ abiflags->isa_rev = 6;
+ break;
+ default:
+ (*_bfd_error_handler)
+ (_("%B: Unknown architecture %s"),
+ abfd, bfd_printable_name (abfd));
+ }
+
+ abiflags->isa_ext = bfd_mips_isa_ext (abfd);
+}
+
+/* Return true if the given ELF header flags describe a 32-bit binary. */
+
+static bfd_boolean
+mips_32bit_flags_p (flagword flags)
+{
+ return ((flags & EF_MIPS_32BITMODE) != 0
+ || (flags & EF_MIPS_ABI) == E_MIPS_ABI_O32
+ || (flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6);
+}
+
+/* Infer the content of the ABI flags based on the elf header. */
+
+static void
+infer_mips_abiflags (bfd *abfd, Elf_Internal_ABIFlags_v0* abiflags)
+{
+ obj_attribute *in_attr;
+
+ memset (abiflags, 0, sizeof (Elf_Internal_ABIFlags_v0));
+ update_mips_abiflags_isa (abfd, abiflags);
+
+ if (mips_32bit_flags_p (elf_elfheader (abfd)->e_flags))
+ abiflags->gpr_size = AFL_REG_32;
+ else
+ abiflags->gpr_size = AFL_REG_64;
+
+ abiflags->cpr1_size = AFL_REG_NONE;
+
+ in_attr = elf_known_obj_attributes (abfd)[OBJ_ATTR_GNU];
+ abiflags->fp_abi = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+
+ if (abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_SINGLE
+ || abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_XX
+ || (abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_DOUBLE
+ && abiflags->gpr_size == AFL_REG_32))
+ abiflags->cpr1_size = AFL_REG_32;
+ else if (abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_DOUBLE
+ || abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_64
+ || abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_64A)
+ abiflags->cpr1_size = AFL_REG_64;
+
+ abiflags->cpr2_size = AFL_REG_NONE;
+
+ if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MDMX)
+ abiflags->ases |= AFL_ASE_MDMX;
+ if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_M16)
+ abiflags->ases |= AFL_ASE_MIPS16;
+ if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS)
+ abiflags->ases |= AFL_ASE_MICROMIPS;
+
+ if (abiflags->fp_abi != Val_GNU_MIPS_ABI_FP_ANY
+ && abiflags->fp_abi != Val_GNU_MIPS_ABI_FP_SOFT
+ && abiflags->fp_abi != Val_GNU_MIPS_ABI_FP_64A)
+ abiflags->flags1 |= AFL_FLAGS1_ODDSPREG;
+}
+
/* We need to use a special link routine to handle the .reginfo and
the .mdebug sections. We need to merge all instances of these
sections together, not write them all out sequentially. */
@@ -13562,7 +14019,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
asection *o;
struct bfd_link_order *p;
asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
- asection *rtproc_sec;
+ asection *rtproc_sec, *abiflags_sec;
Elf32_RegInfo reginfo;
struct ecoff_debug_info debug;
struct mips_htab_traverse_info hti;
@@ -13644,12 +14101,46 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
/* Go through the sections and collect the .reginfo and .mdebug
information. */
+ abiflags_sec = NULL;
reginfo_sec = NULL;
mdebug_sec = NULL;
gptab_data_sec = NULL;
gptab_bss_sec = NULL;
for (o = abfd->sections; o != NULL; o = o->next)
{
+ if (strcmp (o->name, ".MIPS.abiflags") == 0)
+ {
+ /* We have found the .MIPS.abiflags section in the output file.
+ Look through all the link_orders comprising it and remove them.
+ The data is merged in _bfd_mips_elf_merge_private_bfd_data. */
+ for (p = o->map_head.link_order; p != NULL; p = p->next)
+ {
+ asection *input_section;
+
+ if (p->type != bfd_indirect_link_order)
+ {
+ if (p->type == bfd_data_link_order)
+ continue;
+ abort ();
+ }
+
+ input_section = p->u.indirect.section;
+
+ /* Hack: reset the SEC_HAS_CONTENTS flag so that
+ elf_link_input_bfd ignores this section. */
+ input_section->flags &= ~SEC_HAS_CONTENTS;
+ }
+
+ /* Size has been set in _bfd_mips_elf_always_size_sections. */
+ BFD_ASSERT(o->size == sizeof (Elf_External_ABIFlags_v0));
+
+ /* Skip this section later on (I don't think this currently
+ matters, but someday it might). */
+ o->map_head.link_order = NULL;
+
+ abiflags_sec = o;
+ }
+
if (strcmp (o->name, ".reginfo") == 0)
{
memset (&reginfo, 0, sizeof reginfo);
@@ -14134,6 +14625,24 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
/* Now write out the computed sections. */
+ if (abiflags_sec != NULL)
+ {
+ Elf_External_ABIFlags_v0 ext;
+ Elf_Internal_ABIFlags_v0 *abiflags;
+
+ abiflags = &mips_elf_tdata (abfd)->abiflags;
+
+ /* Set up the abiflags if no valid input sections were found. */
+ if (!mips_elf_tdata (abfd)->abiflags_valid)
+ {
+ infer_mips_abiflags (abfd, abiflags);
+ mips_elf_tdata (abfd)->abiflags_valid = TRUE;
+ }
+ bfd_mips_elf_swap_abiflags_v0_out (abfd, abiflags, &ext);
+ if (! bfd_set_section_contents (abfd, abiflags_sec, &ext, 0, sizeof ext))
+ return FALSE;
+ }
+
if (reginfo_sec != NULL)
{
Elf32_External_RegInfo ext;
@@ -14202,12 +14711,12 @@ static const struct mips_mach_extension mips_mach_extensions[] =
{ bfd_mach_mips_octeon2, bfd_mach_mips_octeonp },
{ bfd_mach_mips_octeonp, bfd_mach_mips_octeon },
{ bfd_mach_mips_octeon, bfd_mach_mipsisa64r2 },
+ { bfd_mach_mips_loongson_3a, bfd_mach_mipsisa64r2 },
/* MIPS64 extensions. */
{ bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
{ bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
{ bfd_mach_mips_xlr, bfd_mach_mipsisa64 },
- { bfd_mach_mips_loongson_3a, bfd_mach_mipsisa64 },
/* MIPS V extensions. */
{ bfd_mach_mipsisa64, bfd_mach_mips5 },
@@ -14291,21 +14800,6 @@ mips_mach_extends_p (unsigned long base, unsigned long extension)
}
-/* Return true if the given ELF header flags describe a 32-bit binary. */
-
-static bfd_boolean
-mips_32bit_flags_p (flagword flags)
-{
- return ((flags & EF_MIPS_32BITMODE) != 0
- || (flags & EF_MIPS_ABI) == E_MIPS_ABI_O32
- || (flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32
- || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1
- || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2
- || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32
- || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2);
-}
-
-
/* Merge object attributes from IBFD into OBFD. Raise an error if
there are conflicting attributes. */
static bfd_boolean
@@ -14314,12 +14808,18 @@ mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
obj_attribute *in_attr;
obj_attribute *out_attr;
bfd *abi_fp_bfd;
+ bfd *abi_msa_bfd;
abi_fp_bfd = mips_elf_tdata (obfd)->abi_fp_bfd;
in_attr = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
if (!abi_fp_bfd && in_attr[Tag_GNU_MIPS_ABI_FP].i != Val_GNU_MIPS_ABI_FP_ANY)
mips_elf_tdata (obfd)->abi_fp_bfd = ibfd;
+ abi_msa_bfd = mips_elf_tdata (obfd)->abi_msa_bfd;
+ if (!abi_msa_bfd
+ && in_attr[Tag_GNU_MIPS_ABI_MSA].i != Val_GNU_MIPS_ABI_MSA_ANY)
+ mips_elf_tdata (obfd)->abi_msa_bfd = ibfd;
+
if (!elf_known_obj_attributes_proc (obfd)[0].i)
{
/* This is the first object. Copy the attributes. */
@@ -14337,175 +14837,111 @@ mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
if (in_attr[Tag_GNU_MIPS_ABI_FP].i != out_attr[Tag_GNU_MIPS_ABI_FP].i)
{
- out_attr[Tag_GNU_MIPS_ABI_FP].type = 1;
- if (out_attr[Tag_GNU_MIPS_ABI_FP].i == Val_GNU_MIPS_ABI_FP_ANY)
- out_attr[Tag_GNU_MIPS_ABI_FP].i = in_attr[Tag_GNU_MIPS_ABI_FP].i;
- else if (in_attr[Tag_GNU_MIPS_ABI_FP].i != Val_GNU_MIPS_ABI_FP_ANY)
- switch (out_attr[Tag_GNU_MIPS_ABI_FP].i)
- {
- case Val_GNU_MIPS_ABI_FP_DOUBLE:
- switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
- {
- case Val_GNU_MIPS_ABI_FP_SINGLE:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd, "-mdouble-float", "-msingle-float");
- break;
+ int out_fp, in_fp;
- case Val_GNU_MIPS_ABI_FP_SOFT:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd, "-mhard-float", "-msoft-float");
- break;
-
- case Val_GNU_MIPS_ABI_FP_64:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd,
- "-mdouble-float", "-mips32r2 -mfp64");
- break;
-
- default:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), "
- "%B uses unknown floating point ABI %d"),
- obfd, abi_fp_bfd, ibfd,
- "-mdouble-float", in_attr[Tag_GNU_MIPS_ABI_FP].i);
- break;
- }
- break;
-
- case Val_GNU_MIPS_ABI_FP_SINGLE:
- switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
- {
- case Val_GNU_MIPS_ABI_FP_DOUBLE:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd, "-msingle-float", "-mdouble-float");
- break;
-
- case Val_GNU_MIPS_ABI_FP_SOFT:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd, "-mhard-float", "-msoft-float");
- break;
-
- case Val_GNU_MIPS_ABI_FP_64:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd,
- "-msingle-float", "-mips32r2 -mfp64");
- break;
-
- default:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), "
- "%B uses unknown floating point ABI %d"),
- obfd, abi_fp_bfd, ibfd,
- "-msingle-float", in_attr[Tag_GNU_MIPS_ABI_FP].i);
- break;
- }
- break;
-
- case Val_GNU_MIPS_ABI_FP_SOFT:
- switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
- {
- case Val_GNU_MIPS_ABI_FP_DOUBLE:
- case Val_GNU_MIPS_ABI_FP_SINGLE:
- case Val_GNU_MIPS_ABI_FP_64:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd, "-msoft-float", "-mhard-float");
- break;
-
- default:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), "
- "%B uses unknown floating point ABI %d"),
- obfd, abi_fp_bfd, ibfd,
- "-msoft-float", in_attr[Tag_GNU_MIPS_ABI_FP].i);
- break;
- }
- break;
-
- case Val_GNU_MIPS_ABI_FP_64:
- switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
- {
- case Val_GNU_MIPS_ABI_FP_DOUBLE:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd,
- "-mips32r2 -mfp64", "-mdouble-float");
- break;
-
- case Val_GNU_MIPS_ABI_FP_SINGLE:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd,
- "-mips32r2 -mfp64", "-msingle-float");
- break;
-
- case Val_GNU_MIPS_ABI_FP_SOFT:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd, "-mhard-float", "-msoft-float");
- break;
+ out_fp = out_attr[Tag_GNU_MIPS_ABI_FP].i;
+ in_fp = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+ out_attr[Tag_GNU_MIPS_ABI_FP].type = 1;
+ if (out_fp == Val_GNU_MIPS_ABI_FP_ANY)
+ out_attr[Tag_GNU_MIPS_ABI_FP].i = in_fp;
+ else if (out_fp == Val_GNU_MIPS_ABI_FP_XX
+ && (in_fp == Val_GNU_MIPS_ABI_FP_DOUBLE
+ || in_fp == Val_GNU_MIPS_ABI_FP_64
+ || in_fp == Val_GNU_MIPS_ABI_FP_64A))
+ {
+ mips_elf_tdata (obfd)->abi_fp_bfd = ibfd;
+ out_attr[Tag_GNU_MIPS_ABI_FP].i = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+ }
+ else if (in_fp == Val_GNU_MIPS_ABI_FP_XX
+ && (out_fp == Val_GNU_MIPS_ABI_FP_DOUBLE
+ || out_fp == Val_GNU_MIPS_ABI_FP_64
+ || out_fp == Val_GNU_MIPS_ABI_FP_64A))
+ /* Keep the current setting. */;
+ else if (out_fp == Val_GNU_MIPS_ABI_FP_64A
+ && in_fp == Val_GNU_MIPS_ABI_FP_64)
+ {
+ mips_elf_tdata (obfd)->abi_fp_bfd = ibfd;
+ out_attr[Tag_GNU_MIPS_ABI_FP].i = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+ }
+ else if (in_fp == Val_GNU_MIPS_ABI_FP_64A
+ && out_fp == Val_GNU_MIPS_ABI_FP_64)
+ /* Keep the current setting. */;
+ else if (in_fp != Val_GNU_MIPS_ABI_FP_ANY)
+ {
+ const char *out_string, *in_string;
+
+ out_string = _bfd_mips_fp_abi_string (out_fp);
+ in_string = _bfd_mips_fp_abi_string (in_fp);
+ /* First warn about cases involving unrecognised ABIs. */
+ if (!out_string && !in_string)
+ _bfd_error_handler
+ (_("Warning: %B uses unknown floating point ABI %d "
+ "(set by %B), %B uses unknown floating point ABI %d"),
+ obfd, abi_fp_bfd, ibfd, out_fp, in_fp);
+ else if (!out_string)
+ _bfd_error_handler
+ (_("Warning: %B uses unknown floating point ABI %d "
+ "(set by %B), %B uses %s"),
+ obfd, abi_fp_bfd, ibfd, out_fp, in_string);
+ else if (!in_string)
+ _bfd_error_handler
+ (_("Warning: %B uses %s (set by %B), "
+ "%B uses unknown floating point ABI %d"),
+ obfd, abi_fp_bfd, ibfd, out_string, in_fp);
+ else
+ {
+ /* If one of the bfds is soft-float, the other must be
+ hard-float. The exact choice of hard-float ABI isn't
+ really relevant to the error message. */
+ if (in_fp == Val_GNU_MIPS_ABI_FP_SOFT)
+ out_string = "-mhard-float";
+ else if (out_fp == Val_GNU_MIPS_ABI_FP_SOFT)
+ in_string = "-mhard-float";
+ _bfd_error_handler
+ (_("Warning: %B uses %s (set by %B), %B uses %s"),
+ obfd, abi_fp_bfd, ibfd, out_string, in_string);
+ }
+ }
+ }
- default:
- _bfd_error_handler
- (_("Warning: %B uses %s (set by %B), "
- "%B uses unknown floating point ABI %d"),
- obfd, abi_fp_bfd, ibfd,
- "-mips32r2 -mfp64", in_attr[Tag_GNU_MIPS_ABI_FP].i);
- break;
- }
+ /* Check for conflicting Tag_GNU_MIPS_ABI_MSA attributes and merge
+ non-conflicting ones. */
+ if (in_attr[Tag_GNU_MIPS_ABI_MSA].i != out_attr[Tag_GNU_MIPS_ABI_MSA].i)
+ {
+ out_attr[Tag_GNU_MIPS_ABI_MSA].type = 1;
+ if (out_attr[Tag_GNU_MIPS_ABI_MSA].i == Val_GNU_MIPS_ABI_MSA_ANY)
+ out_attr[Tag_GNU_MIPS_ABI_MSA].i = in_attr[Tag_GNU_MIPS_ABI_MSA].i;
+ else if (in_attr[Tag_GNU_MIPS_ABI_MSA].i != Val_GNU_MIPS_ABI_MSA_ANY)
+ switch (out_attr[Tag_GNU_MIPS_ABI_MSA].i)
+ {
+ case Val_GNU_MIPS_ABI_MSA_128:
+ _bfd_error_handler
+ (_("Warning: %B uses %s (set by %B), "
+ "%B uses unknown MSA ABI %d"),
+ obfd, abi_msa_bfd, ibfd,
+ "-mmsa", in_attr[Tag_GNU_MIPS_ABI_MSA].i);
break;
default:
- switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
+ switch (in_attr[Tag_GNU_MIPS_ABI_MSA].i)
{
- case Val_GNU_MIPS_ABI_FP_DOUBLE:
- _bfd_error_handler
- (_("Warning: %B uses unknown floating point ABI %d "
- "(set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd,
- out_attr[Tag_GNU_MIPS_ABI_FP].i, "-mdouble-float");
- break;
-
- case Val_GNU_MIPS_ABI_FP_SINGLE:
+ case Val_GNU_MIPS_ABI_MSA_128:
_bfd_error_handler
- (_("Warning: %B uses unknown floating point ABI %d "
+ (_("Warning: %B uses unknown MSA ABI %d "
"(set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd,
- out_attr[Tag_GNU_MIPS_ABI_FP].i, "-msingle-float");
- break;
-
- case Val_GNU_MIPS_ABI_FP_SOFT:
- _bfd_error_handler
- (_("Warning: %B uses unknown floating point ABI %d "
- "(set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd,
- out_attr[Tag_GNU_MIPS_ABI_FP].i, "-msoft-float");
- break;
-
- case Val_GNU_MIPS_ABI_FP_64:
- _bfd_error_handler
- (_("Warning: %B uses unknown floating point ABI %d "
- "(set by %B), %B uses %s"),
- obfd, abi_fp_bfd, ibfd,
- out_attr[Tag_GNU_MIPS_ABI_FP].i, "-mips32r2 -mfp64");
- break;
+ obfd, abi_msa_bfd, ibfd,
+ out_attr[Tag_GNU_MIPS_ABI_MSA].i, "-mmsa");
+ break;
default:
_bfd_error_handler
- (_("Warning: %B uses unknown floating point ABI %d "
- "(set by %B), %B uses unknown floating point ABI %d"),
- obfd, abi_fp_bfd, ibfd,
- out_attr[Tag_GNU_MIPS_ABI_FP].i,
- in_attr[Tag_GNU_MIPS_ABI_FP].i);
+ (_("Warning: %B uses unknown MSA ABI %d "
+ "(set by %B), %B uses unknown MSA ABI %d"),
+ obfd, abi_msa_bfd, ibfd,
+ out_attr[Tag_GNU_MIPS_ABI_MSA].i,
+ in_attr[Tag_GNU_MIPS_ABI_MSA].i);
break;
}
- break;
}
}
@@ -14526,6 +14962,7 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
bfd_boolean ok;
bfd_boolean null_input_bfd = TRUE;
asection *sec;
+ obj_attribute *out_attr;
/* Check if we have the same endianness. */
if (! _bfd_generic_verify_endian_match (ibfd, obfd))
@@ -14547,17 +14984,98 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
return FALSE;
}
+ /* Set up the FP ABI attribute from the abiflags if it is not already
+ set. */
+ if (mips_elf_tdata (ibfd)->abiflags_valid)
+ {
+ obj_attribute *in_attr = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
+ if (in_attr[Tag_GNU_MIPS_ABI_FP].i == Val_GNU_MIPS_ABI_FP_ANY)
+ in_attr[Tag_GNU_MIPS_ABI_FP].i =
+ mips_elf_tdata (ibfd)->abiflags.fp_abi;
+ }
+
if (!mips_elf_merge_obj_attributes (ibfd, obfd))
return FALSE;
- new_flags = elf_elfheader (ibfd)->e_flags;
- elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
- old_flags = elf_elfheader (obfd)->e_flags;
+ /* Check to see if the input BFD actually contains any sections.
+ If not, its flags may not have been initialised either, but it cannot
+ actually cause any incompatibility. */
+ for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+ {
+ /* Ignore synthetic sections and empty .text, .data and .bss sections
+ which are automatically generated by gas. Also ignore fake
+ (s)common sections, since merely defining a common symbol does
+ not affect compatibility. */
+ if ((sec->flags & SEC_IS_COMMON) == 0
+ && strcmp (sec->name, ".reginfo")
+ && strcmp (sec->name, ".mdebug")
+ && (sec->size != 0
+ || (strcmp (sec->name, ".text")
+ && strcmp (sec->name, ".data")
+ && strcmp (sec->name, ".bss"))))
+ {
+ null_input_bfd = FALSE;
+ break;
+ }
+ }
+ if (null_input_bfd)
+ return TRUE;
+
+ /* Populate abiflags using existing information. */
+ if (!mips_elf_tdata (ibfd)->abiflags_valid)
+ {
+ infer_mips_abiflags (ibfd, &mips_elf_tdata (ibfd)->abiflags);
+ mips_elf_tdata (ibfd)->abiflags_valid = TRUE;
+ }
+ else
+ {
+ Elf_Internal_ABIFlags_v0 abiflags;
+ Elf_Internal_ABIFlags_v0 in_abiflags;
+ infer_mips_abiflags (ibfd, &abiflags);
+ in_abiflags = mips_elf_tdata (ibfd)->abiflags;
+
+ /* It is not possible to infer the correct ISA revision
+ for R3 or R5 so drop down to R2 for the checks. */
+ if (in_abiflags.isa_rev == 3 || in_abiflags.isa_rev == 5)
+ in_abiflags.isa_rev = 2;
+
+ if (in_abiflags.isa_level != abiflags.isa_level
+ || in_abiflags.isa_rev != abiflags.isa_rev
+ || in_abiflags.isa_ext != abiflags.isa_ext)
+ (*_bfd_error_handler)
+ (_("%B: warning: Inconsistent ISA between e_flags and "
+ ".MIPS.abiflags"), ibfd);
+ if (abiflags.fp_abi != Val_GNU_MIPS_ABI_FP_ANY
+ && in_abiflags.fp_abi != abiflags.fp_abi)
+ (*_bfd_error_handler)
+ (_("%B: warning: Inconsistent FP ABI between e_flags and "
+ ".MIPS.abiflags"), ibfd);
+ if ((in_abiflags.ases & abiflags.ases) != abiflags.ases)
+ (*_bfd_error_handler)
+ (_("%B: warning: Inconsistent ASEs between e_flags and "
+ ".MIPS.abiflags"), ibfd);
+ if (in_abiflags.isa_ext != abiflags.isa_ext)
+ (*_bfd_error_handler)
+ (_("%B: warning: Inconsistent ISA extensions between e_flags and "
+ ".MIPS.abiflags"), ibfd);
+ if (in_abiflags.flags2 != 0)
+ (*_bfd_error_handler)
+ (_("%B: warning: Unexpected flag in the flags2 field of "
+ ".MIPS.abiflags (0x%lx)"), ibfd,
+ (unsigned long) in_abiflags.flags2);
+ }
+
+ if (!mips_elf_tdata (obfd)->abiflags_valid)
+ {
+ /* Copy input abiflags if output abiflags are not already valid. */
+ mips_elf_tdata (obfd)->abiflags = mips_elf_tdata (ibfd)->abiflags;
+ mips_elf_tdata (obfd)->abiflags_valid = TRUE;
+ }
if (! elf_flags_init (obfd))
{
elf_flags_init (obfd) = TRUE;
- elf_elfheader (obfd)->e_flags = new_flags;
+ elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
elf_elfheader (obfd)->e_ident[EI_CLASS]
= elf_elfheader (ibfd)->e_ident[EI_CLASS];
@@ -14569,11 +15087,42 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
bfd_get_mach (ibfd)))
return FALSE;
+
+ /* Update the ABI flags isa_level, isa_rev and isa_ext fields. */
+ update_mips_abiflags_isa (obfd, &mips_elf_tdata (obfd)->abiflags);
}
return TRUE;
}
+ /* Update the output abiflags fp_abi using the computed fp_abi. */
+ out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
+ mips_elf_tdata (obfd)->abiflags.fp_abi = out_attr[Tag_GNU_MIPS_ABI_FP].i;
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+ /* Merge abiflags. */
+ mips_elf_tdata (obfd)->abiflags.isa_rev
+ = max (mips_elf_tdata (obfd)->abiflags.isa_rev,
+ mips_elf_tdata (ibfd)->abiflags.isa_rev);
+ mips_elf_tdata (obfd)->abiflags.gpr_size
+ = max (mips_elf_tdata (obfd)->abiflags.gpr_size,
+ mips_elf_tdata (ibfd)->abiflags.gpr_size);
+ mips_elf_tdata (obfd)->abiflags.cpr1_size
+ = max (mips_elf_tdata (obfd)->abiflags.cpr1_size,
+ mips_elf_tdata (ibfd)->abiflags.cpr1_size);
+ mips_elf_tdata (obfd)->abiflags.cpr2_size
+ = max (mips_elf_tdata (obfd)->abiflags.cpr2_size,
+ mips_elf_tdata (ibfd)->abiflags.cpr2_size);
+#undef max
+ mips_elf_tdata (obfd)->abiflags.ases
+ |= mips_elf_tdata (ibfd)->abiflags.ases;
+ mips_elf_tdata (obfd)->abiflags.flags1
+ |= mips_elf_tdata (ibfd)->abiflags.flags1;
+
+ new_flags = elf_elfheader (ibfd)->e_flags;
+ elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
+ old_flags = elf_elfheader (obfd)->e_flags;
+
/* Check flag compatibility. */
new_flags &= ~EF_MIPS_NOREORDER;
@@ -14596,30 +15145,6 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
if (new_flags == old_flags)
return TRUE;
- /* Check to see if the input BFD actually contains any sections.
- If not, its flags may not have been initialised either, but it cannot
- actually cause any incompatibility. */
- for (sec = ibfd->sections; sec != NULL; sec = sec->next)
- {
- /* Ignore synthetic sections and empty .text, .data and .bss sections
- which are automatically generated by gas. Also ignore fake
- (s)common sections, since merely defining a common symbol does
- not affect compatibility. */
- if ((sec->flags & SEC_IS_COMMON) == 0
- && strcmp (sec->name, ".reginfo")
- && strcmp (sec->name, ".mdebug")
- && (sec->size != 0
- || (strcmp (sec->name, ".text")
- && strcmp (sec->name, ".data")
- && strcmp (sec->name, ".bss"))))
- {
- null_input_bfd = FALSE;
- break;
- }
- }
- if (null_input_bfd)
- return TRUE;
-
ok = TRUE;
if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)
@@ -14660,6 +15185,9 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
elf_elfheader (obfd)->e_flags
|= new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
+ /* Update the ABI flags isa_level, isa_rev, isa_ext fields. */
+ update_mips_abiflags_isa (obfd, &mips_elf_tdata (obfd)->abiflags);
+
/* Copy across the ABI flags if OBFD doesn't use them
and if that was what caused us to treat IBFD as 32-bit. */
if ((old_flags & EF_MIPS_ABI) == 0
@@ -14745,6 +15273,20 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
old_flags &= ~EF_MIPS_NAN2008;
}
+ /* Compare FP64 state. */
+ if ((new_flags & EF_MIPS_FP64) != (old_flags & EF_MIPS_FP64))
+ {
+ _bfd_error_handler (_("%B: linking %s module with previous %s modules"),
+ ibfd,
+ (new_flags & EF_MIPS_FP64
+ ? "-mfp64" : "-mfp32"),
+ (old_flags & EF_MIPS_FP64
+ ? "-mfp64" : "-mfp32"));
+ ok = FALSE;
+ new_flags &= ~EF_MIPS_FP64;
+ old_flags &= ~EF_MIPS_FP64;
+ }
+
/* Warn about any other mismatches */
if (new_flags != old_flags)
{
@@ -14876,6 +15418,188 @@ _bfd_mips_elf_get_target_dtag (bfd_vma dtag)
}
}
+/* Return the meaning of Tag_GNU_MIPS_ABI_FP value FP, or null if
+ not known. */
+
+const char *
+_bfd_mips_fp_abi_string (int fp)
+{
+ switch (fp)
+ {
+ /* These strings aren't translated because they're simply
+ option lists. */
+ case Val_GNU_MIPS_ABI_FP_DOUBLE:
+ return "-mdouble-float";
+
+ case Val_GNU_MIPS_ABI_FP_SINGLE:
+ return "-msingle-float";
+
+ case Val_GNU_MIPS_ABI_FP_SOFT:
+ return "-msoft-float";
+
+ case Val_GNU_MIPS_ABI_FP_OLD_64:
+ return _("-mips32r2 -mfp64 (12 callee-saved)");
+
+ case Val_GNU_MIPS_ABI_FP_XX:
+ return "-mfpxx";
+
+ case Val_GNU_MIPS_ABI_FP_64:
+ return "-mgp32 -mfp64";
+
+ case Val_GNU_MIPS_ABI_FP_64A:
+ return "-mgp32 -mfp64 -mno-odd-spreg";
+
+ default:
+ return 0;
+ }
+}
+
+static void
+print_mips_ases (FILE *file, unsigned int mask)
+{
+ if (mask & AFL_ASE_DSP)
+ fputs ("\n\tDSP ASE", file);
+ if (mask & AFL_ASE_DSPR2)
+ fputs ("\n\tDSP R2 ASE", file);
+ if (mask & AFL_ASE_EVA)
+ fputs ("\n\tEnhanced VA Scheme", file);
+ if (mask & AFL_ASE_MCU)
+ fputs ("\n\tMCU (MicroController) ASE", file);
+ if (mask & AFL_ASE_MDMX)
+ fputs ("\n\tMDMX ASE", file);
+ if (mask & AFL_ASE_MIPS3D)
+ fputs ("\n\tMIPS-3D ASE", file);
+ if (mask & AFL_ASE_MT)
+ fputs ("\n\tMT ASE", file);
+ if (mask & AFL_ASE_SMARTMIPS)
+ fputs ("\n\tSmartMIPS ASE", file);
+ if (mask & AFL_ASE_VIRT)
+ fputs ("\n\tVZ ASE", file);
+ if (mask & AFL_ASE_MSA)
+ fputs ("\n\tMSA ASE", file);
+ if (mask & AFL_ASE_MIPS16)
+ fputs ("\n\tMIPS16 ASE", file);
+ if (mask & AFL_ASE_MICROMIPS)
+ fputs ("\n\tMICROMIPS ASE", file);
+ if (mask & AFL_ASE_XPA)
+ fputs ("\n\tXPA ASE", file);
+ if (mask == 0)
+ fprintf (file, "\n\t%s", _("None"));
+}
+
+static void
+print_mips_isa_ext (FILE *file, unsigned int isa_ext)
+{
+ switch (isa_ext)
+ {
+ case 0:
+ fputs (_("None"), file);
+ break;
+ case AFL_EXT_XLR:
+ fputs ("RMI XLR", file);
+ break;
+ case AFL_EXT_OCTEON2:
+ fputs ("Cavium Networks Octeon2", file);
+ break;
+ case AFL_EXT_OCTEONP:
+ fputs ("Cavium Networks OcteonP", file);
+ break;
+ case AFL_EXT_LOONGSON_3A:
+ fputs ("Loongson 3A", file);
+ break;
+ case AFL_EXT_OCTEON:
+ fputs ("Cavium Networks Octeon", file);
+ break;
+ case AFL_EXT_5900:
+ fputs ("Toshiba R5900", file);
+ break;
+ case AFL_EXT_4650:
+ fputs ("MIPS R4650", file);
+ break;
+ case AFL_EXT_4010:
+ fputs ("LSI R4010", file);
+ break;
+ case AFL_EXT_4100:
+ fputs ("NEC VR4100", file);
+ break;
+ case AFL_EXT_3900:
+ fputs ("Toshiba R3900", file);
+ break;
+ case AFL_EXT_10000:
+ fputs ("MIPS R10000", file);
+ break;
+ case AFL_EXT_SB1:
+ fputs ("Broadcom SB-1", file);
+ break;
+ case AFL_EXT_4111:
+ fputs ("NEC VR4111/VR4181", file);
+ break;
+ case AFL_EXT_4120:
+ fputs ("NEC VR4120", file);
+ break;
+ case AFL_EXT_5400:
+ fputs ("NEC VR5400", file);
+ break;
+ case AFL_EXT_5500:
+ fputs ("NEC VR5500", file);
+ break;
+ case AFL_EXT_LOONGSON_2E:
+ fputs ("ST Microelectronics Loongson 2E", file);
+ break;
+ case AFL_EXT_LOONGSON_2F:
+ fputs ("ST Microelectronics Loongson 2F", file);
+ break;
+ default:
+ fputs (_("Unknown"), file);
+ break;
+ }
+}
+
+static void
+print_mips_fp_abi_value (FILE *file, int val)
+{
+ switch (val)
+ {
+ case Val_GNU_MIPS_ABI_FP_ANY:
+ fprintf (file, _("Hard or soft float\n"));
+ break;
+ case Val_GNU_MIPS_ABI_FP_DOUBLE:
+ fprintf (file, _("Hard float (double precision)\n"));
+ break;
+ case Val_GNU_MIPS_ABI_FP_SINGLE:
+ fprintf (file, _("Hard float (single precision)\n"));
+ break;
+ case Val_GNU_MIPS_ABI_FP_SOFT:
+ fprintf (file, _("Soft float\n"));
+ break;
+ case Val_GNU_MIPS_ABI_FP_OLD_64:
+ fprintf (file, _("Hard float (MIPS32r2 64-bit FPU 12 callee-saved)\n"));
+ break;
+ case Val_GNU_MIPS_ABI_FP_XX:
+ fprintf (file, _("Hard float (32-bit CPU, Any FPU)\n"));
+ break;
+ case Val_GNU_MIPS_ABI_FP_64:
+ fprintf (file, _("Hard float (32-bit CPU, 64-bit FPU)\n"));
+ break;
+ case Val_GNU_MIPS_ABI_FP_64A:
+ fprintf (file, _("Hard float compat (32-bit CPU, 64-bit FPU)\n"));
+ break;
+ default:
+ fprintf (file, "??? (%d)\n", val);
+ break;
+ }
+}
+
+static int
+get_mips_reg_size (int reg_size)
+{
+ return (reg_size == AFL_REG_NONE) ? 0
+ : (reg_size == AFL_REG_32) ? 32
+ : (reg_size == AFL_REG_64) ? 64
+ : (reg_size == AFL_REG_128) ? 128
+ : -1;
+}
+
bfd_boolean
_bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
{
@@ -14924,6 +15648,10 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
fprintf (file, " [mips32r2]");
else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R2)
fprintf (file, " [mips64r2]");
+ else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6)
+ fprintf (file, " [mips32r6]");
+ else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R6)
+ fprintf (file, " [mips64r6]");
else
fprintf (file, _(" [unknown ISA]"));
@@ -14940,7 +15668,7 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
fprintf (file, " [nan2008]");
if (elf_elfheader (abfd)->e_flags & EF_MIPS_FP64)
- fprintf (file, " [fp64]");
+ fprintf (file, " [old fp64]");
if (elf_elfheader (abfd)->e_flags & EF_MIPS_32BITMODE)
fprintf (file, " [32bitmode]");
@@ -14964,6 +15692,30 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
fputc ('\n', file);
+ if (mips_elf_tdata (abfd)->abiflags_valid)
+ {
+ Elf_Internal_ABIFlags_v0 *abiflags = &mips_elf_tdata (abfd)->abiflags;
+ fprintf (file, "\nMIPS ABI Flags Version: %d\n", abiflags->version);
+ fprintf (file, "\nISA: MIPS%d", abiflags->isa_level);
+ if (abiflags->isa_rev > 1)
+ fprintf (file, "r%d", abiflags->isa_rev);
+ fprintf (file, "\nGPR size: %d",
+ get_mips_reg_size (abiflags->gpr_size));
+ fprintf (file, "\nCPR1 size: %d",
+ get_mips_reg_size (abiflags->cpr1_size));
+ fprintf (file, "\nCPR2 size: %d",
+ get_mips_reg_size (abiflags->cpr2_size));
+ fputs ("\nFP ABI: ", file);
+ print_mips_fp_abi_value (file, abiflags->fp_abi);
+ fputs ("ISA Extension: ", file);
+ print_mips_isa_ext (file, abiflags->isa_ext);
+ fputs ("\nASEs:", file);
+ print_mips_ases (file, abiflags->ases);
+ fprintf (file, "\nFLAGS 1: %8.8lx", abiflags->flags1);
+ fprintf (file, "\nFLAGS 2: %8.8lx", abiflags->flags2);
+ fputc ('\n', file);
+ }
+
return TRUE;
}
@@ -15284,4 +16036,8 @@ _bfd_mips_post_process_headers (bfd *abfd, struct bfd_link_info *link_info)
if (htab->use_plts_and_copy_relocs && !htab->is_vxworks)
i_ehdrp->e_ident[EI_ABIVERSION] = 1;
}
+
+ if (mips_elf_tdata (abfd)->abiflags.fp_abi == Val_GNU_MIPS_ABI_FP_64
+ || mips_elf_tdata (abfd)->abiflags.fp_abi == Val_GNU_MIPS_ABI_FP_64A)
+ i_ehdrp->e_ident[EI_ABIVERSION] = 3;
}
diff --git a/binutils-2.24/bfd/elfxx-mips.h b/binutils-2.24/bfd/elfxx-mips.h
index f27dc15..9814e7a 100644
--- a/binutils-2.24/bfd/elfxx-mips.h
+++ b/binutils-2.24/bfd/elfxx-mips.h
@@ -109,6 +109,8 @@ extern bfd_boolean _bfd_mips_elf_merge_private_bfd_data
(bfd *, bfd *);
extern bfd_boolean _bfd_mips_elf_set_private_flags
(bfd *, flagword);
+extern const char * _bfd_mips_fp_abi_string
+ (int);
extern bfd_boolean _bfd_mips_elf_print_private_bfd_data
(bfd *, void *);
extern bfd_boolean _bfd_mips_elf_discard_info
@@ -156,6 +158,8 @@ extern bfd_vma _bfd_mips_elf_plt_sym_val
(bfd_vma, const asection *, const arelent *rel);
extern long _bfd_mips_elf_get_synthetic_symtab
(bfd *, long, asymbol **, long, asymbol **, asymbol **);
+extern bfd_boolean _bfd_mips_elf_gc_mark_extra_sections
+ (struct bfd_link_info *, elf_gc_mark_hook_fn);
extern void _bfd_mips_post_process_headers
(bfd *abfd, struct bfd_link_info *link_info);
diff --git a/binutils-2.24/bfd/libbfd.h b/binutils-2.24/bfd/libbfd.h
index 4aaecbf..e29839b 100644
--- a/binutils-2.24/bfd/libbfd.h
+++ b/binutils-2.24/bfd/libbfd.h
@@ -1128,6 +1128,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_MICROMIPS_7_PCREL_S1",
"BFD_RELOC_MICROMIPS_10_PCREL_S1",
"BFD_RELOC_MICROMIPS_16_PCREL_S1",
+ "BFD_RELOC_MIPS_21_PCREL_S2",
+ "BFD_RELOC_MIPS_26_PCREL_S2",
+ "BFD_RELOC_MIPS_18_PCREL_S3",
+ "BFD_RELOC_MIPS_19_PCREL_S2",
"BFD_RELOC_MICROMIPS_GPREL16",
"BFD_RELOC_MICROMIPS_HI16",
"BFD_RELOC_MICROMIPS_HI16_S",
diff --git a/binutils-2.24/bfd/reloc.c b/binutils-2.24/bfd/reloc.c
index 77a04f8..8151d9b 100644
--- a/binutils-2.24/bfd/reloc.c
+++ b/binutils-2.24/bfd/reloc.c
@@ -2293,6 +2293,17 @@ ENUMDOC
microMIPS PC-relative relocations.
ENUM
+ BFD_RELOC_MIPS_21_PCREL_S2
+ENUMX
+ BFD_RELOC_MIPS_26_PCREL_S2
+ENUMX
+ BFD_RELOC_MIPS_18_PCREL_S3
+ENUMX
+ BFD_RELOC_MIPS_19_PCREL_S2
+ENUMDOC
+ MIPS PC-relative relocations.
+
+ENUM
BFD_RELOC_MICROMIPS_GPREL16
ENUMX
BFD_RELOC_MICROMIPS_HI16