Skip to content

Commit 3d34053

Browse files
authored
[X86,MC] Add relocation R_X86_64_REX2_GOTPCRELX (#106681)
For mov name@GOTPCREL(%rip), %reg test %reg, name@GOTPCREL(%rip) binop name@GOTPCREL(%rip), %reg where binop is one of adc, add, and, cmp, or, sbb, sub, xor instructions, add `R_X86_64_REX2_GOTPCRELX`/`R_X86_64_CODE_4_GOTPCRELX` = 43 if the instruction starts at 4 bytes before the relocation offset. It similar to R_X86_64_GOTPCRELX. Linker can treat `R_X86_64_REX2_GOTPCRELX`/`R_X86_64_CODE_4_GOTPCRELX` as `R_X86_64_GOTPCREL` or convert the above instructions to lea name(%rip), %reg mov $name, %reg test $name, %reg binop $name, %reg if the first byte of the instruction at the relocation `offset - 4` is `0xd5` (namely, encoded w/ REX2 prefix) when possible. Binutils patch: bminor/binutils-gdb@3d5a60d Binutils mailthread: https://sourceware.org/pipermail/binutils/2023-December/131462.html ABI discussion: https://groups.google.com/g/x86-64-abi/c/KbzaNHRB6QU Blog: https://kanrobert.github.io/rfc/All-about-APX-relocation
1 parent ea902d1 commit 3d34053

File tree

12 files changed

+77
-14
lines changed

12 files changed

+77
-14
lines changed

clang/test/Driver/relax.s

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@
88
// RUN: llvm-readobj -r %t | FileCheck --check-prefix=REL %s
99

1010
// REL: R_X86_64_REX_GOTPCRELX foo
11+
// REL: R_X86_64_REX2_GOTPCRELX foo
1112

1213
movq foo@GOTPCREL(%rip), %rax
14+
movq foo@GOTPCREL(%rip), %r16

llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,4 @@ ELF_RELOC(R_X86_64_TLSDESC, 36)
4343
ELF_RELOC(R_X86_64_IRELATIVE, 37)
4444
ELF_RELOC(R_X86_64_GOTPCRELX, 41)
4545
ELF_RELOC(R_X86_64_REX_GOTPCRELX, 42)
46+
ELF_RELOC(R_X86_64_REX2_GOTPCRELX, 43)

llvm/lib/MC/MCTargetOptionsCommandFlags.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
145145

146146
static cl::opt<bool> X86RelaxRelocations(
147147
"x86-relax-relocations",
148-
cl::desc(
149-
"Emit GOTPCRELX/REX_GOTPCRELX instead of GOTPCREL on x86-64 ELF"),
148+
cl::desc("Emit GOTPCRELX/REX_GOTPCRELX/REX2_GOTPCRELX instead of "
149+
"GOTPCREL on x86-64 ELF"),
150150
cl::init(true));
151151
MCBINDOPT(X86RelaxRelocations);
152152

llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,15 +629,19 @@ std::optional<MCFixupKind> X86AsmBackend::getFixupKind(StringRef Name) const {
629629

630630
const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
631631
const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = {
632+
// clang-format off
632633
{"reloc_riprel_4byte", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
633634
{"reloc_riprel_4byte_movq_load", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
635+
{"reloc_riprel_4byte_movq_load_rex2", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
634636
{"reloc_riprel_4byte_relax", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
635637
{"reloc_riprel_4byte_relax_rex", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
638+
{"reloc_riprel_4byte_relax_rex2", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
636639
{"reloc_signed_4byte", 0, 32, 0},
637640
{"reloc_signed_4byte_relax", 0, 32, 0},
638641
{"reloc_global_offset_table", 0, 32, 0},
639642
{"reloc_global_offset_table8", 0, 64, 0},
640643
{"reloc_branch_4byte_pcrel", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
644+
// clang-format on
641645
};
642646

643647
// Fixup kinds from .reloc directive are like R_386_NONE/R_X86_64_NONE. They
@@ -678,7 +682,9 @@ static unsigned getFixupKindSize(unsigned Kind) {
678682
case X86::reloc_riprel_4byte:
679683
case X86::reloc_riprel_4byte_relax:
680684
case X86::reloc_riprel_4byte_relax_rex:
685+
case X86::reloc_riprel_4byte_relax_rex2:
681686
case X86::reloc_riprel_4byte_movq_load:
687+
case X86::reloc_riprel_4byte_movq_load_rex2:
682688
case X86::reloc_signed_4byte:
683689
case X86::reloc_signed_4byte_relax:
684690
case X86::reloc_global_offset_table:

llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ static X86_64RelType getType64(MCFixupKind Kind,
7474
case X86::reloc_riprel_4byte:
7575
case X86::reloc_riprel_4byte_relax:
7676
case X86::reloc_riprel_4byte_relax_rex:
77+
case X86::reloc_riprel_4byte_relax_rex2:
7778
case X86::reloc_riprel_4byte_movq_load:
79+
case X86::reloc_riprel_4byte_movq_load_rex2:
7880
return RT64_32;
7981
case X86::reloc_branch_4byte_pcrel:
8082
Modifier = MCSymbolRefExpr::VK_PLT;
@@ -205,7 +207,7 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
205207
case MCSymbolRefExpr::VK_GOTPCREL:
206208
checkIs32(Ctx, Loc, Type);
207209
// Older versions of ld.bfd/ld.gold/lld
208-
// do not support GOTPCRELX/REX_GOTPCRELX,
210+
// do not support GOTPCRELX/REX_GOTPCRELX/REX2_GOTPCRELX,
209211
// and we want to keep back-compatibility.
210212
if (!Ctx.getTargetOptions()->X86RelaxRelocations)
211213
return ELF::R_X86_64_GOTPCREL;
@@ -217,6 +219,9 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
217219
case X86::reloc_riprel_4byte_relax_rex:
218220
case X86::reloc_riprel_4byte_movq_load:
219221
return ELF::R_X86_64_REX_GOTPCRELX;
222+
case X86::reloc_riprel_4byte_relax_rex2:
223+
case X86::reloc_riprel_4byte_movq_load_rex2:
224+
return ELF::R_X86_64_REX2_GOTPCRELX;
220225
}
221226
llvm_unreachable("unexpected relocation type!");
222227
case MCSymbolRefExpr::VK_GOTPCREL_NORELAX:

llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ namespace X86 {
1616
enum Fixups {
1717
reloc_riprel_4byte = FirstTargetFixupKind, // 32-bit rip-relative
1818
reloc_riprel_4byte_movq_load, // 32-bit rip-relative in movq
19+
reloc_riprel_4byte_movq_load_rex2, // 32-bit rip-relative in movq
20+
// with rex2 prefix
1921
reloc_riprel_4byte_relax, // 32-bit rip-relative in relaxable
2022
// instruction
2123
reloc_riprel_4byte_relax_rex, // 32-bit rip-relative in relaxable
2224
// instruction with rex prefix
25+
reloc_riprel_4byte_relax_rex2, // 32-bit rip-relative in relaxable
26+
// instruction with rex2 prefix
2327
reloc_signed_4byte, // 32-bit signed. Unlike FK_Data_4
2428
// this will be sign extended at
2529
// runtime.

llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -568,8 +568,10 @@ void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc,
568568
if (FixupKind == FK_PCRel_4 ||
569569
FixupKind == MCFixupKind(X86::reloc_riprel_4byte) ||
570570
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load) ||
571+
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load_rex2) ||
571572
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax) ||
572573
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax_rex) ||
574+
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax_rex2) ||
573575
FixupKind == MCFixupKind(X86::reloc_branch_4byte_pcrel)) {
574576
ImmOffset -= 4;
575577
// If this is a pc-relative load off _GLOBAL_OFFSET_TABLE_:
@@ -637,12 +639,11 @@ void X86MCCodeEmitter::emitMemModRMByte(
637639
default:
638640
return X86::reloc_riprel_4byte;
639641
case X86::MOV64rm:
640-
// movq loads is a subset of reloc_riprel_4byte_relax_rex. It is a
642+
// movq loads is a subset of reloc_riprel_4byte_relax_rex/rex2. It is a
641643
// special case because COFF and Mach-O don't support ELF's more
642-
// flexible R_X86_64_REX_GOTPCRELX relaxation.
643-
// TODO: Support new relocation for REX2.
644-
assert(Kind == REX || Kind == REX2);
645-
return X86::reloc_riprel_4byte_movq_load;
644+
// flexible R_X86_64_REX_GOTPCRELX/R_X86_64_REX2_GOTPCRELX relaxation.
645+
return Kind == REX2 ? X86::reloc_riprel_4byte_movq_load_rex2
646+
: X86::reloc_riprel_4byte_movq_load;
646647
case X86::ADC32rm:
647648
case X86::ADD32rm:
648649
case X86::AND32rm:
@@ -665,11 +666,9 @@ void X86MCCodeEmitter::emitMemModRMByte(
665666
case X86::SBB64rm:
666667
case X86::SUB64rm:
667668
case X86::XOR64rm:
668-
// We haven't support relocation for REX2 prefix, so temporarily use REX
669-
// relocation.
670-
// TODO: Support new relocation for REX2.
671-
return (Kind == REX || Kind == REX2) ? X86::reloc_riprel_4byte_relax_rex
672-
: X86::reloc_riprel_4byte_relax;
669+
return Kind == REX2 ? X86::reloc_riprel_4byte_relax_rex2
670+
: Kind == REX ? X86::reloc_riprel_4byte_relax_rex
671+
: X86::reloc_riprel_4byte_relax;
673672
}
674673
}();
675674

llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@ class X86MachObjectWriter : public MCMachObjectTargetWriter {
6666
static bool isFixupKindRIPRel(unsigned Kind) {
6767
return Kind == X86::reloc_riprel_4byte ||
6868
Kind == X86::reloc_riprel_4byte_movq_load ||
69+
Kind == X86::reloc_riprel_4byte_movq_load_rex2 ||
6970
Kind == X86::reloc_riprel_4byte_relax ||
70-
Kind == X86::reloc_riprel_4byte_relax_rex;
71+
Kind == X86::reloc_riprel_4byte_relax_rex ||
72+
Kind == X86::reloc_riprel_4byte_relax_rex2;
7173
}
7274

7375
static unsigned getFixupKindLog2Size(unsigned Kind) {
@@ -83,7 +85,9 @@ static unsigned getFixupKindLog2Size(unsigned Kind) {
8385
case X86::reloc_riprel_4byte:
8486
case X86::reloc_riprel_4byte_relax:
8587
case X86::reloc_riprel_4byte_relax_rex:
88+
case X86::reloc_riprel_4byte_relax_rex2:
8689
case X86::reloc_riprel_4byte_movq_load:
90+
case X86::reloc_riprel_4byte_movq_load_rex2:
8791
case X86::reloc_signed_4byte:
8892
case X86::reloc_signed_4byte_relax:
8993
case X86::reloc_branch_4byte_pcrel:

llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@ unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
6666
case FK_PCRel_4:
6767
case X86::reloc_riprel_4byte:
6868
case X86::reloc_riprel_4byte_movq_load:
69+
case X86::reloc_riprel_4byte_movq_load_rex2:
6970
case X86::reloc_riprel_4byte_relax:
7071
case X86::reloc_riprel_4byte_relax_rex:
72+
case X86::reloc_riprel_4byte_relax_rex2:
7173
case X86::reloc_branch_4byte_pcrel:
7274
return COFF::IMAGE_REL_AMD64_REL32;
7375
case FK_Data_4:

llvm/test/MC/ELF/relocation-alias.s

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ movabsq $memcpy+2, %rax
1616

1717
# CHECK: movq (%rip), %rax
1818
# CHECK-NEXT: R_X86_64_REX_GOTPCRELX abs-0x4
19+
# CHECK: movq (%rip), %r16
20+
# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX abs-0x4
1921
movq abs@GOTPCREL(%rip), %rax
22+
movq abs@GOTPCREL(%rip), %r16
2023
abs = 42
2124

2225
# CHECK: movabsq $0, %rbx

0 commit comments

Comments
 (0)