[llvm-branch-commits] [lld] release/23.x: [LLD][COFF] Emit ARM64X relocations for TLS directory (#213529) (PR #214498)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Aug 6 07:10:34 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-coff

Author: llvmbot

<details>
<summary>Changes</summary>

Backport 65e92e073539c3fe3523256c4fba35ac1dedcb92

Requested by: @<!-- -->cjacek

---
Full diff: https://github.com/llvm/llvm-project/pull/214498.diff


3 Files Affected:

- (modified) lld/COFF/Driver.cpp (+1-4) 
- (modified) lld/COFF/Writer.cpp (+22-4) 
- (modified) lld/test/COFF/arm64x-tls.s (+56-10) 


``````````diff
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 9d39aff73601b..6583e43271ad6 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2841,8 +2841,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
 
   if (ctx.hybridSymtab) {
     // On ARM64X, merge tls chunks, there may be only one true _tls_start and
-    // _tls_end chunk. Additionally, both views use the same _tls_used and
-    // _tls_index.
+    // _tls_end chunk.
     auto maybeReplaceWithNative = [&](StringRef name) {
       auto nativeSym = dyn_cast_or_null<DefinedRegular>(
           ctx.hybridSymtab->findUnderscore(name));
@@ -2852,8 +2851,6 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
               dyn_cast_or_null<DefinedRegular>(ctx.symtab.findUnderscore(name)))
         nativeSym->getChunk()->replace(ecSym->getChunk());
     };
-    maybeReplaceWithNative("_tls_used");
-    maybeReplaceWithNative("_tls_index");
     maybeReplaceWithNative("_tls_start");
     maybeReplaceWithNative("_tls_end");
   }
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 33826c9146c50..3cab426df55cf 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -267,7 +267,7 @@ class Writer {
   void sortBySectionOrder(std::vector<Chunk *> &chunks);
   void fixPartialSectionChars(StringRef name, uint32_t chars);
   bool fixGnuImportChunks();
-  void fixTlsAlignment();
+  void fixTlsAlignment(SymbolTable &symtab);
   PartialSection *createPartialSection(StringRef name, uint32_t outChars);
   PartialSection *findPartialSection(StringRef name, uint32_t outChars);
 
@@ -815,7 +815,7 @@ void Writer::run() {
     // Fix up the alignment in the TLS Directory's characteristic field,
     // if a specific alignment value is needed
     if (tlsAlignment)
-      fixTlsAlignment();
+      ctx.forEachSymtab([&](SymbolTable &symtab) { fixTlsAlignment(symtab); });
   }
 
   if (!ctx.config.pdbPath.empty() && ctx.config.debug) {
@@ -2940,6 +2940,24 @@ void Writer::createDynamicRelocs() {
                              LOAD_CONFIG_TABLE * sizeof(data_directory) +
                              offsetof(data_directory, Size),
                          ctx.symtab.loadConfigSize);
+
+  auto nativeTlsUsed =
+      dyn_cast_or_null<Defined>(ctx.hybridSymtab->findUnderscore("_tls_used"));
+  auto ecTlsUsed =
+      dyn_cast_or_null<Defined>(ctx.symtab.findUnderscore("_tls_used"));
+  if (nativeTlsUsed || ecTlsUsed) {
+    ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
+                           dataDirOffset64 +
+                               TLS_TABLE * sizeof(data_directory) +
+                               offsetof(data_directory, RelativeVirtualAddress),
+                           Arm64XRelocVal(ecTlsUsed));
+    if (!nativeTlsUsed || !ecTlsUsed)
+      ctx.dynamicRelocs->add(
+          IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
+          dataDirOffset64 + TLS_TABLE * sizeof(data_directory) +
+              offsetof(data_directory, Size),
+          ecTlsUsed ? sizeof(coff_tls_directory64) : 0);
+  }
 }
 
 PartialSection *Writer::createPartialSection(StringRef name,
@@ -2958,9 +2976,9 @@ PartialSection *Writer::findPartialSection(StringRef name, uint32_t outChars) {
   return nullptr;
 }
 
-void Writer::fixTlsAlignment() {
+void Writer::fixTlsAlignment(SymbolTable &symtab) {
   Defined *tlsSym =
-      dyn_cast_or_null<Defined>(ctx.symtab.findUnderscore("_tls_used"));
+      dyn_cast_or_null<Defined>(symtab.findUnderscore("_tls_used"));
   if (!tlsSym)
     return;
 
diff --git a/lld/test/COFF/arm64x-tls.s b/lld/test/COFF/arm64x-tls.s
index 608604fab2fb3..4a900edcee676 100644
--- a/lld/test/COFF/arm64x-tls.s
+++ b/lld/test/COFF/arm64x-tls.s
@@ -12,7 +12,7 @@
 // RUN: llvm-lib -machine:arm64x -out:tls.lib tls-aarch64.obj tls-arm64ec.obj loadconfig-arm64ec.obj loadconfig-arm64.obj
 // RUN: lld-link -machine:arm64x -dll -noentry aarch64.obj arm64ec.obj tls.lib -out:out.dll
 
-// Check that we're using native _tls_index and _tls_used for both views.
+// Check that we're using the right _tls_index and _tls_used for both views.
 
 // RUN: llvm-readobj --coff-tls-directory --hex-dump=.ec --hex-dump=.a64 out.dll | FileCheck %s
 // CHECK:      Format: COFF-ARM64X
@@ -20,13 +20,13 @@
 // CHECK-NEXT: AddressSize: 64bit
 // CHECK-EMPTY:
 // CHECK-NEXT: Hex dump of section '.a64':
-// CHECK-NEXT: 0x180004000 00500000 04500000 00700000 01700000
+// CHECK-NEXT: 0x180004000 00500000 04500000 00800000 01800000
 // CHECK-EMPTY:
 // CHECK-NEXT: Hex dump of section '.ec':
-// CHECK-NEXT: 0x180006000 00500000 04500000 00700000 01700000
+// CHECK-NEXT: 0x180007000 00600000 04600000 00800000 01800000
 // CHECK-NEXT: TLSDirectory {
-// CHECK-NEXT:   StartAddressOfRawData: 0x180007000
-// CHECK-NEXT:   EndAddressOfRawData: 0x180007001
+// CHECK-NEXT:   StartAddressOfRawData: 0x180008000
+// CHECK-NEXT:   EndAddressOfRawData: 0x180008001
 // CHECK-NEXT:   AddressOfIndex: 0x180005000
 // CHECK-NEXT:   AddressOfCallBacks: 0x0
 // CHECK-NEXT:   SizeOfZeroFill: 0x0
@@ -40,14 +40,14 @@
 // CHECK-NEXT:   AddressSize: 64bit
 // CHECK-EMPTY:
 // CHECK-NEXT:   Hex dump of section '.a64':
-// CHECK-NEXT:   0x180004000 00500000 04500000 00700000 01700000
+// CHECK-NEXT:   0x180004000 00500000 04500000 00800000 01800000
 // CHECK-EMPTY:
 // CHECK-NEXT:   Hex dump of section '.ec':
-// CHECK-NEXT:   0x180006000 00500000 04500000 00700000 01700000
+// CHECK-NEXT:   0x180007000 00600000 04600000 00800000 01800000
 // CHECK-NEXT:   TLSDirectory {
-// CHECK-NEXT:     StartAddressOfRawData: 0x180007000
-// CHECK-NEXT:     EndAddressOfRawData: 0x180007001
-// CHECK-NEXT:     AddressOfIndex: 0x180005000
+// CHECK-NEXT:     StartAddressOfRawData: 0x180008000
+// CHECK-NEXT:     EndAddressOfRawData: 0x180008001
+// CHECK-NEXT:     AddressOfIndex: 0x180006000
 // CHECK-NEXT:     AddressOfCallBacks: 0x0
 // CHECK-NEXT:     SizeOfZeroFill: 0x0
 // CHECK-NEXT:     Characteristics [ (0x100000)
@@ -56,6 +56,52 @@
 // CHECK-NEXT:   }
 // CHECK-NEXT: }
 
+// RUN: lld-link -machine:arm64x -dll -noentry arm64ec.obj tls.lib -out:out-ec.dll
+// RUN: llvm-readobj --coff-tls-directory out-ec.dll | FileCheck --check-prefix=EC-ONLY %s
+// EC-ONLY:      Format: COFF-ARM64X
+// EC-ONLY-NEXT: Arch: aarch64
+// EC-ONLY-NEXT: AddressSize: 64bit
+// EC-ONLY-NEXT: TLSDirectory {
+// EC-ONLY-NEXT: }
+// EC-ONLY-NEXT: HybridObject {
+// EC-ONLY-NEXT:   Format: COFF-ARM64EC
+// EC-ONLY-NEXT:   Arch: aarch64
+// EC-ONLY-NEXT:   AddressSize: 64bit
+// EC-ONLY-NEXT:   TLSDirectory {
+// EC-ONLY-NEXT:     StartAddressOfRawData: 0x180006000
+// EC-ONLY-NEXT:     EndAddressOfRawData: 0x180006001
+// EC-ONLY-NEXT:     AddressOfIndex: 0x180004000
+// EC-ONLY-NEXT:     AddressOfCallBacks: 0x0
+// EC-ONLY-NEXT:     SizeOfZeroFill: 0x0
+// EC-ONLY-NEXT:     Characteristics [ (0x100000)
+// EC-ONLY-NEXT:       IMAGE_SCN_ALIGN_1BYTES (0x100000)
+// EC-ONLY-NEXT:     ]
+// EC-ONLY-NEXT:   }
+// EC-ONLY-NEXT: }
+
+// RUN: lld-link -machine:arm64x -dll -noentry aarch64.obj tls.lib -out:out-native.dll
+// RUN: llvm-readobj --coff-tls-directory out-native.dll | FileCheck --check-prefix=NATIVE-ONLY %s
+// NATIVE-ONLY:      Format: COFF-ARM64X
+// NATIVE-ONLY-NEXT: Arch: aarch64
+// NATIVE-ONLY-NEXT: AddressSize: 64bit
+// NATIVE-ONLY-NEXT: TLSDirectory {
+// NATIVE-ONLY-NEXT:   StartAddressOfRawData: 0x180006000
+// NATIVE-ONLY-NEXT:   EndAddressOfRawData: 0x180006001
+// NATIVE-ONLY-NEXT:   AddressOfIndex: 0x180005000
+// NATIVE-ONLY-NEXT:   AddressOfCallBacks: 0x0
+// NATIVE-ONLY-NEXT:   SizeOfZeroFill: 0x0
+// NATIVE-ONLY-NEXT:   Characteristics [ (0x100000)
+// NATIVE-ONLY-NEXT:     IMAGE_SCN_ALIGN_1BYTES (0x100000)
+// NATIVE-ONLY-NEXT:   ]
+// NATIVE-ONLY-NEXT: }
+// NATIVE-ONLY-NEXT: HybridObject {
+// NATIVE-ONLY-NEXT:   Format: COFF-ARM64EC
+// NATIVE-ONLY-NEXT:   Arch: aarch64
+// NATIVE-ONLY-NEXT:   AddressSize: 64bit
+// NATIVE-ONLY-NEXT:   TLSDirectory {
+// NATIVE-ONLY-NEXT:   }
+// NATIVE-ONLY-NEXT: }
+
 #--- tls-aarch64.s
         .section .defa64,"dr",discard,_tls_index
         .globl _tls_index

``````````

</details>


https://github.com/llvm/llvm-project/pull/214498


More information about the llvm-branch-commits mailing list