aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--elfcpp/x86_64.h6
-rwxr-xr-xgold/testsuite/x86_64_mov_to_lea.sh16
-rw-r--r--gold/testsuite/x86_64_mov_to_lea1.s1
-rw-r--r--gold/testsuite/x86_64_mov_to_lea2.s1
-rw-r--r--gold/testsuite/x86_64_mov_to_lea3.s1
-rw-r--r--gold/testsuite/x86_64_mov_to_lea4.s1
-rw-r--r--gold/testsuite/x86_64_mov_to_lea5.s1
-rw-r--r--gold/x86_64.cc37
8 files changed, 54 insertions, 10 deletions
diff --git a/elfcpp/x86_64.h b/elfcpp/x86_64.h
index 0377e77..97a87ae 100644
--- a/elfcpp/x86_64.h
+++ b/elfcpp/x86_64.h
@@ -95,9 +95,13 @@ enum
R_X86_64_PC32_BND = 39, // PC relative 32 bit signed with BND prefix
R_X86_64_PLT32_BND = 40, // 32 bit PLT address with BND prefix
R_X86_64_GOTPCRELX = 41, // 32 bit signed PC relative offset to GOT
- // without REX prefix, relaxable.
+ // without REX nor REX2 prefixes, relaxable.
R_X86_64_REX_GOTPCRELX = 42, // 32 bit signed PC relative offset to GOT
// with REX prefix, relaxable.
+ R_X86_64_CODE_4_GOTPCRELX = 43, // 32 bit signed PC relative offset to
+ // GOT if the instruction starts at 4
+ // bytes before the relocation offset,
+ // relaxable.
// GNU vtable garbage collection extensions.
R_X86_64_GNU_VTINHERIT = 250,
R_X86_64_GNU_VTENTRY = 251
diff --git a/gold/testsuite/x86_64_mov_to_lea.sh b/gold/testsuite/x86_64_mov_to_lea.sh
index 1b30e1a..3e248eb 100755
--- a/gold/testsuite/x86_64_mov_to_lea.sh
+++ b/gold/testsuite/x86_64_mov_to_lea.sh
@@ -25,20 +25,36 @@
set -e
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea1.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea1.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea2.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea2.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea3.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea3.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea4.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea4.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea5.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea5.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea6.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea6.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea7.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea7.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea8.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea8.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea9.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea9.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea10.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea10.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea11.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea11.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea12.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea12.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea13.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea13.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea14.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea14.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%eax" x86_64_mov_to_lea15.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26d" x86_64_mov_to_lea15.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%eax" x86_64_mov_to_lea16.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26d" x86_64_mov_to_lea16.stdout
exit 0
diff --git a/gold/testsuite/x86_64_mov_to_lea1.s b/gold/testsuite/x86_64_mov_to_lea1.s
index 4dce487..298ede1 100644
--- a/gold/testsuite/x86_64_mov_to_lea1.s
+++ b/gold/testsuite/x86_64_mov_to_lea1.s
@@ -8,4 +8,5 @@ foo:
.type _start, @function
_start:
movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %r26
.size _start, .-_start
diff --git a/gold/testsuite/x86_64_mov_to_lea2.s b/gold/testsuite/x86_64_mov_to_lea2.s
index 2a11b7a..404f4c1 100644
--- a/gold/testsuite/x86_64_mov_to_lea2.s
+++ b/gold/testsuite/x86_64_mov_to_lea2.s
@@ -3,4 +3,5 @@
.type _start, @function
_start:
movq _DYNAMIC@GOTPCREL(%rip), %rax
+ movq _DYNAMIC@GOTPCREL(%rip), %r26
.size _start, .-_start
diff --git a/gold/testsuite/x86_64_mov_to_lea3.s b/gold/testsuite/x86_64_mov_to_lea3.s
index ac43b78..838c33e 100644
--- a/gold/testsuite/x86_64_mov_to_lea3.s
+++ b/gold/testsuite/x86_64_mov_to_lea3.s
@@ -7,4 +7,5 @@ foo:
.type _start, @function
_start:
movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %r26
.size _start, .-_start
diff --git a/gold/testsuite/x86_64_mov_to_lea4.s b/gold/testsuite/x86_64_mov_to_lea4.s
index 37bee32..a68a4cf 100644
--- a/gold/testsuite/x86_64_mov_to_lea4.s
+++ b/gold/testsuite/x86_64_mov_to_lea4.s
@@ -9,4 +9,5 @@ foo:
.type _start, @function
_start:
movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %r26
.size _start, .-_start
diff --git a/gold/testsuite/x86_64_mov_to_lea5.s b/gold/testsuite/x86_64_mov_to_lea5.s
index e793a2b..e818989 100644
--- a/gold/testsuite/x86_64_mov_to_lea5.s
+++ b/gold/testsuite/x86_64_mov_to_lea5.s
@@ -9,4 +9,5 @@ foo:
.type _start, @function
_start:
movl foo@GOTPCREL+4(%rip), %eax
+ movl foo@GOTPCREL+4(%rip), %r26d
.size _start, .-_start
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 928dfa8..b7be9bf 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -1053,8 +1053,9 @@ class Target_x86_64 : public Sized_target<size, false>
gold_assert(gsym != NULL);
// We cannot do the conversion unless it's one of these relocations.
if (r_type != elfcpp::R_X86_64_GOTPCREL
- && r_type != elfcpp::R_X86_64_GOTPCRELX
- && r_type != elfcpp::R_X86_64_REX_GOTPCRELX)
+ && r_type != elfcpp::R_X86_64_GOTPCRELX
+ && r_type != elfcpp::R_X86_64_REX_GOTPCRELX
+ && r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX)
return false;
// We cannot convert references to IFUNC symbols, or to symbols that
// are not local to the current module.
@@ -2971,6 +2972,7 @@ Target_x86_64<size>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64:
// Absolute in GOT.
return Symbol::ABSOLUTE_REF;
@@ -3251,6 +3253,7 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64:
{
// The symbol requires a GOT section.
@@ -3261,21 +3264,30 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
// mov foo@GOTPCREL(%rip), %reg
// to lea foo(%rip), %reg.
// in Relocate::relocate.
+ size_t r_offset = reloc.get_r_offset();
if (!parameters->incremental()
- && (r_type == elfcpp::R_X86_64_GOTPCREL
- || r_type == elfcpp::R_X86_64_GOTPCRELX
- || r_type == elfcpp::R_X86_64_REX_GOTPCRELX)
+ && (((r_type == elfcpp::R_X86_64_GOTPCREL
+ || r_type == elfcpp::R_X86_64_GOTPCRELX
+ || r_type == elfcpp::R_X86_64_REX_GOTPCRELX)
+ && r_offset >= 2)
+ || (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX
+ && r_offset >= 4))
&& reloc.get_r_addend() == -4
- && reloc.get_r_offset() >= 2
&& !is_ifunc)
{
section_size_type stype;
const unsigned char* view = object->section_contents(data_shndx,
&stype, true);
- if (view[reloc.get_r_offset() - 2] == 0x8b)
+ if (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX
+ && view[r_offset - 4] != 0xd5)
+ goto need_got;
+
+ if (view[r_offset - 2] == 0x8b)
break;
}
+need_got:
+
// The symbol requires a GOT entry.
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
@@ -3498,6 +3510,7 @@ Target_x86_64<size>::Scan::possible_function_pointer_reloc(
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64:
{
return true;
@@ -3714,6 +3727,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64:
{
// The symbol requires a GOT entry.
@@ -3736,8 +3750,12 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
size_t r_offset = reloc.get_r_offset();
if (!parameters->incremental()
&& reloc.get_r_addend() == -4
- && r_offset >= 2
- && Target_x86_64<size>::can_convert_mov_to_lea(gsym, r_type,
+ && ((r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX
+ && r_offset >= 2)
+ || (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX
+ && r_offset >= 4
+ && view[r_offset - 4] == 0xd5))
+ && Target_x86_64<size>::can_convert_mov_to_lea(gsym, r_type,
r_offset, &view))
break;
@@ -4420,6 +4438,7 @@ Target_x86_64<size>::Relocate::relocate(
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
{
bool converted_p = false;