[llvm] [X86][MC] Add R_X86_64_CODE_6_GOTTPOFF (PR #117277)

Feng Zou via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 21 18:36:44 PST 2024


https://github.com/fzou1 created https://github.com/llvm/llvm-project/pull/117277

For

  add %reg1, name at GOTTPOFF(%rip), %reg2
  add name at GOTTPOFF(%rip), %reg1, %reg2

add

  `R_X86_64_CODE_6_GOTTPOFF` = 50

if the instruction starts at 6 bytes before the relocation offset. It's similar to R_X86_64_GOTTPOFF.

Linker can treat `R_X86_64_CODE_6_GOTTPOFF` as `R_X86_64_GOTTPOFF` or convert the instructions above to

  add $name at tpoff, %reg1, %reg2

if the first byte of the instruction at the relocation `offset - 6` is `0xd5` (namely, encoded w/REX2 prefix) when possible.


Binutils patch: https://github.com/bminor/binutils-gdb/commit/5bc71c2a6b8efb27089baa1fecded82be4f550a7
Binutils mailthread: https://sourceware.org/pipermail/binutils/2024-February/132351.html
ABI discussion: https://groups.google.com/g/x86-64-abi/c/jOtHcziQOBE
Blog: https://kanrobert.github.io/rfc/All-about-APX-relocation

>From a5001d28f452f0aaf2fc634227e50049593afb94 Mon Sep 17 00:00:00 2001
From: Feng Zou <feng.zou at intel.com>
Date: Fri, 22 Nov 2024 09:55:08 +0800
Subject: [PATCH] [X86][MC] Add R_X86_64_CODE_6_GOTTPOFF

For

  add %reg1, name at GOTTPOFF(%rip), %reg2
  add name at GOTTPOFF(%rip), %reg1, %reg2

add

  `R_X86_64_CODE_6_GOTTPOFF` = 50

if the instruction starts at 6 bytes before the relocation offset. It's similar
to R_X86_64_GOTTPOFF.

Linker can treat `R_X86_64_CODE_6_GOTTPOFF` as `R_X86_64_GOTTPOFF` or convert
the instructions above to
  add $name at tpoff, %reg1, %reg2

if the first byte of the instruction at the relocation `offset - 6` is `0xd5`
(namely, encoded w/REX2 prefix) when possible.
---
 .../llvm/BinaryFormat/ELFRelocs/x86_64.def    |  1 +
 .../Target/X86/MCTargetDesc/X86AsmBackend.cpp |  2 +
 .../X86/MCTargetDesc/X86ELFObjectWriter.cpp   |  5 ++
 .../Target/X86/MCTargetDesc/X86FixupKinds.h   |  2 +
 .../X86/MCTargetDesc/X86MCCodeEmitter.cpp     |  9 ++-
 .../X86/MCTargetDesc/X86MachObjectWriter.cpp  |  4 +-
 .../MCTargetDesc/X86WinCOFFObjectWriter.cpp   |  1 +
 llvm/test/MC/ELF/relocation.s                 | 72 +++++++++++--------
 8 files changed, 63 insertions(+), 33 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
index 0c026cf443361a..a93d92870cf32d 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
@@ -46,3 +46,4 @@ ELF_RELOC(R_X86_64_REX_GOTPCRELX,    42)
 ELF_RELOC(R_X86_64_CODE_4_GOTPCRELX,    43)
 ELF_RELOC(R_X86_64_CODE_4_GOTTPOFF,    44)
 ELF_RELOC(R_X86_64_CODE_4_GOTPC32_TLSDESC,    45)
+ELF_RELOC(R_X86_64_CODE_6_GOTTPOFF,    50)
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index 8be8f0b6d735c4..01b6c84419fc88 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -634,6 +634,7 @@ const MCFixupKindInfo &X86AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
       {"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_riprel_6byte_relax", 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},
@@ -683,6 +684,7 @@ static unsigned getFixupKindSize(unsigned Kind) {
   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_riprel_6byte_relax:
   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 349cd011eff303..29a1af97d24fa9 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
@@ -77,6 +77,7 @@ static X86_64RelType getType64(MCFixupKind Kind,
   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_riprel_6byte_relax:
     return RT64_32;
   case X86::reloc_branch_4byte_pcrel:
     Modifier = MCSymbolRefExpr::VK_PLT;
@@ -202,6 +203,8 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
     if ((unsigned)Kind == X86::reloc_riprel_4byte_movq_load_rex2 ||
         (unsigned)Kind == X86::reloc_riprel_4byte_relax_rex2)
       return ELF::R_X86_64_CODE_4_GOTTPOFF;
+    else if ((unsigned)Kind == X86::reloc_riprel_6byte_relax)
+      return ELF::R_X86_64_CODE_6_GOTTPOFF;
     return ELF::R_X86_64_GOTTPOFF;
   case MCSymbolRefExpr::VK_TLSLD:
     checkIs32(Ctx, Loc, Type);
@@ -227,6 +230,8 @@ static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
     case X86::reloc_riprel_4byte_relax_rex2:
     case X86::reloc_riprel_4byte_movq_load_rex2:
       return ELF::R_X86_64_CODE_4_GOTPCRELX;
+    case X86::reloc_riprel_6byte_relax:
+      return ELF::R_X86_64_CODE_6_GOTTPOFF;
     }
     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 29bb7eebae3f22..52592a5a13b978 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
@@ -24,6 +24,8 @@ enum Fixups {
                                              // instruction with rex prefix
   reloc_riprel_4byte_relax_rex2,             // 32-bit rip-relative in relaxable
                                              // instruction with rex2 prefix
+  reloc_riprel_6byte_relax,                  // 32-bit rip-relative in relaxable
+                                             // instruction with APX NDD
   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 f12275ffaba8bb..02a306b350d717 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -579,7 +579,9 @@ void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc,
     // this needs to be a GOTPC32 relocation.
     if (startsWithGlobalOffsetTable(Expr) != GOT_None)
       FixupKind = MCFixupKind(X86::reloc_global_offset_table);
-  }
+  } else if (FixupKind == MCFixupKind(X86::reloc_riprel_6byte_relax))
+    ImmOffset -= 6;
+
   if (FixupKind == FK_PCRel_2)
     ImmOffset -= 2;
   if (FixupKind == FK_PCRel_1)
@@ -670,6 +672,11 @@ void X86MCCodeEmitter::emitMemModRMByte(
         return Kind == REX2  ? X86::reloc_riprel_4byte_relax_rex2
                : Kind == REX ? X86::reloc_riprel_4byte_relax_rex
                              : X86::reloc_riprel_4byte_relax;
+      case X86::ADD64rm_ND:
+      case X86::ADD64mr_ND:
+      case X86::ADD64mr_NF_ND:
+      case X86::ADD64rm_NF_ND:
+        return X86::reloc_riprel_6byte_relax;
       }
     }();
 
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
index 41ce5c9fcb82ad..413650e90de657 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
@@ -69,7 +69,8 @@ static bool isFixupKindRIPRel(unsigned Kind) {
          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_rex2;
+         Kind == X86::reloc_riprel_4byte_relax_rex2 ||
+         Kind == X86::reloc_riprel_6byte_relax;
 }
 
 static unsigned getFixupKindLog2Size(unsigned Kind) {
@@ -91,6 +92,7 @@ static unsigned getFixupKindLog2Size(unsigned Kind) {
   case X86::reloc_signed_4byte:
   case X86::reloc_signed_4byte_relax:
   case X86::reloc_branch_4byte_pcrel:
+  case X86::reloc_riprel_6byte_relax:
   case FK_Data_4: return 2;
   case FK_Data_8: return 3;
   }
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
index 7740500fb41830..48d4707bbe1ebd 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
@@ -70,6 +70,7 @@ unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
     case X86::reloc_riprel_4byte_relax:
     case X86::reloc_riprel_4byte_relax_rex:
     case X86::reloc_riprel_4byte_relax_rex2:
+    case X86::reloc_riprel_6byte_relax:
     case X86::reloc_branch_4byte_pcrel:
       return COFF::IMAGE_REL_AMD64_REL32;
     case FK_Data_4:
diff --git a/llvm/test/MC/ELF/relocation.s b/llvm/test/MC/ELF/relocation.s
index 88301f8447bc2a..8e1297be1f1ce5 100644
--- a/llvm/test/MC/ELF/relocation.s
+++ b/llvm/test/MC/ELF/relocation.s
@@ -21,6 +21,12 @@ bar:
         leaq	foo at GOTTPOFF(%rip), %rax # R_X86_64_GOTTPOFF
         movq    foo at GOTTPOFF(%rip), %r31 # R_X86_64_CODE_4_GOTTPOFF
         addq    foo at GOTTPOFF(%rip), %r31 # R_X86_64_CODE_4_GOTTPOFF
+        # NDD
+        addq %r8, foo at GOTTPOFF(%rip), %r16
+        addq foo at GOTTPOFF(%rip), %rax, %r12
+        {nf} addq %r8, foo at GOTTPOFF(%rip), %r16
+        {nf} addq foo at GOTTPOFF(%rip), %rax, %r12
+
         leaq	foo at TLSGD(%rip), %rax    # R_X86_64_TLSGD
         leaq	foo at TPOFF(%rax), %rax    # R_X86_64_TPOFF32
         leaq	foo at TLSLD(%rip), %rdi    # R_X86_64_TLSLD
@@ -81,37 +87,41 @@ weak_sym:
 // CHECK-NEXT:       0x2D R_X86_64_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
 // CHECK-NEXT:       0x35 R_X86_64_CODE_4_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
 // CHECK-NEXT:       0x3D R_X86_64_CODE_4_GOTTPOFF foo 0xFFFFFFFFFFFFFFFC
-// CHECK-NEXT:       0x44 R_X86_64_TLSGD    foo 0xFFFFFFFFFFFFFFFC
-// CHECK-NEXT:       0x4B R_X86_64_TPOFF32  foo 0x0
-// CHECK-NEXT:       0x52 R_X86_64_TLSLD    foo 0xFFFFFFFFFFFFFFFC
-// CHECK-NEXT:       0x59 R_X86_64_DTPOFF32 foo 0x0
-// CHECK-NEXT:       0x5F R_X86_64_GOT64 foo 0x0
-// CHECK-NEXT:       0x69 R_X86_64_GOTOFF64 foo 0x0
-// CHECK-NEXT:       0x72 R_X86_64_32S .text 0x0
-// CHECK-NEXT:       0x79 R_X86_64_PC32 foo 0xFFFFFFFFFFFFFFFC
-// CHECK-NEXT:       0x80 R_X86_64_PC32 foo 0x80
-// CHECK-NEXT:       0x87 R_X86_64_32S .text 0x0
-// CHECK-NEXT:       0x8B R_X86_64_DTPOFF64 foo 0x0
-// CHECK-NEXT:       0x95 R_X86_64_TPOFF64 baz 0x0
-// CHECK-NEXT:       0x9D R_X86_64_PC16 foo 0x9D
-// CHECK-NEXT:       0x9F R_X86_64_PC8 foo 0x9F
-// CHECK-NEXT:       0xA1 R_X86_64_PLT32 foo 0xFFFFFFFFFFFFFFFC
-// CHECK-NEXT:       0xA8 R_X86_64_PC32 foo 0xFFFFFFFFFFFFFFFB
-// CHECK-NEXT:       0xAF R_X86_64_GOTPC32 _GLOBAL_OFFSET_TABLE_ 0x3
-// CHECK-NEXT:       0xB6 R_X86_64_GOTPC32 _GLOBAL_OFFSET_TABLE_ 0xFFFFFFFFFFFFFFFC
-// CHECK-NEXT:       0xBB R_X86_64_GOTPC32 _GLOBAL_OFFSET_TABLE_ 0x1
-// CHECK-NEXT:       0xC1 R_X86_64_GOTPC64 _GLOBAL_OFFSET_TABLE_ 0x2
-// CHECK-NEXT:       0xC9 R_X86_64_SIZE64 blah 0x0
-// CHECK-NEXT:       0xD1 R_X86_64_SIZE64 blah 0x20
-// CHECK-NEXT:       0xD9 R_X86_64_SIZE64 blah 0xFFFFFFFFFFFFFFE0
-// CHECK-NEXT:       0xE4 R_X86_64_SIZE32 blah 0x0
-// CHECK-NEXT:       0xEB R_X86_64_SIZE32 blah 0x20
-// CHECK-NEXT:       0xF2 R_X86_64_SIZE32 blah 0xFFFFFFFFFFFFFFE0
-// CHECK-NEXT:       0xF6 R_X86_64_GOTPCREL foo 0x0
-// CHECK-NEXT:       0xFA R_X86_64_PLT32 foo 0x0
-// CHECK-NEXT:       0x10E R_X86_64_32 .text 0x10E
-// CHECK-NEXT:       0x113 R_X86_64_PC16 pr23771 0xFFFFFFFFFFFFFFFE
-// CHECK-NEXT:       0x115 R_X86_64_PC32 pr23272 0x0
+// CHECK-NEXT:       0x47 R_X86_64_CODE_6_GOTTPOFF foo 0xFFFFFFFFFFFFFFFA
+// CHECK-NEXT:       0x51 R_X86_64_CODE_6_GOTTPOFF foo 0xFFFFFFFFFFFFFFFA
+// CHECK-NEXT:       0x5B R_X86_64_CODE_6_GOTTPOFF foo 0xFFFFFFFFFFFFFFFA
+// CHECK-NEXT:       0x65 R_X86_64_CODE_6_GOTTPOFF foo 0xFFFFFFFFFFFFFFFA
+// CHECK-NEXT:       0x6C R_X86_64_TLSGD    foo 0xFFFFFFFFFFFFFFFC
+// CHECK-NEXT:       0x73 R_X86_64_TPOFF32  foo 0x0
+// CHECK-NEXT:       0x7A R_X86_64_TLSLD    foo 0xFFFFFFFFFFFFFFFC
+// CHECK-NEXT:       0x81 R_X86_64_DTPOFF32 foo 0x0
+// CHECK-NEXT:       0x87 R_X86_64_GOT64 foo 0x0
+// CHECK-NEXT:       0x91 R_X86_64_GOTOFF64 foo 0x0
+// CHECK-NEXT:       0x9A R_X86_64_32S .text 0x0
+// CHECK-NEXT:       0xA1 R_X86_64_PC32 foo 0xFFFFFFFFFFFFFFFC
+// CHECK-NEXT:       0xA8 R_X86_64_PC32 foo 0xA8
+// CHECK-NEXT:       0xAF R_X86_64_32S .text 0x0
+// CHECK-NEXT:       0xB3 R_X86_64_DTPOFF64 foo 0x0
+// CHECK-NEXT:       0xBD R_X86_64_TPOFF64 baz 0x0
+// CHECK-NEXT:       0xC5 R_X86_64_PC16 foo 0xC5
+// CHECK-NEXT:       0xC7 R_X86_64_PC8 foo 0xC7
+// CHECK-NEXT:       0xC9 R_X86_64_PLT32 foo 0xFFFFFFFFFFFFFFFC
+// CHECK-NEXT:       0xD0 R_X86_64_PC32 foo 0xFFFFFFFFFFFFFFFB
+// CHECK-NEXT:       0xD7 R_X86_64_GOTPC32 _GLOBAL_OFFSET_TABLE_ 0x3
+// CHECK-NEXT:       0xDE R_X86_64_GOTPC32 _GLOBAL_OFFSET_TABLE_ 0xFFFFFFFFFFFFFFFC
+// CHECK-NEXT:       0xE3 R_X86_64_GOTPC32 _GLOBAL_OFFSET_TABLE_ 0x1
+// CHECK-NEXT:       0xE9 R_X86_64_GOTPC64 _GLOBAL_OFFSET_TABLE_ 0x2
+// CHECK-NEXT:       0xF1 R_X86_64_SIZE64 blah 0x0
+// CHECK-NEXT:       0xF9 R_X86_64_SIZE64 blah 0x20
+// CHECK-NEXT:       0x101 R_X86_64_SIZE64 blah 0xFFFFFFFFFFFFFFE0
+// CHECK-NEXT:       0x10C R_X86_64_SIZE32 blah 0x0
+// CHECK-NEXT:       0x113 R_X86_64_SIZE32 blah 0x20
+// CHECK-NEXT:       0x11A R_X86_64_SIZE32 blah 0xFFFFFFFFFFFFFFE0
+// CHECK-NEXT:       0x11E R_X86_64_GOTPCREL foo 0x0
+// CHECK-NEXT:       0x122 R_X86_64_PLT32 foo 0x0
+// CHECK-NEXT:       0x136 R_X86_64_32 .text 0x136
+// CHECK-NEXT:       0x13B R_X86_64_PC16 pr23771 0xFFFFFFFFFFFFFFFE
+// CHECK-NEXT:       0x13D R_X86_64_PC32 pr23272 0x0
 // CHECK-NEXT:     ]
 // CHECK-NEXT:   }
 



More information about the llvm-commits mailing list