gold: Handle R_X86_64_CODE_4_GOTPCRELX
Handle R_X86_64_CODE_4_GOTPCRELX and convert mov name@GOTPCREL(%rip), %r31 to lea name@GOTPCREL(%rip), %r31 if the instruction is encoded with the REX2 prefix when possible. elfcpp/ * x86_64.h (R_X86_64_CODE_4_GOTPCRELX): New. gold/ * x86_64.cc (Target_x86_64::can_convert_mov_to_lea): Handle R_X86_64_CODE_4_GOTPCRELX. (Target_x86_64::Scan::get_reference_flags): Likewise. (Target_x86_64::Scan::local): Likewise. (Target_x86_64::Scan::possible_function_pointer_reloc): Likewise. (Target_x86_64::Scan::global): Likewise. (Target_x86_64::Relocate::relocate): Likewise. * testsuite/x86_64_mov_to_lea1.s: Add a test for R_X86_64_CODE_4_GOTPCRELX. * testsuite/x86_64_mov_to_lea2.s: Likewise. * testsuite/x86_64_mov_to_lea3.s: Likewise. * testsuite/x86_64_mov_to_lea4.s: Likewise. * testsuite/x86_64_mov_to_lea5.s: Likewise. * testsuite/x86_64_mov_to_lea.sh: Updated.
This commit is contained in:
parent
3d5a60de52
commit
4a54cb0658
8 changed files with 54 additions and 10 deletions
|
@ -95,9 +95,13 @@ enum
|
||||||
R_X86_64_PC32_BND = 39, // PC relative 32 bit signed with BND prefix
|
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_PLT32_BND = 40, // 32 bit PLT address with BND prefix
|
||||||
R_X86_64_GOTPCRELX = 41, // 32 bit signed PC relative offset to GOT
|
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
|
R_X86_64_REX_GOTPCRELX = 42, // 32 bit signed PC relative offset to GOT
|
||||||
// with REX prefix, relaxable.
|
// 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.
|
// GNU vtable garbage collection extensions.
|
||||||
R_X86_64_GNU_VTINHERIT = 250,
|
R_X86_64_GNU_VTINHERIT = 250,
|
||||||
R_X86_64_GNU_VTENTRY = 251
|
R_X86_64_GNU_VTENTRY = 251
|
||||||
|
|
|
@ -25,20 +25,36 @@
|
||||||
set -e
|
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),%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),%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),%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),%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),%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),%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),%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),%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),%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),%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),%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),%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),%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),%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),%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),%eax" x86_64_mov_to_lea16.stdout
|
||||||
|
grep -q "mov 0x[a-f0-9]\+(%rip),%r26d" x86_64_mov_to_lea16.stdout
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
@ -8,4 +8,5 @@ foo:
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_start:
|
||||||
movq foo@GOTPCREL(%rip), %rax
|
movq foo@GOTPCREL(%rip), %rax
|
||||||
|
movq foo@GOTPCREL(%rip), %r26
|
||||||
.size _start, .-_start
|
.size _start, .-_start
|
||||||
|
|
|
@ -3,4 +3,5 @@
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_start:
|
||||||
movq _DYNAMIC@GOTPCREL(%rip), %rax
|
movq _DYNAMIC@GOTPCREL(%rip), %rax
|
||||||
|
movq _DYNAMIC@GOTPCREL(%rip), %r26
|
||||||
.size _start, .-_start
|
.size _start, .-_start
|
||||||
|
|
|
@ -7,4 +7,5 @@ foo:
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_start:
|
||||||
movq foo@GOTPCREL(%rip), %rax
|
movq foo@GOTPCREL(%rip), %rax
|
||||||
|
movq foo@GOTPCREL(%rip), %r26
|
||||||
.size _start, .-_start
|
.size _start, .-_start
|
||||||
|
|
|
@ -9,4 +9,5 @@ foo:
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_start:
|
||||||
movq foo@GOTPCREL(%rip), %rax
|
movq foo@GOTPCREL(%rip), %rax
|
||||||
|
movq foo@GOTPCREL(%rip), %r26
|
||||||
.size _start, .-_start
|
.size _start, .-_start
|
||||||
|
|
|
@ -9,4 +9,5 @@ foo:
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_start:
|
||||||
movl foo@GOTPCREL+4(%rip), %eax
|
movl foo@GOTPCREL+4(%rip), %eax
|
||||||
|
movl foo@GOTPCREL+4(%rip), %r26d
|
||||||
.size _start, .-_start
|
.size _start, .-_start
|
||||||
|
|
|
@ -1053,8 +1053,9 @@ class Target_x86_64 : public Sized_target<size, false>
|
||||||
gold_assert(gsym != NULL);
|
gold_assert(gsym != NULL);
|
||||||
// We cannot do the conversion unless it's one of these relocations.
|
// We cannot do the conversion unless it's one of these relocations.
|
||||||
if (r_type != elfcpp::R_X86_64_GOTPCREL
|
if (r_type != elfcpp::R_X86_64_GOTPCREL
|
||||||
&& r_type != elfcpp::R_X86_64_GOTPCRELX
|
&& r_type != elfcpp::R_X86_64_GOTPCRELX
|
||||||
&& r_type != elfcpp::R_X86_64_REX_GOTPCRELX)
|
&& r_type != elfcpp::R_X86_64_REX_GOTPCRELX
|
||||||
|
&& r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX)
|
||||||
return false;
|
return false;
|
||||||
// We cannot convert references to IFUNC symbols, or to symbols that
|
// We cannot convert references to IFUNC symbols, or to symbols that
|
||||||
// are not local to the current module.
|
// 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_GOTPCREL:
|
||||||
case elfcpp::R_X86_64_GOTPCRELX:
|
case elfcpp::R_X86_64_GOTPCRELX:
|
||||||
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
||||||
|
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
|
||||||
case elfcpp::R_X86_64_GOTPLT64:
|
case elfcpp::R_X86_64_GOTPLT64:
|
||||||
// Absolute in GOT.
|
// Absolute in GOT.
|
||||||
return Symbol::ABSOLUTE_REF;
|
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_GOTPCREL:
|
||||||
case elfcpp::R_X86_64_GOTPCRELX:
|
case elfcpp::R_X86_64_GOTPCRELX:
|
||||||
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
||||||
|
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
|
||||||
case elfcpp::R_X86_64_GOTPLT64:
|
case elfcpp::R_X86_64_GOTPLT64:
|
||||||
{
|
{
|
||||||
// The symbol requires a GOT section.
|
// The symbol requires a GOT section.
|
||||||
|
@ -3261,21 +3264,30 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
|
||||||
// mov foo@GOTPCREL(%rip), %reg
|
// mov foo@GOTPCREL(%rip), %reg
|
||||||
// to lea foo(%rip), %reg.
|
// to lea foo(%rip), %reg.
|
||||||
// in Relocate::relocate.
|
// in Relocate::relocate.
|
||||||
|
size_t r_offset = reloc.get_r_offset();
|
||||||
if (!parameters->incremental()
|
if (!parameters->incremental()
|
||||||
&& (r_type == elfcpp::R_X86_64_GOTPCREL
|
&& (((r_type == elfcpp::R_X86_64_GOTPCREL
|
||||||
|| r_type == elfcpp::R_X86_64_GOTPCRELX
|
|| r_type == elfcpp::R_X86_64_GOTPCRELX
|
||||||
|| r_type == elfcpp::R_X86_64_REX_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_addend() == -4
|
||||||
&& reloc.get_r_offset() >= 2
|
|
||||||
&& !is_ifunc)
|
&& !is_ifunc)
|
||||||
{
|
{
|
||||||
section_size_type stype;
|
section_size_type stype;
|
||||||
const unsigned char* view = object->section_contents(data_shndx,
|
const unsigned char* view = object->section_contents(data_shndx,
|
||||||
&stype, true);
|
&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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
need_got:
|
||||||
|
|
||||||
// The symbol requires a GOT entry.
|
// The symbol requires a GOT entry.
|
||||||
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
|
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_GOTPCREL:
|
||||||
case elfcpp::R_X86_64_GOTPCRELX:
|
case elfcpp::R_X86_64_GOTPCRELX:
|
||||||
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
||||||
|
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
|
||||||
case elfcpp::R_X86_64_GOTPLT64:
|
case elfcpp::R_X86_64_GOTPLT64:
|
||||||
{
|
{
|
||||||
return true;
|
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_GOTPCREL:
|
||||||
case elfcpp::R_X86_64_GOTPCRELX:
|
case elfcpp::R_X86_64_GOTPCRELX:
|
||||||
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
||||||
|
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
|
||||||
case elfcpp::R_X86_64_GOTPLT64:
|
case elfcpp::R_X86_64_GOTPLT64:
|
||||||
{
|
{
|
||||||
// The symbol requires a GOT entry.
|
// 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();
|
size_t r_offset = reloc.get_r_offset();
|
||||||
if (!parameters->incremental()
|
if (!parameters->incremental()
|
||||||
&& reloc.get_r_addend() == -4
|
&& reloc.get_r_addend() == -4
|
||||||
&& r_offset >= 2
|
&& ((r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX
|
||||||
&& Target_x86_64<size>::can_convert_mov_to_lea(gsym, r_type,
|
&& 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))
|
r_offset, &view))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -4420,6 +4438,7 @@ Target_x86_64<size>::Relocate::relocate(
|
||||||
case elfcpp::R_X86_64_GOTPCREL:
|
case elfcpp::R_X86_64_GOTPCREL:
|
||||||
case elfcpp::R_X86_64_GOTPCRELX:
|
case elfcpp::R_X86_64_GOTPCRELX:
|
||||||
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
case elfcpp::R_X86_64_REX_GOTPCRELX:
|
||||||
|
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
|
||||||
{
|
{
|
||||||
bool converted_p = false;
|
bool converted_p = false;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue