summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--binutils-2.24/gold/i386.cc127
-rw-r--r--binutils-2.24/gold/testsuite/Makefile.am56
-rwxr-xr-xbinutils-2.24/gold/testsuite/i386_mov_to_lea.sh36
-rw-r--r--binutils-2.24/gold/testsuite/i386_mov_to_lea1.s11
-rw-r--r--binutils-2.24/gold/testsuite/i386_mov_to_lea2.s10
-rw-r--r--binutils-2.24/gold/testsuite/i386_mov_to_lea3.s4
-rw-r--r--binutils-2.24/gold/testsuite/i386_mov_to_lea4.s12
-rw-r--r--binutils-2.24/gold/testsuite/i386_mov_to_lea5.s12
-rw-r--r--binutils-2.25/gold/ChangeLog20
-rw-r--r--binutils-2.25/gold/aarch64.cc585
-rw-r--r--binutils-2.25/gold/i386.cc127
-rw-r--r--binutils-2.25/gold/options.h8
-rw-r--r--binutils-2.25/gold/testsuite/Makefile.am56
-rwxr-xr-xbinutils-2.25/gold/testsuite/i386_mov_to_lea.sh36
-rw-r--r--binutils-2.25/gold/testsuite/i386_mov_to_lea1.s11
-rw-r--r--binutils-2.25/gold/testsuite/i386_mov_to_lea2.s10
-rw-r--r--binutils-2.25/gold/testsuite/i386_mov_to_lea3.s4
-rw-r--r--binutils-2.25/gold/testsuite/i386_mov_to_lea4.s12
-rw-r--r--binutils-2.25/gold/testsuite/i386_mov_to_lea5.s12
19 files changed, 1078 insertions, 71 deletions
diff --git a/binutils-2.24/gold/i386.cc b/binutils-2.24/gold/i386.cc
index 6a3280df..29005668 100644
--- a/binutils-2.24/gold/i386.cc
+++ b/binutils-2.24/gold/i386.cc
@@ -716,6 +716,26 @@ class Target_i386 : public Sized_target<32, false>
static tls::Tls_optimization
optimize_tls_reloc(bool is_final, int r_type);
+ // Check if relocation against this symbol is a candidate for
+ // conversion from
+ // mov foo@GOT(%reg), %reg
+ // to
+ // lea foo@GOTOFF(%reg), %reg.
+ static bool
+ can_convert_mov_to_lea(const Symbol* gsym)
+ {
+ gold_assert(gsym != NULL);
+ return (gsym->type() != elfcpp::STT_GNU_IFUNC
+ && !gsym->is_undefined ()
+ && !gsym->is_from_dynobj()
+ && !gsym->is_preemptible()
+ && (!parameters->options().shared()
+ || (gsym->visibility() != elfcpp::STV_DEFAULT
+ && gsym->visibility() != elfcpp::STV_PROTECTED)
+ || parameters->options().Bsymbolic())
+ && strcmp(gsym->name(), "_DYNAMIC") != 0);
+ }
+
// Get the GOT section, creating it if necessary.
Output_data_got<32, false>*
got_section(Symbol_table*, Layout*);
@@ -1800,8 +1820,26 @@ Target_i386::Scan::local(Symbol_table* symtab,
case elfcpp::R_386_GOT32:
{
- // The symbol requires a GOT entry.
+ // We need GOT section.
Output_data_got<32, false>* got = target->got_section(symtab, layout);
+
+ // If the relocation symbol isn't IFUNC,
+ // and is local, then we will convert
+ // mov foo@GOT(%reg), %reg
+ // to
+ // lea foo@GOTOFF(%reg), %reg
+ // in Relocate::relocate.
+ if (reloc.get_r_offset() >= 2
+ && lsym.get_st_type() != elfcpp::STT_GNU_IFUNC)
+ {
+ section_size_type stype;
+ const unsigned char* view = object->section_contents(data_shndx,
+ &stype, true);
+ if (view[reloc.get_r_offset() - 2] == 0x8b)
+ break;
+ }
+
+ // Otherwise, the symbol requires a GOT entry.
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
// For a STT_GNU_IFUNC symbol we want the PLT offset. That
@@ -2192,8 +2230,24 @@ Target_i386::Scan::global(Symbol_table* symtab,
case elfcpp::R_386_GOT32:
{
- // The symbol requires a GOT entry.
+ // The symbol requires a GOT section.
Output_data_got<32, false>* got = target->got_section(symtab, layout);
+
+ // If we convert this from
+ // mov foo@GOT(%reg), %reg
+ // to
+ // lea foo@GOTOFF(%reg), %reg
+ // in Relocate::relocate, then there is nothing to do here.
+ if (reloc.get_r_offset() >= 2
+ && Target_i386::can_convert_mov_to_lea(gsym))
+ {
+ section_size_type stype;
+ const unsigned char* view = object->section_contents(data_shndx,
+ &stype, true);
+ if (view[reloc.get_r_offset() - 2] == 0x8b)
+ break;
+ }
+
if (gsym->final_value_is_known())
{
// For a STT_GNU_IFUNC symbol we want the PLT address.
@@ -2695,35 +2749,6 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
}
}
- // Get the GOT offset if needed.
- // The GOT pointer points to the end of the GOT section.
- // We need to subtract the size of the GOT section to get
- // the actual offset to use in the relocation.
- bool have_got_offset = false;
- unsigned int got_offset = 0;
- switch (r_type)
- {
- case elfcpp::R_386_GOT32:
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
- got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
- - target->got_size());
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
- got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
- - target->got_size());
- }
- have_got_offset = true;
- break;
-
- default:
- break;
- }
-
switch (r_type)
{
case elfcpp::R_386_NONE:
@@ -2772,8 +2797,44 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
break;
case elfcpp::R_386_GOT32:
- gold_assert(have_got_offset);
- Relocate_functions<32, false>::rel32(view, got_offset);
+ // Convert
+ // mov foo@GOT(%reg), %reg
+ // to
+ // lea foo@GOTOFF(%reg), %reg
+ // if possible.
+ if (rel.get_r_offset() >= 2
+ && view[-2] == 0x8b
+ && ((gsym == NULL && !psymval->is_ifunc_symbol())
+ || (gsym != NULL
+ && Target_i386::can_convert_mov_to_lea(gsym))))
+ {
+ view[-2] = 0x8d;
+ elfcpp::Elf_types<32>::Elf_Addr value;
+ value = (psymval->value(object, 0)
+ - target->got_plt_section()->address());
+ Relocate_functions<32, false>::rel32(view, value);
+ }
+ else
+ {
+ // The GOT pointer points to the end of the GOT section.
+ // We need to subtract the size of the GOT section to get
+ // the actual offset to use in the relocation.
+ unsigned int got_offset = 0;
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+ got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
+ - target->got_size());
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+ - target->got_size());
+ }
+ Relocate_functions<32, false>::rel32(view, got_offset);
+ }
break;
case elfcpp::R_386_GOTOFF:
diff --git a/binutils-2.24/gold/testsuite/Makefile.am b/binutils-2.24/gold/testsuite/Makefile.am
index d57730ea..bb78b845 100644
--- a/binutils-2.24/gold/testsuite/Makefile.am
+++ b/binutils-2.24/gold/testsuite/Makefile.am
@@ -909,6 +909,62 @@ endif FN_PTRS_IN_SO_WITHOUT_PIC
endif TLS
+if DEFAULT_TARGET_I386
+
+check_SCRIPTS += i386_mov_to_lea.sh
+check_DATA += i386_mov_to_lea1.stdout i386_mov_to_lea2.stdout \
+ i386_mov_to_lea3.stdout i386_mov_to_lea4.stdout \
+ i386_mov_to_lea5.stdout i386_mov_to_lea6.stdout \
+ i386_mov_to_lea7.stdout i386_mov_to_lea8.stdout
+MOSTLYCLEANFILES += i386_mov_to_lea1 i386_mov_to_lea2 i386_mov_to_lea3 \
+ i386_mov_to_lea4 i386_mov_to_lea5 i386_mov_to_lea6 \
+ i386_mov_to_lea7 i386_mov_to_lea8
+
+i386_mov_to_lea1.o: i386_mov_to_lea1.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea2.o: i386_mov_to_lea2.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea3.o: i386_mov_to_lea3.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea4.o: i386_mov_to_lea4.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea5.o: i386_mov_to_lea5.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea1: i386_mov_to_lea1.o
+ ../ld-new -Bsymbolic -shared -melf_i386 -o $@ $<
+i386_mov_to_lea2: i386_mov_to_lea1.o
+ ../ld-new -pie -melf_i386 -o $@ $<
+i386_mov_to_lea3: i386_mov_to_lea1.o
+ ../ld-new -melf_i386 -o $@ $<
+i386_mov_to_lea4: i386_mov_to_lea1.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea5: i386_mov_to_lea2.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea6: i386_mov_to_lea3.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea7: i386_mov_to_lea4.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea8: i386_mov_to_lea5.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea1.stdout: i386_mov_to_lea1
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea2.stdout: i386_mov_to_lea2
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea3.stdout: i386_mov_to_lea3
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea4.stdout: i386_mov_to_lea4
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea5.stdout: i386_mov_to_lea5
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea6.stdout: i386_mov_to_lea6
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea7.stdout: i386_mov_to_lea7
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea8.stdout: i386_mov_to_lea8
+ $(TEST_OBJDUMP) -dw $< > $@
+
+endif DEFAULT_TARGET_I386
+
check_PROGRAMS += many_sections_test
many_sections_test_SOURCES = many_sections_test.cc
many_sections_test_DEPENDENCIES = gcctestdir/ld
diff --git a/binutils-2.24/gold/testsuite/i386_mov_to_lea.sh b/binutils-2.24/gold/testsuite/i386_mov_to_lea.sh
new file mode 100755
index 00000000..03703729
--- /dev/null
+++ b/binutils-2.24/gold/testsuite/i386_mov_to_lea.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# i386_mov_to_lea.sh -- a test for mov2lea conversion.
+
+# Copyright (C) 2010-2015 Free Software Foundation, Inc.
+# Written by Tocar Ilya <ilya.tocar@intel.com>
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+set -e
+
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea1.stdout
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea2.stdout
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea3.stdout
+grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea4.stdout
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea5.stdout
+grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea6.stdout
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea7.stdout
+grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea8.stdout
+
+exit 0
diff --git a/binutils-2.24/gold/testsuite/i386_mov_to_lea1.s b/binutils-2.24/gold/testsuite/i386_mov_to_lea1.s
new file mode 100644
index 00000000..6d0f436e
--- /dev/null
+++ b/binutils-2.24/gold/testsuite/i386_mov_to_lea1.s
@@ -0,0 +1,11 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+ .type bar, @function
+bar:
+ movl foo@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/binutils-2.24/gold/testsuite/i386_mov_to_lea2.s b/binutils-2.24/gold/testsuite/i386_mov_to_lea2.s
new file mode 100644
index 00000000..65f1bfd7
--- /dev/null
+++ b/binutils-2.24/gold/testsuite/i386_mov_to_lea2.s
@@ -0,0 +1,10 @@
+ .text
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+ .type bar, @function
+bar:
+ movl foo@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/binutils-2.24/gold/testsuite/i386_mov_to_lea3.s b/binutils-2.24/gold/testsuite/i386_mov_to_lea3.s
new file mode 100644
index 00000000..6785e71c
--- /dev/null
+++ b/binutils-2.24/gold/testsuite/i386_mov_to_lea3.s
@@ -0,0 +1,4 @@
+ .type bar, @function
+bar:
+ movl _DYNAMIC@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/binutils-2.24/gold/testsuite/i386_mov_to_lea4.s b/binutils-2.24/gold/testsuite/i386_mov_to_lea4.s
new file mode 100644
index 00000000..7e4c4db6
--- /dev/null
+++ b/binutils-2.24/gold/testsuite/i386_mov_to_lea4.s
@@ -0,0 +1,12 @@
+ .text
+ .globl foo
+ .hidden foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+ .type bar, @function
+bar:
+ movl foo@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/binutils-2.24/gold/testsuite/i386_mov_to_lea5.s b/binutils-2.24/gold/testsuite/i386_mov_to_lea5.s
new file mode 100644
index 00000000..6999aae2
--- /dev/null
+++ b/binutils-2.24/gold/testsuite/i386_mov_to_lea5.s
@@ -0,0 +1,12 @@
+ .text
+ .globl foo
+ .protected foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+ .type bar, @function
+bar:
+ movl foo@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/binutils-2.25/gold/ChangeLog b/binutils-2.25/gold/ChangeLog
index b73da0a2..4e9aec03 100644
--- a/binutils-2.25/gold/ChangeLog
+++ b/binutils-2.25/gold/ChangeLog
@@ -1,3 +1,23 @@
+2015-04-27 Han Shen <shenhan@google.com>
+
+ * options.h (--fix-cortex-a53-843419): Rename option.
+ * aarch64.cc (AArch64_relobj::do_count_local_symbols): Use renamed
+ option.
+ (AArch64_relobj::scan_sections_for_stubs): Use renamed option.
+
+2015-04/16 Han Shen <shenhan@google.com>
+
+ * aarch64.cc (AArch64_insn_utilities): New utility class.
+ (AArch64_relobj::Mapping_symbol_position): New struct.
+ (AArch64_relobj::Mapping_symbol_info): New typedef.
+ (AArch64_relobj::do_count_local_symbols): New function overriding
+ parent's implementation.
+ (AArch64_relobj::mapping_symbol_info_): New member
+ (AArch64_relobj::scan_erratum_843419): New method.
+ (Target_aarch64::scan_erratum_843419_span): New method.
+ (Target_aarch64::is_erratum_843419_sequence): New method.
+ * options.h (fix_cortex_a53): New option.
+
2015-02-21 H.J. Lu <hongjiu.lu@intel.com>
* configure.ac (default_size): Set to 32 for x32.
diff --git a/binutils-2.25/gold/aarch64.cc b/binutils-2.25/gold/aarch64.cc
index 31176a4b..7498273c 100644
--- a/binutils-2.25/gold/aarch64.cc
+++ b/binutils-2.25/gold/aarch64.cc
@@ -23,6 +23,7 @@
#include "gold.h"
#include <cstring>
+#include <map>
#include "elfcpp.h"
#include "dwarf.h"
@@ -65,6 +66,273 @@ class Target_aarch64;
template<int size, bool big_endian>
class AArch64_relocate_functions;
+// Utility class dealing with insns. This is ported from macros in
+// bfd/elfnn-aarch64.cc, but wrapped inside a class as static members. This
+// class is used in erratum sequence scanning.
+
+template<bool big_endian>
+class AArch64_insn_utilities
+{
+public:
+ typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
+
+ static const int BYTES_PER_INSN = 4;
+
+ static unsigned int
+ aarch64_bit(Insntype insn, int pos)
+ { return ((1 << pos) & insn) >> pos; }
+
+ static unsigned int
+ aarch64_bits(Insntype insn, int pos, int l)
+ { return (insn >> pos) & ((1 << l) - 1); }
+
+ static bool
+ is_adrp(const Insntype insn)
+ { return (insn & 0x9F000000) == 0x90000000; }
+
+ static unsigned int
+ aarch64_rm(const Insntype insn)
+ { return aarch64_bits(insn, 16, 5); }
+
+ static unsigned int
+ aarch64_rn(const Insntype insn)
+ { return aarch64_bits(insn, 5, 5); }
+
+ static unsigned int
+ aarch64_rd(const Insntype insn)
+ { return aarch64_bits(insn, 0, 5); }
+
+ static unsigned int
+ aarch64_rt(const Insntype insn)
+ { return aarch64_bits(insn, 0, 5); }
+
+ static unsigned int
+ aarch64_rt2(const Insntype insn)
+ { return aarch64_bits(insn, 10, 5); }
+
+ static bool
+ aarch64_b(const Insntype insn)
+ { return (insn & 0xFC000000) == 0x14000000; }
+
+ static bool
+ aarch64_bl(const Insntype insn)
+ { return (insn & 0xFC000000) == 0x94000000; }
+
+ static bool
+ aarch64_blr(const Insntype insn)
+ { return (insn & 0xFFFFFC1F) == 0xD63F0000; }
+
+ static bool
+ aarch64_br(const Insntype insn)
+ { return (insn & 0xFFFFFC1F) == 0xD61F0000; }
+
+ // All ld/st ops. See C4-182 of the ARM ARM. The encoding space for
+ // LD_PCREL, LDST_RO, LDST_UI and LDST_UIMM cover prefetch ops.
+ static bool
+ aarch64_ld(Insntype insn) { return aarch64_bit(insn, 22) == 1; }
+
+ static bool
+ aarch64_ldst(Insntype insn)
+ { return (insn & 0x0a000000) == 0x08000000; }
+
+ static bool
+ aarch64_ldst_ex(Insntype insn)
+ { return (insn & 0x3f000000) == 0x08000000; }
+
+ static bool
+ aarch64_ldst_pcrel(Insntype insn)
+ { return (insn & 0x3b000000) == 0x18000000; }
+
+ static bool
+ aarch64_ldst_nap(Insntype insn)
+ { return (insn & 0x3b800000) == 0x28000000; }
+
+ static bool
+ aarch64_ldstp_pi(Insntype insn)
+ { return (insn & 0x3b800000) == 0x28800000; }
+
+ static bool
+ aarch64_ldstp_o(Insntype insn)
+ { return (insn & 0x3b800000) == 0x29000000; }
+
+ static bool
+ aarch64_ldstp_pre(Insntype insn)
+ { return (insn & 0x3b800000) == 0x29800000; }
+
+ static bool
+ aarch64_ldst_ui(Insntype insn)
+ { return (insn & 0x3b200c00) == 0x38000000; }
+
+ static bool
+ aarch64_ldst_piimm(Insntype insn)
+ { return (insn & 0x3b200c00) == 0x38000400; }
+
+ static bool
+ aarch64_ldst_u(Insntype insn)
+ { return (insn & 0x3b200c00) == 0x38000800; }
+
+ static bool
+ aarch64_ldst_preimm(Insntype insn)
+ { return (insn & 0x3b200c00) == 0x38000c00; }
+
+ static bool
+ aarch64_ldst_ro(Insntype insn)
+ { return (insn & 0x3b200c00) == 0x38200800; }
+
+ static bool
+ aarch64_ldst_uimm(Insntype insn)
+ { return (insn & 0x3b000000) == 0x39000000; }
+
+ static bool
+ aarch64_ldst_simd_m(Insntype insn)
+ { return (insn & 0xbfbf0000) == 0x0c000000; }
+
+ static bool
+ aarch64_ldst_simd_m_pi(Insntype insn)
+ { return (insn & 0xbfa00000) == 0x0c800000; }
+
+ static bool
+ aarch64_ldst_simd_s(Insntype insn)
+ { return (insn & 0xbf9f0000) == 0x0d000000; }
+
+ static bool
+ aarch64_ldst_simd_s_pi(Insntype insn)
+ { return (insn & 0xbf800000) == 0x0d800000; }
+
+ // Classify an INSN if it is indeed a load/store. Return true if INSN is a
+ // LD/ST instruction otherwise return false. For scalar LD/ST instructions
+ // PAIR is FALSE, RT is returned and RT2 is set equal to RT. For LD/ST pair
+ // instructions PAIR is TRUE, RT and RT2 are returned.
+ static bool
+ aarch64_mem_op_p(Insntype insn, unsigned int *rt, unsigned int *rt2,
+ bool *pair, bool *load)
+ {
+ uint32_t opcode;
+ unsigned int r;
+ uint32_t opc = 0;
+ uint32_t v = 0;
+ uint32_t opc_v = 0;
+
+ /* Bail out quickly if INSN doesn't fall into the the load-store
+ encoding space. */
+ if (!aarch64_ldst (insn))
+ return false;
+
+ *pair = false;
+ *load = false;
+ if (aarch64_ldst_ex (insn))
+ {
+ *rt = aarch64_rt (insn);
+ *rt2 = *rt;
+ if (aarch64_bit (insn, 21) == 1)
+ {
+ *pair = true;
+ *rt2 = aarch64_rt2 (insn);
+ }
+ *load = aarch64_ld (insn);
+ return true;
+ }
+ else if (aarch64_ldst_nap (insn)
+ || aarch64_ldstp_pi (insn)
+ || aarch64_ldstp_o (insn)
+ || aarch64_ldstp_pre (insn))
+ {
+ *pair = true;
+ *rt = aarch64_rt (insn);
+ *rt2 = aarch64_rt2 (insn);
+ *load = aarch64_ld (insn);
+ return true;
+ }
+ else if (aarch64_ldst_pcrel (insn)
+ || aarch64_ldst_ui (insn)
+ || aarch64_ldst_piimm (insn)
+ || aarch64_ldst_u (insn)
+ || aarch64_ldst_preimm (insn)
+ || aarch64_ldst_ro (insn)
+ || aarch64_ldst_uimm (insn))
+ {
+ *rt = aarch64_rt (insn);
+ *rt2 = *rt;
+ if (aarch64_ldst_pcrel (insn))
+ *load = true;
+ opc = aarch64_bits (insn, 22, 2);
+ v = aarch64_bit (insn, 26);
+ opc_v = opc | (v << 2);
+ *load = (opc_v == 1 || opc_v == 2 || opc_v == 3
+ || opc_v == 5 || opc_v == 7);
+ return true;
+ }
+ else if (aarch64_ldst_simd_m (insn)
+ || aarch64_ldst_simd_m_pi (insn))
+ {
+ *rt = aarch64_rt (insn);
+ *load = aarch64_bit (insn, 22);
+ opcode = (insn >> 12) & 0xf;
+ switch (opcode)
+ {
+ case 0:
+ case 2:
+ *rt2 = *rt + 3;
+ break;
+
+ case 4:
+ case 6:
+ *rt2 = *rt + 2;
+ break;
+
+ case 7:
+ *rt2 = *rt;
+ break;
+
+ case 8:
+ case 10:
+ *rt2 = *rt + 1;
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+ }
+ else if (aarch64_ldst_simd_s (insn)
+ || aarch64_ldst_simd_s_pi (insn))
+ {
+ *rt = aarch64_rt (insn);
+ r = (insn >> 21) & 1;
+ *load = aarch64_bit (insn, 22);
+ opcode = (insn >> 13) & 0x7;
+ switch (opcode)
+ {
+ case 0:
+ case 2:
+ case 4:
+ *rt2 = *rt + r;
+ break;
+
+ case 1:
+ case 3:
+ case 5:
+ *rt2 = *rt + (r == 0 ? 2 : 3);
+ break;
+
+ case 6:
+ *rt2 = *rt + r;
+ break;
+
+ case 7:
+ *rt2 = *rt + (r == 0 ? 2 : 3);
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+};
+
+
// Output_data_got_aarch64 class.
template<int size, bool big_endian>
@@ -916,7 +1184,14 @@ class AArch64_relobj : public Sized_relobj_file<size, big_endian>
this->stub_tables_[shndx] = stub_table;
}
- // Scan all relocation sections for stub generation.
+ // Entrance to erratum_843419 scanning.
+ void
+ scan_erratum_843419(unsigned int shndx,
+ const elfcpp::Shdr<size, big_endian>&,
+ Output_section*, const Symbol_table*,
+ The_target_aarch64*);
+
+ // Scan all relocation sections for stub generation.
void
scan_sections_for_stubs(The_target_aarch64*, const Symbol_table*,
const Layout*);
@@ -935,6 +1210,30 @@ class AArch64_relobj : public Sized_relobj_file<size, big_endian>
this->set_relocs_must_follow_section_writes();
}
+ // Structure for mapping symbol position.
+ struct Mapping_symbol_position
+ {
+ Mapping_symbol_position(unsigned int shndx, AArch64_address offset):
+ shndx_(shndx), offset_(offset)
+ {}
+
+ // "<" comparator used in ordered_map container.
+ bool
+ operator<(const Mapping_symbol_position& p) const
+ {
+ return (this->shndx_ < p.shndx_
+ || (this->shndx_ == p.shndx_ && this->offset_ < p.offset_));
+ }
+
+ // Section index.
+ unsigned int shndx_;
+
+ // Section offset.
+ AArch64_address offset_;
+ };
+
+ typedef std::map<Mapping_symbol_position, char> Mapping_symbol_info;
+
protected:
// Post constructor setup.
void
@@ -953,6 +1252,11 @@ class AArch64_relobj : public Sized_relobj_file<size, big_endian>
const unsigned char* pshdrs, Output_file* of,
typename Sized_relobj_file<size, big_endian>::Views* pviews);
+ // Count local symbols and (optionally) record mapping info.
+ virtual void
+ do_count_local_symbols(Stringpool_template<char>*,
+ Stringpool_template<char>*);
+
private:
// Whether a section needs to be scanned for relocation stubs.
bool
@@ -962,9 +1266,93 @@ class AArch64_relobj : public Sized_relobj_file<size, big_endian>
// List of stub tables.
Stub_table_list stub_tables_;
+
+ // Mapping symbol information sorted by (section index, section_offset).
+ Mapping_symbol_info mapping_symbol_info_;
}; // End of AArch64_relobj
+// Override to record mapping symbol information.
+template<int size, bool big_endian>
+void
+AArch64_relobj<size, big_endian>::do_count_local_symbols(
+ Stringpool_template<char>* pool, Stringpool_template<char>* dynpool)
+{
+ Sized_relobj_file<size, big_endian>::do_count_local_symbols(pool, dynpool);
+
+ // Only erratum-fixing work needs mapping symbols, so skip this time consuming
+ // processing if not fixing erratum.
+ if (!parameters->options().fix_cortex_a53_843419())
+ return;
+
+ const unsigned int loccount = this->local_symbol_count();
+ if (loccount == 0)
+ return;
+
+ // Read the symbol table section header.
+ const unsigned int symtab_shndx = this->symtab_shndx();
+ elfcpp::Shdr<size, big_endian>
+ symtabshdr(this, this->elf_file()->section_header(symtab_shndx));
+ gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
+
+ // Read the local symbols.
+ const int sym_size =elfcpp::Elf_sizes<size>::sym_size;
+ gold_assert(loccount == symtabshdr.get_sh_info());
+ off_t locsize = loccount * sym_size;
+ const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
+ locsize, true, true);
+
+ // For mapping symbol processing, we need to read the symbol names.
+ unsigned int strtab_shndx = this->adjust_shndx(symtabshdr.get_sh_link());
+ if (strtab_shndx >= this->shnum())
+ {
+ this->error(_("invalid symbol table name index: %u"), strtab_shndx);
+ return;
+ }
+
+ elfcpp::Shdr<size, big_endian>
+ strtabshdr(this, this->elf_file()->section_header(strtab_shndx));
+ if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
+ {
+ this->error(_("symbol table name section has wrong type: %u"),
+ static_cast<unsigned int>(strtabshdr.get_sh_type()));
+ return;
+ }
+
+ const char* pnames =
+ reinterpret_cast<const char*>(this->get_view(strtabshdr.get_sh_offset(),
+ strtabshdr.get_sh_size(),
+ false, false));
+
+ // Skip the first dummy symbol.
+ psyms += sym_size;
+ typename Sized_relobj_file<size, big_endian>::Local_values*
+ plocal_values = this->local_values();
+ for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
+ {
+ elfcpp::Sym<size, big_endian> sym(psyms);
+ Symbol_value<size>& lv((*plocal_values)[i]);
+ AArch64_address input_value = lv.input_value();
+
+ // Check to see if this is a mapping symbol.
+ const char* sym_name = pnames + sym.get_st_name();
+ if (sym_name[0] == '$' && (sym_name[1] == 'x' || sym_name[1] == 'd')
+ && sym_name[2] == '\0')
+ {
+ bool is_ordinary;
+ unsigned int input_shndx =
+ this->adjust_sym_shndx(i, sym.get_st_shndx(), &is_ordinary);
+ gold_assert(is_ordinary);
+
+ Mapping_symbol_position msp(input_shndx, input_value);
+ // Insert mapping_symbol_info into map whose ordering is defined by
+ // (shndx, offset_within_section).
+ this->mapping_symbol_info_[msp] = sym_name[1];
+ }
+ }
+}
+
+
// Relocate sections.
template<int size, bool big_endian>
@@ -1105,6 +1493,70 @@ AArch64_relobj<size, big_endian>::section_needs_reloc_stub_scanning(
}
+// Scan section SHNDX for erratum 843419.
+
+template<int size, bool big_endian>
+void
+AArch64_relobj<size, big_endian>::scan_erratum_843419(
+ unsigned int shndx, const elfcpp::Shdr<size, big_endian>& shdr,
+ Output_section* os, const Symbol_table* symtab,
+ The_target_aarch64* target)
+{
+ if (shdr.get_sh_size() == 0
+ || (shdr.get_sh_flags() &
+ (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR)) == 0
+ || shdr.get_sh_type() != elfcpp::SHT_PROGBITS)
+ return;
+
+ if (!os || symtab->is_section_folded(this, shndx)) return;
+
+ AArch64_address output_offset = this->get_output_section_offset(shndx);
+ AArch64_address output_address;
+ if (output_offset != invalid_address)
+ output_address = os->address() + output_offset;
+ else
+ {
+ const Output_relaxed_input_section* poris =
+ os->find_relaxed_input_section(this, shndx);
+ if (!poris) return;
+ output_address = poris->address();
+ }
+
+ section_size_type input_view_size = 0;
+ const unsigned char* input_view =
+ this->section_contents(shndx, &input_view_size, false);
+
+ Mapping_symbol_position section_start(shndx, 0);
+ // Find the first mapping symbol record within section shndx.
+ typename Mapping_symbol_info::const_iterator p =
+ this->mapping_symbol_info_.lower_bound(section_start);
+ if (p == this->mapping_symbol_info_.end() || p->first.shndx_ != shndx)
+ gold_warning(_("cannot scan executable section %u of %s for Cortex-A53 "
+ "erratum because it has no mapping symbols."),
+ shndx, this->name().c_str());
+ while (p != this->mapping_symbol_info_.end() &&
+ p->first.shndx_ == shndx)
+ {
+ typename Mapping_symbol_info::const_iterator prev = p;
+ ++p;
+ if (prev->second == 'x')
+ {
+ section_size_type span_start =
+ convert_to_section_size_type(prev->first.offset_);
+ section_size_type span_end;
+ if (p != this->mapping_symbol_info_.end()
+ && p->first.shndx_ == shndx)
+ span_end = convert_to_section_size_type(p->first.offset_);
+ else
+ span_end = convert_to_section_size_type(shdr.get_sh_size());
+ target->scan_erratum_843419_span(
+ this, shndx, span_start, span_end,
+ const_cast<unsigned char*>(input_view), output_address);
+ }
+ }
+}
+
+
// Scan relocations for stub generation.
template<int size, bool big_endian>
@@ -1138,6 +1590,8 @@ AArch64_relobj<size, big_endian>::scan_sections_for_stubs(
for (unsigned int i = 1; i < shnum; ++i, p += shdr_size)
{
const elfcpp::Shdr<size, big_endian> shdr(p);
+ if (parameters->options().fix_cortex_a53_843419())
+ scan_erratum_843419(i, shdr, out_sections[i], symtab, target);
if (this->section_needs_reloc_stub_scanning(shdr, out_sections, symtab,
pshdrs))
{
@@ -1644,6 +2098,7 @@ class Target_aarch64 : public Sized_target<size, big_endian>
typedef Unordered_map<Section_id,
AArch64_input_section<size, big_endian>*,
Section_id_hash> AArch64_input_section_map;
+ typedef AArch64_insn_utilities<big_endian> Insn_utilities;
const static int TCB_SIZE = size / 8 * 2;
Target_aarch64(const Target::Target_info* info = &aarch64_info)
@@ -1836,6 +2291,17 @@ class Target_aarch64 : public Sized_target<size, big_endian>
return static_cast<This*>(parameters->sized_target<size, big_endian>());
}
+
+ // Scan erratum for a part of a section.
+ void
+ scan_erratum_843419_span(
+ AArch64_relobj<size, big_endian>*,
+ unsigned int shndx,
+ const section_size_type,
+ const section_size_type,
+ unsigned char*,
+ Address);
+
protected:
void
do_select_as_default_target()
@@ -2129,6 +2595,12 @@ class Target_aarch64 : public Sized_target<size, big_endian>
return this->plt_;
}
+ // Return whether this is a 3-insn erratum sequence.
+ bool is_erratum_843419_sequence(
+ typename elfcpp::Swap<32,big_endian>::Valtype insn1,
+ typename elfcpp::Swap<32,big_endian>::Valtype insn2,
+ typename elfcpp::Swap<32,big_endian>::Valtype insn3);
+
// Get the dynamic reloc section, creating it if necessary.
Reloc_section*
rela_dyn_section(Layout*);
@@ -2560,7 +3032,7 @@ Target_aarch64<size, big_endian>::scan_reloc_for_stub(
typename The_reloc_stub::Stub_type stub_type = The_reloc_stub::
stub_type_for_reloc(r_type, address, destination);
if (stub_type == The_reloc_stub::ST_NONE)
- return ;
+ return;
The_stub_table* stub_table = aarch64_relobj->stub_table(relinfo->data_shndx);
gold_assert(stub_table != NULL);
@@ -6714,6 +7186,115 @@ Target_aarch64<size, big_endian>::relocate_relocs(
}
+// Return whether this is a 3-insn erratum sequence.
+
+template<int size, bool big_endian>
+bool
+Target_aarch64<size, big_endian>::is_erratum_843419_sequence(
+ typename elfcpp::Swap<32,big_endian>::Valtype insn1,
+ typename elfcpp::Swap<32,big_endian>::Valtype insn2,
+ typename elfcpp::Swap<32,big_endian>::Valtype insn3)
+{
+ unsigned rt1, rt2;
+ bool load, pair;
+
+ // The 2nd insn is a single register load or store; or register pair
+ // store.
+ if (Insn_utilities::aarch64_mem_op_p(insn2, &rt1, &rt2, &pair, &load)
+ && (!pair || (pair && !load)))
+ {
+ // The 3rd insn is a load or store instruction from the "Load/store
+ // register (unsigned immediate)" encoding class, using Rn as the
+ // base address register.
+ if (Insn_utilities::aarch64_ldst_uimm(insn3)
+ && (Insn_utilities::aarch64_rn(insn3)
+ == Insn_utilities::aarch64_rd(insn1)))
+ return true;
+ }
+ return false;
+}
+
+
+// Scan erratum for section SHNDX range
+// [output_address + span_start, output_address + span_end).
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::scan_erratum_843419_span(
+ AArch64_relobj<size, big_endian>* relobj,
+ unsigned int shndx,
+ const section_size_type span_start,
+ const section_size_type span_end,
+ unsigned char* input_view,
+ Address output_address)
+{
+ typedef typename Insn_utilities::Insntype Insntype;
+
+ // Adjust output_address and view to the start of span.
+ output_address += span_start;
+ input_view += span_start;
+
+ if ((output_address & 0x03) != 0)
+ return;
+
+ section_size_type offset = 0;
+ section_size_type span_length = span_end - span_start;
+ // The first instruction must be ending at 0xFF8 or 0xFFC.
+ unsigned int page_offset = output_address & 0xFFF;
+ // Make sure starting position, that is "output_address+offset",
+ // starts at page position 0xff8 or 0xffc.
+ if (page_offset < 0xff8)
+ offset = 0xff8 - page_offset;
+ while (offset + 3 * Insn_utilities::BYTES_PER_INSN <= span_length)
+ {
+ Insntype* ip = reinterpret_cast<Insntype*>(input_view + offset);
+ Insntype insn1 = ip[0];
+ if (Insn_utilities::is_adrp(insn1))
+ {
+ Insntype insn2 = ip[1];
+ Insntype insn3 = ip[2];
+ bool do_report = false;
+ if (is_erratum_843419_sequence(insn1, insn2, insn3))
+ do_report = true;
+ else if (offset + 4 * Insn_utilities::BYTES_PER_INSN <= span_length)
+ {
+ // Optionally we can have an insn between ins2 and ins3
+ Insntype insn_opt = ip[2];
+ // And insn_opt must not be a branch.
+ if (!Insn_utilities::aarch64_b(insn_opt)
+ && !Insn_utilities::aarch64_bl(insn_opt)
+ && !Insn_utilities::aarch64_blr(insn_opt)
+ && !Insn_utilities::aarch64_br(insn_opt))
+ {
+ // And insn_opt must not write to dest reg in insn1. However
+ // we do a conservative scan, which means we may fix/report
+ // more than necessary, but it doesn't hurt.
+
+ Insntype insn4 = ip[3];
+ if (is_erratum_843419_sequence(insn1, insn2, insn4))
+ do_report = true;
+ }
+ }
+ if (do_report)
+ {
+ gold_error(_("Erratum 943419 found at \"%s\", section %d, "
+ "offset 0x%08x."),
+ relobj->name().c_str(), shndx,
+ (unsigned int)(span_start + offset));
+ }
+ }
+
+ // Advance to next candidate instruction. We only consider instruction
+ // sequences starting at a page offset of 0xff8 or 0xffc.
+ page_offset = (output_address + offset) & 0xfff;
+ if (page_offset == 0xff8)
+ offset += 4;
+ else // (page_offset == 0xffc), we move to next page's 0xff8.
+ offset += 0xffc;
+ }
+}
+
+
// The selector for aarch64 object files.
template<int size, bool big_endian>
diff --git a/binutils-2.25/gold/i386.cc b/binutils-2.25/gold/i386.cc
index 24f41036..eb5fbf76 100644
--- a/binutils-2.25/gold/i386.cc
+++ b/binutils-2.25/gold/i386.cc
@@ -738,6 +738,26 @@ class Target_i386 : public Sized_target<32, false>
static tls::Tls_optimization
optimize_tls_reloc(bool is_final, int r_type);
+ // Check if relocation against this symbol is a candidate for
+ // conversion from
+ // mov foo@GOT(%reg), %reg
+ // to
+ // lea foo@GOTOFF(%reg), %reg.
+ static bool
+ can_convert_mov_to_lea(const Symbol* gsym)
+ {
+ gold_assert(gsym != NULL);
+ return (gsym->type() != elfcpp::STT_GNU_IFUNC
+ && !gsym->is_undefined ()
+ && !gsym->is_from_dynobj()
+ && !gsym->is_preemptible()
+ && (!parameters->options().shared()
+ || (gsym->visibility() != elfcpp::STV_DEFAULT
+ && gsym->visibility() != elfcpp::STV_PROTECTED)
+ || parameters->options().Bsymbolic())
+ && strcmp(gsym->name(), "_DYNAMIC") != 0);
+ }
+
// Get the GOT section, creating it if necessary.
Output_data_got<32, false>*
got_section(Symbol_table*, Layout*);
@@ -1835,8 +1855,26 @@ Target_i386::Scan::local(Symbol_table* symtab,
case elfcpp::R_386_GOT32:
{
- // The symbol requires a GOT entry.
+ // We need GOT section.
Output_data_got<32, false>* got = target->got_section(symtab, layout);
+
+ // If the relocation symbol isn't IFUNC,
+ // and is local, then we will convert
+ // mov foo@GOT(%reg), %reg
+ // to
+ // lea foo@GOTOFF(%reg), %reg
+ // in Relocate::relocate.
+ if (reloc.get_r_offset() >= 2
+ && lsym.get_st_type() != elfcpp::STT_GNU_IFUNC)
+ {
+ section_size_type stype;
+ const unsigned char* view = object->section_contents(data_shndx,
+ &stype, true);
+ if (view[reloc.get_r_offset() - 2] == 0x8b)
+ break;
+ }
+
+ // Otherwise, the symbol requires a GOT entry.
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
// For a STT_GNU_IFUNC symbol we want the PLT offset. That
@@ -2229,8 +2267,24 @@ Target_i386::Scan::global(Symbol_table* symtab,
case elfcpp::R_386_GOT32:
{
- // The symbol requires a GOT entry.
+ // The symbol requires a GOT section.
Output_data_got<32, false>* got = target->got_section(symtab, layout);
+
+ // If we convert this from
+ // mov foo@GOT(%reg), %reg
+ // to
+ // lea foo@GOTOFF(%reg), %reg
+ // in Relocate::relocate, then there is nothing to do here.
+ if (reloc.get_r_offset() >= 2
+ && Target_i386::can_convert_mov_to_lea(gsym))
+ {
+ section_size_type stype;
+ const unsigned char* view = object->section_contents(data_shndx,
+ &stype, true);
+ if (view[reloc.get_r_offset() - 2] == 0x8b)
+ break;
+ }
+
if (gsym->final_value_is_known())
{
// For a STT_GNU_IFUNC symbol we want the PLT address.
@@ -2732,35 +2786,6 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
}
}
- // Get the GOT offset if needed.
- // The GOT pointer points to the end of the GOT section.
- // We need to subtract the size of the GOT section to get
- // the actual offset to use in the relocation.
- bool have_got_offset = false;
- unsigned int got_offset = 0;
- switch (r_type)
- {
- case elfcpp::R_386_GOT32:
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
- got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
- - target->got_size());
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
- got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
- - target->got_size());
- }
- have_got_offset = true;
- break;
-
- default:
- break;
- }
-
switch (r_type)
{
case elfcpp::R_386_NONE:
@@ -2809,8 +2834,44 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
break;
case elfcpp::R_386_GOT32:
- gold_assert(have_got_offset);
- Relocate_functions<32, false>::rel32(view, got_offset);
+ // Convert
+ // mov foo@GOT(%reg), %reg
+ // to
+ // lea foo@GOTOFF(%reg), %reg
+ // if possible.
+ if (rel.get_r_offset() >= 2
+ && view[-2] == 0x8b
+ && ((gsym == NULL && !psymval->is_ifunc_symbol())
+ || (gsym != NULL
+ && Target_i386::can_convert_mov_to_lea(gsym))))
+ {
+ view[-2] = 0x8d;
+ elfcpp::Elf_types<32>::Elf_Addr value;
+ value = (psymval->value(object, 0)
+ - target->got_plt_section()->address());
+ Relocate_functions<32, false>::rel32(view, value);
+ }
+ else
+ {
+ // The GOT pointer points to the end of the GOT section.
+ // We need to subtract the size of the GOT section to get
+ // the actual offset to use in the relocation.
+ unsigned int got_offset = 0;
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+ got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
+ - target->got_size());
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+ - target->got_size());
+ }
+ Relocate_functions<32, false>::rel32(view, got_offset);
+ }
break;
case elfcpp::R_386_GOTOFF:
diff --git a/binutils-2.25/gold/options.h b/binutils-2.25/gold/options.h
index 93dc7ec3..3402a280 100644
--- a/binutils-2.25/gold/options.h
+++ b/binutils-2.25/gold/options.h
@@ -809,6 +809,11 @@ class General_options
N_("(ARM only) Fix binaries for Cortex-A8 erratum."),
N_("(ARM only) Do not fix binaries for Cortex-A8 erratum."));
+ DEFINE_bool(fix_cortex_a53_843419, options::TWO_DASHES, '\0', false,
+ N_("(AArch64 only) Scan binaries for Cortex-A53 errata 843419."),
+ N_("(AArch64 only) Do not scan binaries for Cortex-A53 "
+ "errata 843419."));
+
DEFINE_bool(fix_arm1176, options::TWO_DASHES, '\0', true,
N_("(ARM only) Fix binaries for ARM1176 erratum."),
N_("(ARM only) Do not fix binaries for ARM1176 erratum."));
@@ -1330,9 +1335,6 @@ class General_options
DEFINE_bool(fix_cortex_a53_835769, options::TWO_DASHES, '\0', false,
N_("Ignored for now"), NULL);
- DEFINE_bool(fix_cortex_a53_843419, options::TWO_DASHES, '\0', false,
- N_("Ignored for now"), NULL);
-
public:
typedef options::Dir_list Dir_list;
diff --git a/binutils-2.25/gold/testsuite/Makefile.am b/binutils-2.25/gold/testsuite/Makefile.am
index 7b73f9d1..83619428 100644
--- a/binutils-2.25/gold/testsuite/Makefile.am
+++ b/binutils-2.25/gold/testsuite/Makefile.am
@@ -957,6 +957,62 @@ endif FN_PTRS_IN_SO_WITHOUT_PIC
endif TLS
+if DEFAULT_TARGET_I386
+
+check_SCRIPTS += i386_mov_to_lea.sh
+check_DATA += i386_mov_to_lea1.stdout i386_mov_to_lea2.stdout \
+ i386_mov_to_lea3.stdout i386_mov_to_lea4.stdout \
+ i386_mov_to_lea5.stdout i386_mov_to_lea6.stdout \
+ i386_mov_to_lea7.stdout i386_mov_to_lea8.stdout
+MOSTLYCLEANFILES += i386_mov_to_lea1 i386_mov_to_lea2 i386_mov_to_lea3 \
+ i386_mov_to_lea4 i386_mov_to_lea5 i386_mov_to_lea6 \
+ i386_mov_to_lea7 i386_mov_to_lea8
+
+i386_mov_to_lea1.o: i386_mov_to_lea1.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea2.o: i386_mov_to_lea2.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea3.o: i386_mov_to_lea3.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea4.o: i386_mov_to_lea4.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea5.o: i386_mov_to_lea5.s
+ $(TEST_AS) --32 -o $@ $<
+i386_mov_to_lea1: i386_mov_to_lea1.o
+ ../ld-new -Bsymbolic -shared -melf_i386 -o $@ $<
+i386_mov_to_lea2: i386_mov_to_lea1.o
+ ../ld-new -pie -melf_i386 -o $@ $<
+i386_mov_to_lea3: i386_mov_to_lea1.o
+ ../ld-new -melf_i386 -o $@ $<
+i386_mov_to_lea4: i386_mov_to_lea1.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea5: i386_mov_to_lea2.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea6: i386_mov_to_lea3.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea7: i386_mov_to_lea4.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea8: i386_mov_to_lea5.o
+ ../ld-new -melf_i386 -shared -o $@ $<
+i386_mov_to_lea1.stdout: i386_mov_to_lea1
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea2.stdout: i386_mov_to_lea2
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea3.stdout: i386_mov_to_lea3
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea4.stdout: i386_mov_to_lea4
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea5.stdout: i386_mov_to_lea5
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea6.stdout: i386_mov_to_lea6
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea7.stdout: i386_mov_to_lea7
+ $(TEST_OBJDUMP) -dw $< > $@
+i386_mov_to_lea8.stdout: i386_mov_to_lea8
+ $(TEST_OBJDUMP) -dw $< > $@
+
+endif DEFAULT_TARGET_I386
+
check_PROGRAMS += many_sections_test
many_sections_test_SOURCES = many_sections_test.cc
many_sections_test_DEPENDENCIES = gcctestdir/ld
diff --git a/binutils-2.25/gold/testsuite/i386_mov_to_lea.sh b/binutils-2.25/gold/testsuite/i386_mov_to_lea.sh
new file mode 100755
index 00000000..03703729
--- /dev/null
+++ b/binutils-2.25/gold/testsuite/i386_mov_to_lea.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# i386_mov_to_lea.sh -- a test for mov2lea conversion.
+
+# Copyright (C) 2010-2015 Free Software Foundation, Inc.
+# Written by Tocar Ilya <ilya.tocar@intel.com>
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+set -e
+
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea1.stdout
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea2.stdout
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea3.stdout
+grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea4.stdout
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea5.stdout
+grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea6.stdout
+grep -q "lea -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea7.stdout
+grep -q "mov -0x[a-f0-9]\+(%ecx),%eax" i386_mov_to_lea8.stdout
+
+exit 0
diff --git a/binutils-2.25/gold/testsuite/i386_mov_to_lea1.s b/binutils-2.25/gold/testsuite/i386_mov_to_lea1.s
new file mode 100644
index 00000000..6d0f436e
--- /dev/null
+++ b/binutils-2.25/gold/testsuite/i386_mov_to_lea1.s
@@ -0,0 +1,11 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+ .type bar, @function
+bar:
+ movl foo@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/binutils-2.25/gold/testsuite/i386_mov_to_lea2.s b/binutils-2.25/gold/testsuite/i386_mov_to_lea2.s
new file mode 100644
index 00000000..65f1bfd7
--- /dev/null
+++ b/binutils-2.25/gold/testsuite/i386_mov_to_lea2.s
@@ -0,0 +1,10 @@
+ .text
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+ .type bar, @function
+bar:
+ movl foo@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/binutils-2.25/gold/testsuite/i386_mov_to_lea3.s b/binutils-2.25/gold/testsuite/i386_mov_to_lea3.s
new file mode 100644
index 00000000..6785e71c
--- /dev/null
+++ b/binutils-2.25/gold/testsuite/i386_mov_to_lea3.s
@@ -0,0 +1,4 @@
+ .type bar, @function
+bar:
+ movl _DYNAMIC@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/binutils-2.25/gold/testsuite/i386_mov_to_lea4.s b/binutils-2.25/gold/testsuite/i386_mov_to_lea4.s
new file mode 100644
index 00000000..7e4c4db6
--- /dev/null
+++ b/binutils-2.25/gold/testsuite/i386_mov_to_lea4.s
@@ -0,0 +1,12 @@
+ .text
+ .globl foo
+ .hidden foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+ .type bar, @function
+bar:
+ movl foo@GOT(%ecx), %eax
+ .size bar, .-bar
diff --git a/binutils-2.25/gold/testsuite/i386_mov_to_lea5.s b/binutils-2.25/gold/testsuite/i386_mov_to_lea5.s
new file mode 100644
index 00000000..6999aae2
--- /dev/null
+++ b/binutils-2.25/gold/testsuite/i386_mov_to_lea5.s
@@ -0,0 +1,12 @@
+ .text
+ .globl foo
+ .protected foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+ .globl bar
+ .type bar, @function
+bar:
+ movl foo@GOT(%ecx), %eax
+ .size bar, .-bar