Skip to content

Commit 4a54cb0

Browse files
committed
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.
1 parent 3d5a60d commit 4a54cb0

File tree

8 files changed

+54
-10
lines changed

8 files changed

+54
-10
lines changed

elfcpp/x86_64.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,13 @@ enum
9595
R_X86_64_PC32_BND = 39, // PC relative 32 bit signed with BND prefix
9696
R_X86_64_PLT32_BND = 40, // 32 bit PLT address with BND prefix
9797
R_X86_64_GOTPCRELX = 41, // 32 bit signed PC relative offset to GOT
98-
// without REX prefix, relaxable.
98+
// without REX nor REX2 prefixes, relaxable.
9999
R_X86_64_REX_GOTPCRELX = 42, // 32 bit signed PC relative offset to GOT
100100
// with REX prefix, relaxable.
101+
R_X86_64_CODE_4_GOTPCRELX = 43, // 32 bit signed PC relative offset to
102+
// GOT if the instruction starts at 4
103+
// bytes before the relocation offset,
104+
// relaxable.
101105
// GNU vtable garbage collection extensions.
102106
R_X86_64_GNU_VTINHERIT = 250,
103107
R_X86_64_GNU_VTENTRY = 251

gold/testsuite/x86_64_mov_to_lea.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,36 @@
2525
set -e
2626

2727
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea1.stdout
28+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea1.stdout
2829
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea2.stdout
30+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea2.stdout
2931
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea3.stdout
32+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea3.stdout
3033
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea4.stdout
34+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea4.stdout
3135
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea5.stdout
36+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea5.stdout
3237
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea6.stdout
38+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea6.stdout
3339
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea7.stdout
40+
grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea7.stdout
3441
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea8.stdout
42+
grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea8.stdout
3543
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea9.stdout
44+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea9.stdout
3645
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea10.stdout
46+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea10.stdout
3747
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea11.stdout
48+
grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea11.stdout
3849
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea12.stdout
50+
grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea12.stdout
3951
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea13.stdout
52+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea13.stdout
4053
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea14.stdout
54+
grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea14.stdout
4155
grep -q "mov 0x[a-f0-9]\+(%rip),%eax" x86_64_mov_to_lea15.stdout
56+
grep -q "mov 0x[a-f0-9]\+(%rip),%r26d" x86_64_mov_to_lea15.stdout
4257
grep -q "mov 0x[a-f0-9]\+(%rip),%eax" x86_64_mov_to_lea16.stdout
58+
grep -q "mov 0x[a-f0-9]\+(%rip),%r26d" x86_64_mov_to_lea16.stdout
4359

4460
exit 0

gold/testsuite/x86_64_mov_to_lea1.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ foo:
88
.type _start, @function
99
_start:
1010
movq foo@GOTPCREL(%rip), %rax
11+
movq foo@GOTPCREL(%rip), %r26
1112
.size _start, .-_start

gold/testsuite/x86_64_mov_to_lea2.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
.type _start, @function
44
_start:
55
movq _DYNAMIC@GOTPCREL(%rip), %rax
6+
movq _DYNAMIC@GOTPCREL(%rip), %r26
67
.size _start, .-_start

gold/testsuite/x86_64_mov_to_lea3.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ foo:
77
.type _start, @function
88
_start:
99
movq foo@GOTPCREL(%rip), %rax
10+
movq foo@GOTPCREL(%rip), %r26
1011
.size _start, .-_start

gold/testsuite/x86_64_mov_to_lea4.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ foo:
99
.type _start, @function
1010
_start:
1111
movq foo@GOTPCREL(%rip), %rax
12+
movq foo@GOTPCREL(%rip), %r26
1213
.size _start, .-_start

gold/testsuite/x86_64_mov_to_lea5.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ foo:
99
.type _start, @function
1010
_start:
1111
movl foo@GOTPCREL+4(%rip), %eax
12+
movl foo@GOTPCREL+4(%rip), %r26d
1213
.size _start, .-_start

gold/x86_64.cc

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,8 +1053,9 @@ class Target_x86_64 : public Sized_target<size, false>
10531053
gold_assert(gsym != NULL);
10541054
// We cannot do the conversion unless it's one of these relocations.
10551055
if (r_type != elfcpp::R_X86_64_GOTPCREL
1056-
&& r_type != elfcpp::R_X86_64_GOTPCRELX
1057-
&& r_type != elfcpp::R_X86_64_REX_GOTPCRELX)
1056+
&& r_type != elfcpp::R_X86_64_GOTPCRELX
1057+
&& r_type != elfcpp::R_X86_64_REX_GOTPCRELX
1058+
&& r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX)
10581059
return false;
10591060
// We cannot convert references to IFUNC symbols, or to symbols that
10601061
// are not local to the current module.
@@ -2971,6 +2972,7 @@ Target_x86_64<size>::Scan::get_reference_flags(unsigned int r_type)
29712972
case elfcpp::R_X86_64_GOTPCREL:
29722973
case elfcpp::R_X86_64_GOTPCRELX:
29732974
case elfcpp::R_X86_64_REX_GOTPCRELX:
2975+
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
29742976
case elfcpp::R_X86_64_GOTPLT64:
29752977
// Absolute in GOT.
29762978
return Symbol::ABSOLUTE_REF;
@@ -3251,6 +3253,7 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
32513253
case elfcpp::R_X86_64_GOTPCREL:
32523254
case elfcpp::R_X86_64_GOTPCRELX:
32533255
case elfcpp::R_X86_64_REX_GOTPCRELX:
3256+
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
32543257
case elfcpp::R_X86_64_GOTPLT64:
32553258
{
32563259
// The symbol requires a GOT section.
@@ -3261,21 +3264,30 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
32613264
// mov foo@GOTPCREL(%rip), %reg
32623265
// to lea foo(%rip), %reg.
32633266
// in Relocate::relocate.
3267+
size_t r_offset = reloc.get_r_offset();
32643268
if (!parameters->incremental()
3265-
&& (r_type == elfcpp::R_X86_64_GOTPCREL
3266-
|| r_type == elfcpp::R_X86_64_GOTPCRELX
3267-
|| r_type == elfcpp::R_X86_64_REX_GOTPCRELX)
3269+
&& (((r_type == elfcpp::R_X86_64_GOTPCREL
3270+
|| r_type == elfcpp::R_X86_64_GOTPCRELX
3271+
|| r_type == elfcpp::R_X86_64_REX_GOTPCRELX)
3272+
&& r_offset >= 2)
3273+
|| (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX
3274+
&& r_offset >= 4))
32683275
&& reloc.get_r_addend() == -4
3269-
&& reloc.get_r_offset() >= 2
32703276
&& !is_ifunc)
32713277
{
32723278
section_size_type stype;
32733279
const unsigned char* view = object->section_contents(data_shndx,
32743280
&stype, true);
3275-
if (view[reloc.get_r_offset() - 2] == 0x8b)
3281+
if (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX
3282+
&& view[r_offset - 4] != 0xd5)
3283+
goto need_got;
3284+
3285+
if (view[r_offset - 2] == 0x8b)
32763286
break;
32773287
}
32783288

3289+
need_got:
3290+
32793291
// The symbol requires a GOT entry.
32803292
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
32813293

@@ -3498,6 +3510,7 @@ Target_x86_64<size>::Scan::possible_function_pointer_reloc(
34983510
case elfcpp::R_X86_64_GOTPCREL:
34993511
case elfcpp::R_X86_64_GOTPCRELX:
35003512
case elfcpp::R_X86_64_REX_GOTPCRELX:
3513+
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
35013514
case elfcpp::R_X86_64_GOTPLT64:
35023515
{
35033516
return true;
@@ -3714,6 +3727,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
37143727
case elfcpp::R_X86_64_GOTPCREL:
37153728
case elfcpp::R_X86_64_GOTPCRELX:
37163729
case elfcpp::R_X86_64_REX_GOTPCRELX:
3730+
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
37173731
case elfcpp::R_X86_64_GOTPLT64:
37183732
{
37193733
// The symbol requires a GOT entry.
@@ -3736,8 +3750,12 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
37363750
size_t r_offset = reloc.get_r_offset();
37373751
if (!parameters->incremental()
37383752
&& reloc.get_r_addend() == -4
3739-
&& r_offset >= 2
3740-
&& Target_x86_64<size>::can_convert_mov_to_lea(gsym, r_type,
3753+
&& ((r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX
3754+
&& r_offset >= 2)
3755+
|| (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX
3756+
&& r_offset >= 4
3757+
&& view[r_offset - 4] == 0xd5))
3758+
&& Target_x86_64<size>::can_convert_mov_to_lea(gsym, r_type,
37413759
r_offset, &view))
37423760
break;
37433761

@@ -4420,6 +4438,7 @@ Target_x86_64<size>::Relocate::relocate(
44204438
case elfcpp::R_X86_64_GOTPCREL:
44214439
case elfcpp::R_X86_64_GOTPCRELX:
44224440
case elfcpp::R_X86_64_REX_GOTPCRELX:
4441+
case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
44234442
{
44244443
bool converted_p = false;
44254444

0 commit comments

Comments
 (0)