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

Jacek Caban via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 11 03:05:41 PST 2025


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

In the native view, ExtraEFRTable references the x86 exception table. The EC view references the ARM exception table, as it did before this change.

>From 704f3425719c50780d1f61e5732ad3071c78d745 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 484ac9cdcaf9eaf..05edbd3e07b4200 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
@@ -2360,16 +2363,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 =
@@ -2423,12 +2427,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.first->getRVA() +
+                 pdata.last->getSize();
+        ctx.dynamicRelocs->set(chpeSym->getRVA() +
+                                   offsetof(chpe_metadata, ExtraRFETableSize),
+                               size);
+      }
+    }
   }
 }
 
@@ -2664,6 +2678,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 +
@@ -2671,14 +2693,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) {
@@ -2705,6 +2724,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 fbec797525f7f8f..cf59330b2354377 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