[clang] [lld] [llvm] [X86, lld] Add relocation R_X86_64_REX2_GOTPCRELX (PR #106681)
Shengchen Kan via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 1 03:02:32 PDT 2024
https://github.com/KanRobert updated https://github.com/llvm/llvm-project/pull/106681
>From 8d8aea0d9d6b85a3b279a1c60b50cf9b859d6919 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Tue, 25 Jun 2024 20:33:10 +0800
Subject: [PATCH 1/7] [X86,lld] Add relocation R_X86_64_REX2_GOTPCRELX
For
mov name at GOTPCREL(%rip), %reg
test %reg, name at GOTPCREL(%rip)
binop name at 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: https://github.com/bminor/binutils-gdb/commit/3d5a60de52556f6a53d71d7e607c6696450ae3e4
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
---
clang/test/Driver/relax.s | 2 ++
lld/ELF/Arch/X86_64.cpp | 3 ++
lld/test/ELF/x86-64-gotpc-no-relax-err.s | 10 ++++--
lld/test/ELF/x86-64-gotpc-relax.s | 2 +-
.../llvm/BinaryFormat/ELFRelocs/x86_64.def | 1 +
llvm/lib/MC/MCTargetOptionsCommandFlags.cpp | 4 +--
.../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 4 +++
.../X86/MCTargetDesc/X86ELFObjectWriter.cpp | 7 +++-
.../Target/X86/MCTargetDesc/X86FixupKinds.h | 4 +++
.../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 19 +++++------
.../X86/MCTargetDesc/X86MachObjectWriter.cpp | 6 +++-
.../MCTargetDesc/X86WinCOFFObjectWriter.cpp | 2 ++
llvm/test/MC/ELF/relocation-alias.s | 3 ++
llvm/test/MC/X86/gotpcrelx.s | 34 +++++++++++++++++++
14 files changed, 83 insertions(+), 18 deletions(-)
diff --git a/clang/test/Driver/relax.s b/clang/test/Driver/relax.s
index 154d4db0a31385..b4a696a328eb56 100644
--- a/clang/test/Driver/relax.s
+++ b/clang/test/Driver/relax.s
@@ -8,5 +8,7 @@
// RUN: llvm-readobj -r %t | FileCheck --check-prefix=REL %s
// REL: R_X86_64_REX_GOTPCRELX foo
+// REL: R_X86_64_REX2_GOTPCRELX foo
movq foo at GOTPCREL(%rip), %rax
+ movq foo at GOTPCREL(%rip), %r16
diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp
index 65a81fe12f8709..ba5ce68e509199 100644
--- a/lld/ELF/Arch/X86_64.cpp
+++ b/lld/ELF/Arch/X86_64.cpp
@@ -388,6 +388,7 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
+ case R_X86_64_REX2_GOTPCRELX:
case R_X86_64_GOTTPOFF:
return R_GOT_PC;
case R_X86_64_GOTOFF64:
@@ -725,6 +726,7 @@ int64_t X86_64::getImplicitAddend(const uint8_t *buf, RelType type) const {
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
+ case R_X86_64_REX2_GOTPCRELX:
case R_X86_64_PC32:
case R_X86_64_GOTTPOFF:
case R_X86_64_PLT32:
@@ -808,6 +810,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
break;
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
+ case R_X86_64_REX2_GOTPCRELX:
if (rel.expr != R_GOT_PC) {
relaxGot(loc, rel, val);
} else {
diff --git a/lld/test/ELF/x86-64-gotpc-no-relax-err.s b/lld/test/ELF/x86-64-gotpc-no-relax-err.s
index 618dca47755f41..4280c8fd1dc97e 100644
--- a/lld/test/ELF/x86-64-gotpc-no-relax-err.s
+++ b/lld/test/ELF/x86-64-gotpc-no-relax-err.s
@@ -7,15 +7,19 @@
## `>>> defined in` for linker synthesized __stop_* symbols (there is no
## associated file or linker script line number).
-# CHECK: error: {{.*}}:(.text+0x2): relocation R_X86_64_GOTPCRELX out of range: 2147483658 is not in [-2147483648, 2147483647]; references '__stop_data'
+# CHECK: error: {{.*}}:(.text+0x2): relocation R_X86_64_GOTPCRELX out of range: 2147483666 is not in [-2147483648, 2147483647]; references '__stop_data'
# CHECK-NEXT: >>> defined in <internal>
# CHECK-EMPTY:
-# CHECK-NEXT: error: {{.*}}:(.text+0x9): relocation R_X86_64_REX_GOTPCRELX out of range: 2147483651 is not in [-2147483648, 2147483647]; references '__stop_data'
+# CHECK-NEXT: error: {{.*}}:(.text+0x9): relocation R_X86_64_REX_GOTPCRELX out of range: 2147483659 is not in [-2147483648, 2147483647]; references '__stop_data'
+# CHECK-NEXT: >>> defined in <internal>
+# CHECK-EMPTY:
+# CHECK-NEXT: error: {{.*}}:(.text+0x11): relocation R_X86_64_REX2_GOTPCRELX out of range: 2147483651 is not in [-2147483648, 2147483647]; references '__stop_data'
# CHECK-NEXT: >>> defined in <internal>
#--- a.s
movl __stop_data at GOTPCREL(%rip), %eax # out of range
movq __stop_data at GOTPCREL(%rip), %rax # out of range
+ movq __stop_data at GOTPCREL(%rip), %r16 # out of range
movq __stop_data at GOTPCREL(%rip), %rax # in range
.section data,"aw", at progbits
@@ -23,5 +27,5 @@
#--- lds
SECTIONS {
.text 0x200000 : { *(.text) }
- .got 0x80200010 : { *(.got) }
+ .got 0x80200016 : { *(.got) }
}
diff --git a/lld/test/ELF/x86-64-gotpc-relax.s b/lld/test/ELF/x86-64-gotpc-relax.s
index 5945bfc04a0225..1fb3a3c76852ab 100644
--- a/lld/test/ELF/x86-64-gotpc-relax.s
+++ b/lld/test/ELF/x86-64-gotpc-relax.s
@@ -1,5 +1,5 @@
# REQUIRES: x86
-## Test R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX GOT optimization.
+## Test R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX/R_X86_64_REX2_GOTPCRELX GOT optimization.
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: ld.lld %t.o -o %t1 --no-apply-dynamic-relocs
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
index 18fdcf9472dc48..161b1969abfeb4 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
@@ -43,3 +43,4 @@ ELF_RELOC(R_X86_64_TLSDESC, 36)
ELF_RELOC(R_X86_64_IRELATIVE, 37)
ELF_RELOC(R_X86_64_GOTPCRELX, 41)
ELF_RELOC(R_X86_64_REX_GOTPCRELX, 42)
+ELF_RELOC(R_X86_64_REX2_GOTPCRELX, 43)
diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
index 1a4f7e93eeb74a..92618bdabbe519 100644
--- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -145,8 +145,8 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
static cl::opt<bool> X86RelaxRelocations(
"x86-relax-relocations",
- cl::desc(
- "Emit GOTPCRELX/REX_GOTPCRELX instead of GOTPCREL on x86-64 ELF"),
+ cl::desc("Emit GOTPCRELX/REX_GOTPCRELX/REX2_GOTPCRELX instead of "
+ "GOTPCREL on x86-64 ELF"),
cl::init(true));
MCBINDOPT(X86RelaxRelocations);
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index cf0cb92424c166..c02338995f44c0 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -631,8 +631,10 @@ const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = {
{"reloc_riprel_4byte", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_riprel_4byte_movq_load", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
+ {"reloc_riprel_4byte_movq_load_rex2", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_riprel_4byte_relax", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_riprel_4byte_relax_rex", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
+ {"reloc_riprel_4byte_relax_rex2", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_signed_4byte", 0, 32, 0},
{"reloc_signed_4byte_relax", 0, 32, 0},
{"reloc_global_offset_table", 0, 32, 0},
@@ -678,7 +680,9 @@ static unsigned getFixupKindSize(unsigned Kind) {
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
+ case X86::reloc_riprel_4byte_relax_rex2:
case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
case X86::reloc_signed_4byte:
case X86::reloc_signed_4byte_relax:
case X86::reloc_global_offset_table:
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
index 0b2efdfc16cc5d..9fdc62b8c8516f 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
@@ -74,7 +74,9 @@ static X86_64RelType getType64(MCFixupKind Kind,
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
+ case X86::reloc_riprel_4byte_relax_rex2:
case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
return RT64_32;
case X86::reloc_branch_4byte_pcrel:
Modifier = MCSymbolRefExpr::VK_PLT;
@@ -205,7 +207,7 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
case MCSymbolRefExpr::VK_GOTPCREL:
checkIs32(Ctx, Loc, Type);
// Older versions of ld.bfd/ld.gold/lld
- // do not support GOTPCRELX/REX_GOTPCRELX,
+ // do not support GOTPCRELX/REX_GOTPCRELX/REX2_GOTPCRELX,
// and we want to keep back-compatibility.
if (!Ctx.getTargetOptions()->X86RelaxRelocations)
return ELF::R_X86_64_GOTPCREL;
@@ -217,6 +219,9 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
case X86::reloc_riprel_4byte_relax_rex:
case X86::reloc_riprel_4byte_movq_load:
return ELF::R_X86_64_REX_GOTPCRELX;
+ case X86::reloc_riprel_4byte_relax_rex2:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
+ return ELF::R_X86_64_REX2_GOTPCRELX;
}
llvm_unreachable("unexpected relocation type!");
case MCSymbolRefExpr::VK_GOTPCREL_NORELAX:
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h b/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
index 2d5217115d07cb..29bb7eebae3f22 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
@@ -16,10 +16,14 @@ namespace X86 {
enum Fixups {
reloc_riprel_4byte = FirstTargetFixupKind, // 32-bit rip-relative
reloc_riprel_4byte_movq_load, // 32-bit rip-relative in movq
+ reloc_riprel_4byte_movq_load_rex2, // 32-bit rip-relative in movq
+ // with rex2 prefix
reloc_riprel_4byte_relax, // 32-bit rip-relative in relaxable
// instruction
reloc_riprel_4byte_relax_rex, // 32-bit rip-relative in relaxable
// instruction with rex prefix
+ reloc_riprel_4byte_relax_rex2, // 32-bit rip-relative in relaxable
+ // instruction with rex2 prefix
reloc_signed_4byte, // 32-bit signed. Unlike FK_Data_4
// this will be sign extended at
// runtime.
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 469a385e085271..852af1600bb2df 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -568,8 +568,10 @@ void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc,
if (FixupKind == FK_PCRel_4 ||
FixupKind == MCFixupKind(X86::reloc_riprel_4byte) ||
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load) ||
+ FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load_rex2) ||
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax) ||
FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax_rex) ||
+ FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax_rex2) ||
FixupKind == MCFixupKind(X86::reloc_branch_4byte_pcrel)) {
ImmOffset -= 4;
// If this is a pc-relative load off _GLOBAL_OFFSET_TABLE_:
@@ -638,12 +640,11 @@ void X86MCCodeEmitter::emitMemModRMByte(
default:
return X86::reloc_riprel_4byte;
case X86::MOV64rm:
- // movq loads is a subset of reloc_riprel_4byte_relax_rex. It is a
+ // movq loads is a subset of reloc_riprel_4byte_relax_rex/rex2. It is a
// special case because COFF and Mach-O don't support ELF's more
- // flexible R_X86_64_REX_GOTPCRELX relaxation.
- // TODO: Support new relocation for REX2.
- assert(Kind == REX || Kind == REX2);
- return X86::reloc_riprel_4byte_movq_load;
+ // flexible R_X86_64_REX_GOTPCRELX/R_X86_64_REX2_GOTPCRELX relaxation.
+ return Kind == REX2 ? X86::reloc_riprel_4byte_movq_load_rex2
+ : X86::reloc_riprel_4byte_movq_load;
case X86::ADC32rm:
case X86::ADD32rm:
case X86::AND32rm:
@@ -666,11 +667,9 @@ void X86MCCodeEmitter::emitMemModRMByte(
case X86::SBB64rm:
case X86::SUB64rm:
case X86::XOR64rm:
- // We haven't support relocation for REX2 prefix, so temporarily use REX
- // relocation.
- // TODO: Support new relocation for REX2.
- return (Kind == REX || Kind == REX2) ? X86::reloc_riprel_4byte_relax_rex
- : X86::reloc_riprel_4byte_relax;
+ return Kind == REX2 ? X86::reloc_riprel_4byte_relax_rex2
+ : Kind == REX ? X86::reloc_riprel_4byte_relax_rex
+ : X86::reloc_riprel_4byte_relax;
}
}();
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
index ec95b1ffec387d..41ce5c9fcb82ad 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
@@ -66,8 +66,10 @@ class X86MachObjectWriter : public MCMachObjectTargetWriter {
static bool isFixupKindRIPRel(unsigned Kind) {
return Kind == X86::reloc_riprel_4byte ||
Kind == X86::reloc_riprel_4byte_movq_load ||
+ Kind == X86::reloc_riprel_4byte_movq_load_rex2 ||
Kind == X86::reloc_riprel_4byte_relax ||
- Kind == X86::reloc_riprel_4byte_relax_rex;
+ Kind == X86::reloc_riprel_4byte_relax_rex ||
+ Kind == X86::reloc_riprel_4byte_relax_rex2;
}
static unsigned getFixupKindLog2Size(unsigned Kind) {
@@ -83,7 +85,9 @@ static unsigned getFixupKindLog2Size(unsigned Kind) {
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
+ case X86::reloc_riprel_4byte_relax_rex2:
case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
case X86::reloc_signed_4byte:
case X86::reloc_signed_4byte_relax:
case X86::reloc_branch_4byte_pcrel:
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
index 10fc176b59d8ab..7740500fb41830 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
@@ -66,8 +66,10 @@ unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
case FK_PCRel_4:
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_riprel_4byte_movq_load_rex2:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
+ case X86::reloc_riprel_4byte_relax_rex2:
case X86::reloc_branch_4byte_pcrel:
return COFF::IMAGE_REL_AMD64_REL32;
case FK_Data_4:
diff --git a/llvm/test/MC/ELF/relocation-alias.s b/llvm/test/MC/ELF/relocation-alias.s
index 51fb0c37052fe7..66bf2ceea508ba 100644
--- a/llvm/test/MC/ELF/relocation-alias.s
+++ b/llvm/test/MC/ELF/relocation-alias.s
@@ -16,7 +16,10 @@ movabsq $memcpy+2, %rax
# CHECK: movq (%rip), %rax
# CHECK-NEXT: R_X86_64_REX_GOTPCRELX abs-0x4
+# CHECK: movq (%rip), %r16
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX abs-0x4
movq abs at GOTPCREL(%rip), %rax
+movq abs at GOTPCREL(%rip), %r16
abs = 42
# CHECK: movabsq $0, %rbx
diff --git a/llvm/test/MC/X86/gotpcrelx.s b/llvm/test/MC/X86/gotpcrelx.s
index e63e3e9a946fd1..5a8ba454bc904c 100644
--- a/llvm/test/MC/X86/gotpcrelx.s
+++ b/llvm/test/MC/X86/gotpcrelx.s
@@ -37,6 +37,16 @@
# CHECK-NEXT: R_X86_64_REX_GOTPCRELX sbb
# CHECK-NEXT: R_X86_64_REX_GOTPCRELX sub
# CHECK-NEXT: R_X86_64_REX_GOTPCRELX xor
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX mov
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX test
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX adc
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX add
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX and
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX cmp
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX or
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX sbb
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX sub
+# CHECK-NEXT: R_X86_64_REX2_GOTPCRELX xor
# CHECK-NEXT: }
# NORELAX-NEXT: R_X86_64_GOTPCREL mov
@@ -71,6 +81,16 @@
# NORELAX-NEXT: R_X86_64_GOTPCREL sbb
# NORELAX-NEXT: R_X86_64_GOTPCREL sub
# NORELAX-NEXT: R_X86_64_GOTPCREL xor
+# NORELAX-NEXT: R_X86_64_GOTPCREL mov
+# NORELAX-NEXT: R_X86_64_GOTPCREL test
+# NORELAX-NEXT: R_X86_64_GOTPCREL adc
+# NORELAX-NEXT: R_X86_64_GOTPCREL add
+# NORELAX-NEXT: R_X86_64_GOTPCREL and
+# NORELAX-NEXT: R_X86_64_GOTPCREL cmp
+# NORELAX-NEXT: R_X86_64_GOTPCREL or
+# NORELAX-NEXT: R_X86_64_GOTPCREL sbb
+# NORELAX-NEXT: R_X86_64_GOTPCREL sub
+# NORELAX-NEXT: R_X86_64_GOTPCREL xor
# NORELAX-NEXT: }
movl mov at GOTPCREL(%rip), %eax
@@ -108,10 +128,22 @@ sbb sbb at GOTPCREL(%rip), %rax
sub sub at GOTPCREL(%rip), %rax
xor xor at GOTPCREL(%rip), %rax
+movq mov at GOTPCREL(%rip), %r16
+test %r16, test at GOTPCREL(%rip)
+adc adc at GOTPCREL(%rip), %r16
+add add at GOTPCREL(%rip), %r16
+and and at GOTPCREL(%rip), %r16
+cmp cmp at GOTPCREL(%rip), %r16
+or or at GOTPCREL(%rip), %r16
+sbb sbb at GOTPCREL(%rip), %r16
+sub sub at GOTPCREL(%rip), %r16
+xor xor at GOTPCREL(%rip), %r16
+
# COMMON-NEXT: Section ({{.*}}) .rela.norelax {
# COMMON-NEXT: R_X86_64_GOTPCREL mov 0x0
# COMMON-NEXT: R_X86_64_GOTPCREL mov 0xFFFFFFFFFFFFFFFD
# COMMON-NEXT: R_X86_64_GOTPCREL mov 0xFFFFFFFFFFFFFFFC
+# COMMON-NEXT: R_X86_64_GOTPCREL mov 0xFFFFFFFFFFFFFFFD
# COMMON-NEXT: }
# COMMON-NEXT: ]
@@ -123,3 +155,5 @@ movl mov at GOTPCREL+4(%rip), %eax
movq mov at GOTPCREL+1(%rip), %rax
## We could emit R_X86_64_GOTPCRELX, but it is probably unnecessary.
movl mov at GOTPCREL+0(%rip), %eax
+## Don't emit R_X86_64_GOTPCRELX.
+movq mov at GOTPCREL+1(%rip), %r16
>From dee3e268cccfdf34df7158acecfa07a9600ea9e5 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Fri, 30 Aug 2024 16:20:27 +0800
Subject: [PATCH 2/7] add more test
---
llvm/test/MC/X86/reloc-directive-elf-64.s | 3 +++
1 file changed, 3 insertions(+)
diff --git a/llvm/test/MC/X86/reloc-directive-elf-64.s b/llvm/test/MC/X86/reloc-directive-elf-64.s
index 8f5d8c895e7d76..323603efc70618 100644
--- a/llvm/test/MC/X86/reloc-directive-elf-64.s
+++ b/llvm/test/MC/X86/reloc-directive-elf-64.s
@@ -9,6 +9,7 @@
# PRINT-NEXT: .reloc 0, R_X86_64_64, .data+2
# PRINT-NEXT: .reloc 0, R_X86_64_GOTPCRELX, foo+3
# PRINT-NEXT: .reloc 0, R_X86_64_REX_GOTPCRELX, 5
+# PRINT-NEXT: .reloc 0, R_X86_64_REX2_GOTPCRELX, 7
# PRINT: .reloc 0, BFD_RELOC_NONE, 9
# PRINT-NEXT: .reloc 0, BFD_RELOC_8, 9
# PRINT-NEXT: .reloc 0, BFD_RELOC_16, 9
@@ -21,6 +22,7 @@
# CHECK-NEXT: 0x0 R_X86_64_64 .data 0x2
# CHECK-NEXT: 0x0 R_X86_64_GOTPCRELX foo 0x3
# CHECK-NEXT: 0x0 R_X86_64_REX_GOTPCRELX - 0x5
+# CHECK-NEXT: 0x0 R_X86_64_REX2_GOTPCRELX - 0x7
# CHECK-NEXT: 0x0 R_X86_64_NONE - 0x9
# CHECK-NEXT: 0x0 R_X86_64_8 - 0x9
# CHECK-NEXT: 0x0 R_X86_64_16 - 0x9
@@ -37,6 +39,7 @@
.reloc 0, R_X86_64_64, .data+2
.reloc 0, R_X86_64_GOTPCRELX, foo+3
.reloc 0, R_X86_64_REX_GOTPCRELX, 5
+ .reloc 0, R_X86_64_REX2_GOTPCRELX, 7
.reloc 0, BFD_RELOC_NONE, 9
.reloc 0, BFD_RELOC_8, 9
>From 9c2c4017abf25ca349fb4e345f08ff9f03ee7906 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Fri, 30 Aug 2024 16:30:18 +0800
Subject: [PATCH 3/7] clang-format
---
llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
index 9fdc62b8c8516f..90222278d1ad6f 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
@@ -221,7 +221,7 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
return ELF::R_X86_64_REX_GOTPCRELX;
case X86::reloc_riprel_4byte_relax_rex2:
case X86::reloc_riprel_4byte_movq_load_rex2:
- return ELF::R_X86_64_REX2_GOTPCRELX;
+ return ELF::R_X86_64_REX2_GOTPCRELX;
}
llvm_unreachable("unexpected relocation type!");
case MCSymbolRefExpr::VK_GOTPCREL_NORELAX:
>From e275beb14aa80359cae29fb4debbe5c64c647e2c Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Fri, 30 Aug 2024 17:06:47 +0800
Subject: [PATCH 4/7] add more test
---
lld/test/ELF/x86-64-gotpc-relax-nopic.s | 109 +++++++++++++++---------
lld/test/ELF/x86-64-gotpc-relax.s | 13 +++
2 files changed, 82 insertions(+), 40 deletions(-)
diff --git a/lld/test/ELF/x86-64-gotpc-relax-nopic.s b/lld/test/ELF/x86-64-gotpc-relax-nopic.s
index 7481904d16f1b4..e3cd93d1d57962 100644
--- a/lld/test/ELF/x86-64-gotpc-relax-nopic.s
+++ b/lld/test/ELF/x86-64-gotpc-relax-nopic.s
@@ -10,30 +10,39 @@
# SYMRELOC: Symbols [
# SYMRELOC: Symbol {
# SYMRELOC: Name: bar
-# SYMRELOC-NEXT: Value: 0x203248
+# SYMRELOC-NEXT: Value: 0x203290
## 2105751 = 0x202197 (bar)
# DISASM: Disassembly of section .text:
# DISASM-EMPTY:
# DISASM-NEXT: <_start>:
-# DISASM-NEXT: 2011c8: adcl {{.*}}(%rip), %eax # 0x202240
-# DISASM-NEXT: addl {{.*}}(%rip), %ebx # 0x202240
-# DISASM-NEXT: andl {{.*}}(%rip), %ecx # 0x202240
-# DISASM-NEXT: cmpl {{.*}}(%rip), %edx # 0x202240
-# DISASM-NEXT: orl {{.*}}(%rip), %edi # 0x202240
-# DISASM-NEXT: sbbl {{.*}}(%rip), %esi # 0x202240
-# DISASM-NEXT: subl {{.*}}(%rip), %ebp # 0x202240
-# DISASM-NEXT: xorl $0x203248, %r8d
-# DISASM-NEXT: testl $0x203248, %r15d
-# DISASM-NEXT: 201200: adcq $0x203248, %rax
-# DISASM-NEXT: addq $0x203248, %rbx
-# DISASM-NEXT: andq $0x203248, %rcx
-# DISASM-NEXT: cmpq $0x203248, %rdx
-# DISASM-NEXT: orq $0x203248, %rdi
-# DISASM-NEXT: sbbq $0x203248, %rsi
-# DISASM-NEXT: subq $0x203248, %rbp
-# DISASM-NEXT: xorq $0x203248, %r8
-# DISASM-NEXT: testq $0x203248, %r15
+# DISASM-NEXT: 2011c8: adcl {{.*}}(%rip), %eax # 0x202288
+# DISASM-NEXT: addl {{.*}}(%rip), %ebx # 0x202288
+# DISASM-NEXT: andl {{.*}}(%rip), %ecx # 0x202288
+# DISASM-NEXT: cmpl {{.*}}(%rip), %edx # 0x202288
+# DISASM-NEXT: orl {{.*}}(%rip), %edi # 0x202288
+# DISASM-NEXT: sbbl {{.*}}(%rip), %esi # 0x202288
+# DISASM-NEXT: subl {{.*}}(%rip), %ebp # 0x202288
+# DISASM-NEXT: xorl $0x203290, %r8d
+# DISASM-NEXT: testl $0x203290, %r15d
+# DISASM-NEXT: 201200: adcq $0x203290, %rax
+# DISASM-NEXT: addq $0x203290, %rbx
+# DISASM-NEXT: andq $0x203290, %rcx
+# DISASM-NEXT: cmpq $0x203290, %rdx
+# DISASM-NEXT: orq $0x203290, %rdi
+# DISASM-NEXT: sbbq $0x203290, %rsi
+# DISASM-NEXT: subq $0x203290, %rbp
+# DISASM-NEXT: xorq $0x203290, %r8
+# DISASM-NEXT: testq $0x203290, %r15
+# DISASM-NEXT: 20123f: adcq $0x203290, %r16
+# DISASM-NEXT: addq $0x203290, %r17
+# DISASM-NEXT: andq $0x203290, %r18
+# DISASM-NEXT: cmpq $0x203290, %r19
+# DISASM-NEXT: orq $0x203290, %r20
+# DISASM-NEXT: sbbq $0x203290, %r21
+# DISASM-NEXT: subq $0x203290, %r22
+# DISASM-NEXT: xorq $0x203290, %r23
+# DISASM-NEXT: testq $0x203290, %r24
# RUN: ld.lld --hash-style=sysv -shared %t.o -o %t2
# RUN: llvm-readobj -S -r -d %t2 | FileCheck --check-prefix=SEC-PIC %s
@@ -46,8 +55,8 @@
# SEC-PIC-NEXT: SHF_ALLOC
# SEC-PIC-NEXT: SHF_WRITE
# SEC-PIC-NEXT: ]
-# SEC-PIC-NEXT: Address: 0x2380
-# SEC-PIC-NEXT: Offset: 0x380
+# SEC-PIC-NEXT: Address: 0x23C8
+# SEC-PIC-NEXT: Offset: 0x3C8
# SEC-PIC-NEXT: Size: 8
# SEC-PIC-NEXT: Link:
# SEC-PIC-NEXT: Info:
@@ -57,7 +66,7 @@
# SEC-PIC: 0x000000006FFFFFF9 RELACOUNT 1
# SEC-PIC: Relocations [
# SEC-PIC-NEXT: Section ({{.*}}) .rela.dyn {
-# SEC-PIC-NEXT: 0x2380 R_X86_64_RELATIVE - 0x3388
+# SEC-PIC-NEXT: 0x23C8 R_X86_64_RELATIVE - 0x33D0
# SEC-PIC-NEXT: }
# SEC-PIC-NEXT: ]
@@ -65,24 +74,33 @@
# DISASM-PIC: Disassembly of section .text:
# DISASM-PIC-EMPTY:
# DISASM-PIC-NEXT: <_start>:
-# DISASM-PIC-NEXT: 1268: adcl {{.*}}(%rip), %eax # 0x2380
-# DISASM-PIC-NEXT: addl {{.*}}(%rip), %ebx # 0x2380
-# DISASM-PIC-NEXT: andl {{.*}}(%rip), %ecx # 0x2380
-# DISASM-PIC-NEXT: cmpl {{.*}}(%rip), %edx # 0x2380
-# DISASM-PIC-NEXT: orl {{.*}}(%rip), %edi # 0x2380
-# DISASM-PIC-NEXT: sbbl {{.*}}(%rip), %esi # 0x2380
-# DISASM-PIC-NEXT: subl {{.*}}(%rip), %ebp # 0x2380
-# DISASM-PIC-NEXT: xorl {{.*}}(%rip), %r8d # 0x2380
-# DISASM-PIC-NEXT: testl %r15d, {{.*}}(%rip) # 0x2380
-# DISASM-PIC-NEXT: 12a0: adcq {{.*}}(%rip), %rax # 0x2380
-# DISASM-PIC-NEXT: addq {{.*}}(%rip), %rbx # 0x2380
-# DISASM-PIC-NEXT: andq {{.*}}(%rip), %rcx # 0x2380
-# DISASM-PIC-NEXT: cmpq {{.*}}(%rip), %rdx # 0x2380
-# DISASM-PIC-NEXT: orq {{.*}}(%rip), %rdi # 0x2380
-# DISASM-PIC-NEXT: sbbq {{.*}}(%rip), %rsi # 0x2380
-# DISASM-PIC-NEXT: subq {{.*}}(%rip), %rbp # 0x2380
-# DISASM-PIC-NEXT: xorq {{.*}}(%rip), %r8 # 0x2380
-# DISASM-PIC-NEXT: testq %r15, {{.*}}(%rip) # 0x2380
+# DISASM-PIC-NEXT: 1268: adcl {{.*}}(%rip), %eax # 0x23c8
+# DISASM-PIC-NEXT: addl {{.*}}(%rip), %ebx # 0x23c8
+# DISASM-PIC-NEXT: andl {{.*}}(%rip), %ecx # 0x23c8
+# DISASM-PIC-NEXT: cmpl {{.*}}(%rip), %edx # 0x23c8
+# DISASM-PIC-NEXT: orl {{.*}}(%rip), %edi # 0x23c8
+# DISASM-PIC-NEXT: sbbl {{.*}}(%rip), %esi # 0x23c8
+# DISASM-PIC-NEXT: subl {{.*}}(%rip), %ebp # 0x23c8
+# DISASM-PIC-NEXT: xorl {{.*}}(%rip), %r8d # 0x23c8
+# DISASM-PIC-NEXT: testl %r15d, {{.*}}(%rip) # 0x23c8
+# DISASM-PIC-NEXT: 12a0: adcq {{.*}}(%rip), %rax # 0x23c8
+# DISASM-PIC-NEXT: addq {{.*}}(%rip), %rbx # 0x23c8
+# DISASM-PIC-NEXT: andq {{.*}}(%rip), %rcx # 0x23c8
+# DISASM-PIC-NEXT: cmpq {{.*}}(%rip), %rdx # 0x23c8
+# DISASM-PIC-NEXT: orq {{.*}}(%rip), %rdi # 0x23c8
+# DISASM-PIC-NEXT: sbbq {{.*}}(%rip), %rsi # 0x23c8
+# DISASM-PIC-NEXT: subq {{.*}}(%rip), %rbp # 0x23c8
+# DISASM-PIC-NEXT: xorq {{.*}}(%rip), %r8 # 0x23c8
+# DISASM-PIC-NEXT: testq %r15, {{.*}}(%rip) # 0x23c8
+# DISASM-PIC-NEXT: 12df: adcq {{.*}}(%rip), %r16 # 0x23c8
+# DISASM-PIC-NEXT: addq {{.*}}(%rip), %r17 # 0x23c8
+# DISASM-PIC-NEXT: andq {{.*}}(%rip), %r18 # 0x23c8
+# DISASM-PIC-NEXT: cmpq {{.*}}(%rip), %r19 # 0x23c8
+# DISASM-PIC-NEXT: orq {{.*}}(%rip), %r20 # 0x23c8
+# DISASM-PIC-NEXT: sbbq {{.*}}(%rip), %r21 # 0x23c8
+# DISASM-PIC-NEXT: subq {{.*}}(%rip), %r22 # 0x23c8
+# DISASM-PIC-NEXT: xorq {{.*}}(%rip), %r23 # 0x23c8
+# DISASM-PIC-NEXT: testq %r24, {{.*}}(%rip) # 0x23c8
.data
.type bar, @object
@@ -115,3 +133,14 @@ _start:
subq bar at GOTPCREL(%rip), %rbp
xorq bar at GOTPCREL(%rip), %r8
testq %r15, bar at GOTPCREL(%rip)
+
+## R_X86_64_REX2_GOTPCRELX
+ adcq bar at GOTPCREL(%rip), %r16
+ addq bar at GOTPCREL(%rip), %r17
+ andq bar at GOTPCREL(%rip), %r18
+ cmpq bar at GOTPCREL(%rip), %r19
+ orq bar at GOTPCREL(%rip), %r20
+ sbbq bar at GOTPCREL(%rip), %r21
+ subq bar at GOTPCREL(%rip), %r22
+ xorq bar at GOTPCREL(%rip), %r23
+ testq %r24, bar at GOTPCREL(%rip)
diff --git a/lld/test/ELF/x86-64-gotpc-relax.s b/lld/test/ELF/x86-64-gotpc-relax.s
index 1fb3a3c76852ab..ee15738268d5a8 100644
--- a/lld/test/ELF/x86-64-gotpc-relax.s
+++ b/lld/test/ELF/x86-64-gotpc-relax.s
@@ -120,3 +120,16 @@ _start:
jmp *hid at GOTPCREL(%rip)
jmp *ifunc at GOTPCREL(%rip)
jmp *ifunc at GOTPCREL(%rip)
+
+ movq foo at GOTPCREL(%rip), %r16
+ movq foo at GOTPCREL(%rip), %r16
+ movq hid at GOTPCREL(%rip), %r16
+ movq hid at GOTPCREL(%rip), %r16
+ movq ifunc at GOTPCREL(%rip), %r16
+ movq ifunc at GOTPCREL(%rip), %r16
+ movq foo at GOTPCREL(%rip), %r16
+ movq foo at GOTPCREL(%rip), %r16
+ movq hid at GOTPCREL(%rip), %r16
+ movq hid at GOTPCREL(%rip), %r16
+ movq ifunc at GOTPCREL(%rip), %r16
+ movq ifunc at GOTPCREL(%rip), %r16
>From 604aaaf7838ba323766fcb5f28cb954d022ad0e5 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Fri, 30 Aug 2024 17:56:53 +0800
Subject: [PATCH 5/7] disable clang-format
---
llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index c02338995f44c0..42c301750ed3be 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -629,6 +629,7 @@ std::optional<MCFixupKind> X86AsmBackend::getFixupKind(StringRef Name) const {
const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = {
+ // clang-format off
{"reloc_riprel_4byte", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_riprel_4byte_movq_load", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"reloc_riprel_4byte_movq_load_rex2", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
@@ -640,6 +641,7 @@ const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"reloc_global_offset_table", 0, 32, 0},
{"reloc_global_offset_table8", 0, 64, 0},
{"reloc_branch_4byte_pcrel", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
+ // clang-format on
};
// Fixup kinds from .reloc directive are like R_386_NONE/R_X86_64_NONE. They
>From 12cde6989b5fed08e902140b4be4d6219b898a43 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Sun, 1 Sep 2024 13:55:38 +0800
Subject: [PATCH 6/7] Make test x86-64-gotpc-relax.s pass
---
lld/ELF/Arch/X86_64.cpp | 13 ++++++-----
lld/test/ELF/x86-64-gotpc-relax.s | 39 ++++++++++++++++++++-----------
2 files changed, 33 insertions(+), 19 deletions(-)
diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp
index ba5ce68e509199..109c5addfda8b9 100644
--- a/lld/ELF/Arch/X86_64.cpp
+++ b/lld/ELF/Arch/X86_64.cpp
@@ -862,12 +862,13 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
const uint8_t *loc) const {
- // Only R_X86_64_[REX_]GOTPCRELX can be relaxed. GNU as may emit GOTPCRELX
- // with addend != -4. Such an instruction does not load the full GOT entry, so
- // we cannot relax the relocation. E.g. movl x at GOTPCREL+4(%rip), %rax
- // (addend=0) loads the high 32 bits of the GOT entry.
+ // Only R_X86_64_[REX_]|[REX2_]GOTPCRELX can be relaxed. GNU as may emit
+ // GOTPCRELX with addend != -4. Such an instruction does not load the full GOT
+ // entry, so we cannot relax the relocation. E.g. movl x at GOTPCREL+4(%rip),
+ // %rax (addend=0) loads the high 32 bits of the GOT entry.
if (!config->relax || addend != -4 ||
- (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX))
+ (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX &&
+ type != R_X86_64_REX2_GOTPCRELX))
return R_GOT_PC;
const uint8_t op = loc[-2];
const uint8_t modRm = loc[-1];
@@ -883,7 +884,7 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
if (op == 0xff && (modRm == 0x15 || modRm == 0x25))
return R_RELAX_GOT_PC;
- // We don't support test/binop instructions without a REX prefix.
+ // We don't support test/binop instructions without a REX/REX2 prefix.
if (type == R_X86_64_GOTPCRELX)
return R_GOT_PC;
diff --git a/lld/test/ELF/x86-64-gotpc-relax.s b/lld/test/ELF/x86-64-gotpc-relax.s
index ee15738268d5a8..b1ff995b3fc211 100644
--- a/lld/test/ELF/x86-64-gotpc-relax.s
+++ b/lld/test/ELF/x86-64-gotpc-relax.s
@@ -15,16 +15,16 @@
## In our implementation, .got is retained even if all GOT-generating relocations are optimized.
# CHECK: Name Type Address Off Size ES Flg Lk Inf Al
-# CHECK: .iplt PROGBITS 0000000000201280 000280 000010 00 AX 0 0 16
-# CHECK-NEXT: .got PROGBITS 0000000000202290 000290 000000 00 WA 0 0 8
+# CHECK: .iplt PROGBITS 00000000002012e0 0002e0 000010 00 AX 0 0 16
+# CHECK-NEXT: .got PROGBITS 00000000002022f0 0002f0 000000 00 WA 0 0 8
## There is one R_X86_64_IRELATIVE relocations.
# RELOC-LABEL: Relocation section '.rela.dyn' at offset {{.*}} contains 1 entry:
# CHECK: Offset Info Type Symbol's Value Symbol's Name + Addend
-# CHECK: 0000000000203290 0000000000000025 R_X86_64_IRELATIVE 2011e2
+# CHECK: 00000000002032f0 0000000000000025 R_X86_64_IRELATIVE 2011e2
# CHECK-LABEL: Hex dump of section '.got.plt':
-# NOAPPLY-NEXT: 0x00203290 00000000 00000000
-# APPLY-NEXT: 0x00203290 e2112000 00000000
+# NOAPPLY-NEXT: 0x002032f0 00000000 00000000
+# APPLY-NEXT: 0x002032f0 e2112000 00000000
# 0x201173 + 7 - 10 = 0x201170
# 0x20117a + 7 - 17 = 0x201170
@@ -43,20 +43,20 @@
# DISASM-NEXT: leaq -17(%rip), %rax
# DISASM-NEXT: leaq -23(%rip), %rax
# DISASM-NEXT: leaq -30(%rip), %rax
-# DISASM-NEXT: movq 8330(%rip), %rax
-# DISASM-NEXT: movq 8323(%rip), %rax
+# DISASM-NEXT: movq 8426(%rip), %rax
+# DISASM-NEXT: movq 8419(%rip), %rax
# DISASM-NEXT: leaq -52(%rip), %rax
# DISASM-NEXT: leaq -59(%rip), %rax
# DISASM-NEXT: leaq -65(%rip), %rax
# DISASM-NEXT: leaq -72(%rip), %rax
-# DISASM-NEXT: movq 8288(%rip), %rax
-# DISASM-NEXT: movq 8281(%rip), %rax
+# DISASM-NEXT: movq 8384(%rip), %rax
+# DISASM-NEXT: movq 8377(%rip), %rax
# DISASM-NEXT: callq 0x2011e0 <foo>
# DISASM-NEXT: callq 0x2011e0 <foo>
# DISASM-NEXT: callq 0x2011e1 <hid>
# DISASM-NEXT: callq 0x2011e1 <hid>
-# DISASM-NEXT: callq *8251(%rip)
-# DISASM-NEXT: callq *8245(%rip)
+# DISASM-NEXT: callq *8347(%rip)
+# DISASM-NEXT: callq *8341(%rip)
# DISASM-NEXT: jmp 0x2011e0 <foo>
# DISASM-NEXT: nop
# DISASM-NEXT: jmp 0x2011e0 <foo>
@@ -65,13 +65,26 @@
# DISASM-NEXT: nop
# DISASM-NEXT: jmp 0x2011e1 <hid>
# DISASM-NEXT: nop
-# DISASM-NEXT: jmpq *8215(%rip)
-# DISASM-NEXT: jmpq *8209(%rip)
+# DISASM-NEXT: jmpq *8311(%rip)
+# DISASM-NEXT: jmpq *8305(%rip)
+# DISASM-NEXT: leaq -167(%rip), %r16
+# DISASM-NEXT: leaq -175(%rip), %r16
+# DISASM-NEXT: leaq -182(%rip), %r16
+# DISASM-NEXT: leaq -190(%rip), %r16
+# DISASM-NEXT: movq 8265(%rip), %r16
+# DISASM-NEXT: movq 8257(%rip), %r16
+# DISASM-NEXT: leaq -215(%rip), %r16
+# DISASM-NEXT: leaq -223(%rip), %r16
+# DISASM-NEXT: leaq -230(%rip), %r16
+# DISASM-NEXT: leaq -238(%rip), %r16
+# DISASM-NEXT: movq 8217(%rip), %r16
+# DISASM-NEXT: movq 8209(%rip), %r16
# NORELAX-LABEL: <_start>:
# NORELAX-COUNT-12: movq
# NORELAX-COUNT-6: callq *
# NORELAX-COUNT-6: jmpq *
+# NORELAX-COUNT-12: movq
.text
.globl foo
>From f9b70bab805f49251a1080a01c521069583d7961 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Sun, 1 Sep 2024 18:02:01 +0800
Subject: [PATCH 7/7] Make test x86-64-gotpc-relax-nopic.s pass
---
lld/ELF/Arch/X86_64.cpp | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp
index 109c5addfda8b9..a94dd25aae9389 100644
--- a/lld/ELF/Arch/X86_64.cpp
+++ b/lld/ELF/Arch/X86_64.cpp
@@ -901,6 +901,7 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
uint8_t modRm) {
const uint8_t rex = loc[-3];
+ const bool isRex2 = loc[-4] == 0xd5;
// Convert "test %reg, foo at GOTPCREL(%rip)" to "test $foo, %reg".
if (op == 0x85) {
// See "TEST-Logical Compare" (4-428 Vol. 2B),
@@ -925,7 +926,7 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
// See "TEST-Logical Compare" (4-428 Vol. 2B).
loc[-2] = 0xf7;
- // Move R bit to the B bit in REX byte.
+ // Move R bit to the B bit in REX/REX2 byte.
// REX byte is encoded as 0100WRXB, where
// 0100 is 4bit fixed pattern.
// REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the
@@ -936,7 +937,18 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
// REX.B This 1-bit value is an extension to the MODRM.rm field or the
// SIB.base field.
// See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A).
- loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
+ //
+ // REX2 prefix is encoded as 0xd5|M|R2|X2|B2|WRXB, where
+ // 0xd5 is 1byte fixed pattern.
+ // REX2's [W,R,X,B] have the same meanings as REX's.
+ // REX2.M encodes the map id.
+ // R2/X2/B2 provides the fifth and most siginicant bits of the R/X/B
+ // register identifiers, each of which can now address all 32 GPRs.
+ // TODO: Add the section number here after APX SPEC is merged into SDM.
+ if (isRex2)
+ loc[-3] = (rex & ~0x44) | (rex & 0x44) >> 2;
+ else
+ loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
write32le(loc, val);
return;
}
@@ -957,7 +969,10 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
// "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for
// descriptions about each operation.
loc[-2] = 0x81;
- loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
+ if (isRex2)
+ loc[-3] = (rex & ~0x44) | (rex & 0x44) >> 2;
+ else
+ loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
write32le(loc, val);
}
More information about the cfe-commits
mailing list