[lld] [LLD][COFF] Emit ARM64X relocations for CHPE ExtraRFETable entries (PR #126713)

Jacek Caban via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 13 10:19:14 PST 2025


https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/126713

>From feeca774f2061728deabb6c48779ea933b0539f9 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Tue, 11 Feb 2025 00:20:07 +0100
Subject: [PATCH] [LLD][COFF] Emit ARM64X relocations for CHPE ExtraRFETable
 entries

In the native view, ExtraEFRTable references the x86 exception table. The EC view references the ARM exception table, as it did before this change.
---
 lld/COFF/Writer.cpp              | 49 ++++++++++++++++++++++++++------
 lld/test/COFF/pdata-arm64ec.test | 14 +++++++--
 2 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index b03a4eab16ce2..678de915b6cdb 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -343,6 +343,9 @@ class Writer {
   // x86_64 .pdata sections on ARM64EC/ARM64X targets.
   ChunkRange hybridPdata;
 
+  // CHPE metadata symbol on ARM64C target.
+  DefinedRegular *chpeSym = nullptr;
+
   COFFLinkerContext &ctx;
 };
 } // anonymous namespace
@@ -2362,16 +2365,17 @@ void Writer::setECSymbols() {
     return a.first->getRVA() < b.first->getRVA();
   });
 
+  ChunkRange &chpePdata = ctx.hybridSymtab ? hybridPdata : pdata;
   Symbol *rfeTableSym = symtab->findUnderscore("__arm64x_extra_rfe_table");
   replaceSymbol<DefinedSynthetic>(rfeTableSym, "__arm64x_extra_rfe_table",
-                                  pdata.first);
+                                  chpePdata.first);
 
-  if (pdata.first) {
+  if (chpePdata.first) {
     Symbol *rfeSizeSym =
         symtab->findUnderscore("__arm64x_extra_rfe_table_size");
     cast<DefinedAbsolute>(rfeSizeSym)
-        ->setVA(pdata.last->getRVA() + pdata.last->getSize() -
-                pdata.first->getRVA());
+        ->setVA(chpePdata.last->getRVA() + chpePdata.last->getSize() -
+                chpePdata.first->getRVA());
   }
 
   Symbol *rangesCountSym =
@@ -2425,12 +2429,22 @@ void Writer::setECSymbols() {
               offsetof(data_directory, Size),
           symtab->edataEnd->getRVA() - symtab->edataStart->getRVA() +
               symtab->edataEnd->getSize());
-    if (hybridPdata.first)
+    if (hybridPdata.first) {
       ctx.dynamicRelocs->set(
           dataDirOffset64 + EXCEPTION_TABLE * sizeof(data_directory) +
               offsetof(data_directory, Size),
           hybridPdata.last->getRVA() - hybridPdata.first->getRVA() +
               hybridPdata.last->getSize());
+      if (chpeSym) {
+        size_t size = 0;
+        if (pdata.first)
+          size = pdata.last->getRVA() + pdata.last->getSize() -
+                 pdata.first->getRVA();
+        ctx.dynamicRelocs->set(chpeSym->getRVA() +
+                                   offsetof(chpe_metadata, ExtraRFETableSize),
+                               size);
+      }
+    }
   }
 }
 
@@ -2666,6 +2680,14 @@ void Writer::createDynamicRelocs() {
                          coffHeaderOffset + offsetof(coff_file_header, Machine),
                          AMD64);
 
+  if (ctx.symtab.entry != ctx.hybridSymtab->entry ||
+      pdata.first != hybridPdata.first) {
+    chpeSym = cast_or_null<DefinedRegular>(
+        ctx.hybridSymtab->findUnderscore("__chpe_metadata"));
+    if (!chpeSym)
+      Warn(ctx) << "'__chpe_metadata' is missing for ARM64X target";
+  }
+
   if (ctx.symtab.entry != ctx.hybridSymtab->entry) {
     ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
                            peHeaderOffset +
@@ -2673,14 +2695,11 @@ void Writer::createDynamicRelocs() {
                            cast_or_null<Defined>(ctx.hybridSymtab->entry));
 
     // Swap the alternate entry point in the CHPE metadata.
-    Symbol *s = ctx.hybridSymtab->findUnderscore("__chpe_metadata");
-    if (auto chpeSym = cast_or_null<DefinedRegular>(s))
+    if (chpeSym)
       ctx.dynamicRelocs->add(
           IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
           Arm64XRelocVal(chpeSym, offsetof(chpe_metadata, AlternateEntryPoint)),
           cast_or_null<Defined>(ctx.symtab.entry));
-    else
-      Warn(ctx) << "'__chpe_metadata' is missing for ARM64X target";
   }
 
   if (ctx.symtab.edataStart != ctx.hybridSymtab->edataStart) {
@@ -2707,6 +2726,18 @@ void Writer::createDynamicRelocs() {
                            dataDirOffset64 +
                                EXCEPTION_TABLE * sizeof(data_directory) +
                                offsetof(data_directory, Size));
+
+    // Swap ExtraRFETable in the CHPE metadata.
+    if (chpeSym) {
+      ctx.dynamicRelocs->add(
+          IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
+          Arm64XRelocVal(chpeSym, offsetof(chpe_metadata, ExtraRFETable)),
+          pdata.first);
+      // The Size value is assigned after addresses are finalized.
+      ctx.dynamicRelocs->add(
+          IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
+          Arm64XRelocVal(chpeSym, offsetof(chpe_metadata, ExtraRFETableSize)));
+    }
   }
 
   // Set the hybrid load config to the EC load config.
diff --git a/lld/test/COFF/pdata-arm64ec.test b/lld/test/COFF/pdata-arm64ec.test
index fbec797525f7f..cf59330b23543 100644
--- a/lld/test/COFF/pdata-arm64ec.test
+++ b/lld/test/COFF/pdata-arm64ec.test
@@ -58,18 +58,26 @@ Mixed arm64x code:
 RUN: lld-link -out:test4.dll -machine:arm64x arm64-func-sym.obj arm64ec-func-sym.obj \
 RUN:          x86_64-func-sym.obj loadconfig-arm64.obj loadconfig-arm64ec.obj -dll -noentry
 
-RUN: llvm-readobj --headers test4.dll | FileCheck -check-prefix=DIR3 %s
+RUN: llvm-readobj --headers --coff-load-config test4.dll | FileCheck -check-prefix=DIR3 %s
 DIR3:      ImageOptionalHeader {
 DIR3:        DataDirectory {
 DIR3:          ExceptionTableRVA: 0x6000
 DIR3-NEXT:     ExceptionTableSize: 0x10
 DIR3:        }
 DIR3:      }
+DIR3:      CHPEMetadata [
+DIR3:        ExtraRFETable: 0x6010
+DIR3-NEXT:   ExtraRFETableSize: 0xC
+DIR3:      ]
 DIR3:      HybridObject {
 DIR3:        ImageOptionalHeader {
 DIR3:          ExceptionTableRVA: 0x6010
 DIR3-NEXT:     ExceptionTableSize: 0xC
 DIR3:        }
+DIR3:        CHPEMetadata [
+DIR3:          ExtraRFETable: 0x6000
+DIR3-NEXT:     ExtraRFETableSize: 0x10
+DIR3:        ]
 DIR3:      }
 
 RUN: llvm-objdump -s --section=.pdata test4.dll | FileCheck -check-prefix=DATA4 %s
@@ -86,12 +94,12 @@ RUN: llvm-objdump -s --section=.pdata test5.dll | FileCheck -check-prefix=DATA3
 
 RUN: lld-link -out:test6.dll -machine:arm64x arm64ec-func-sym.obj x86_64-func-sym.obj \
 RUN:          arm64-func-sym.obj loadconfig-arm64.obj loadconfig-arm64ec.obj -dll -noentry
-RUN: llvm-readobj --headers test6.dll | FileCheck -check-prefix=DIR3 %s
+RUN: llvm-readobj --headers --coff-load-config test6.dll | FileCheck -check-prefix=DIR3 %s
 RUN: llvm-objdump -s --section=.pdata test6.dll | FileCheck -check-prefix=DATA4 %s
 
 RUN: lld-link -out:test7.dll -machine:arm64x x86_64-func-sym.obj arm64ec-func-sym.obj \
 RUN:          arm64-func-sym.obj loadconfig-arm64.obj loadconfig-arm64ec.obj -dll -noentry
-RUN: llvm-readobj --headers test7.dll | FileCheck -check-prefix=DIR3 %s
+RUN: llvm-readobj --headers --coff-load-config test7.dll | FileCheck -check-prefix=DIR3 %s
 RUN: llvm-objdump -s --section=.pdata test7.dll | FileCheck -check-prefix=DATA4 %s
 
 #--- arm64-func-sym.s



More information about the llvm-commits mailing list