[lld] [LLD][COFF] Add support for CHPE code ranges metadata. (PR #105741)

Jacek Caban via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 23 12:16:44 PDT 2024


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

>From dee0f2b6ef96307a3464a09eeafb16b4be1d61fd Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Mon, 19 Aug 2024 11:08:22 +0200
Subject: [PATCH] [LLD][COFF] Add support for CHPE code ranges metadata.

This is part of CHPE metadata containing a sorted list of x86_64 export thunks RVAs and sizes.
---
 lld/COFF/Chunks.cpp                         | 16 ++++++++++++++++
 lld/COFF/Chunks.h                           | 11 +++++++++++
 lld/COFF/Driver.cpp                         |  2 ++
 lld/COFF/Writer.cpp                         | 10 ++++++++++
 lld/test/COFF/Inputs/loadconfig-arm64ec.s   |  4 ++--
 lld/test/COFF/arm64ec-export-thunks.test    |  9 +++++++--
 lld/test/COFF/arm64ec-patchable-thunks.test |  4 +++-
 7 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 4e3a564ebacd87..72a9ad05ca11c1 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -1078,6 +1078,22 @@ void ECExportThunkChunk::writeTo(uint8_t *buf) const {
   write32le(buf + 10, target->getRVA() - rva - 14);
 }
 
+size_t CHPECodeRangesChunk::getSize() const {
+  return exportThunks.size() * sizeof(chpe_code_range_entry);
+}
+
+void CHPECodeRangesChunk::writeTo(uint8_t *buf) const {
+  auto ranges = reinterpret_cast<chpe_code_range_entry *>(buf);
+
+  for (uint32_t i = 0; i < exportThunks.size(); i++) {
+    Chunk *thunk = exportThunks[i].first;
+    uint32_t start = thunk->getRVA();
+    ranges[i].StartRva = start;
+    ranges[i].EndRva = start + thunk->getSize();
+    ranges[i].EntryPoint = start;
+  }
+}
+
 size_t CHPERedirectionChunk::getSize() const {
   return exportThunks.size() * sizeof(chpe_redirection_entry);
 }
diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index 015df41b04c67d..fe202008971a54 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -749,6 +749,17 @@ class ECCodeMapChunk : public NonSectionChunk {
   std::vector<ECCodeMapEntry> ↦
 };
 
+class CHPECodeRangesChunk : public NonSectionChunk {
+public:
+  CHPECodeRangesChunk(std::vector<std::pair<Chunk *, Defined *>> &exportThunks)
+      : exportThunks(exportThunks) {}
+  size_t getSize() const override;
+  void writeTo(uint8_t *buf) const override;
+
+private:
+  std::vector<std::pair<Chunk *, Defined *>> &exportThunks;
+};
+
 class CHPERedirectionChunk : public NonSectionChunk {
 public:
   CHPERedirectionChunk(std::vector<std::pair<Chunk *, Defined *>> &exportThunks)
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 472f5074ba8b8c..3ef9fa3f65c6a6 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2444,6 +2444,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     ctx.symtab.addAbsolute("__arm64x_redirection_metadata_count", 0);
     ctx.symtab.addAbsolute("__hybrid_code_map", 0);
     ctx.symtab.addAbsolute("__hybrid_code_map_count", 0);
+    ctx.symtab.addAbsolute("__x64_code_ranges_to_entry_points", 0);
+    ctx.symtab.addAbsolute("__x64_code_ranges_to_entry_points_count", 0);
   }
 
   if (config->pseudoRelocs) {
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 358d16fe330cea..0360e186ecf0cf 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -2071,6 +2071,12 @@ void Writer::createECChunks() {
   replaceSymbol<DefinedSynthetic>(codeMapSym, codeMapSym->getName(),
                                   codeMapChunk);
 
+  CHPECodeRangesChunk *ranges = make<CHPECodeRangesChunk>(exportThunks);
+  rdataSec->addChunk(ranges);
+  Symbol *rangesSym =
+      ctx.symtab.findUnderscore("__x64_code_ranges_to_entry_points");
+  replaceSymbol<DefinedSynthetic>(rangesSym, rangesSym->getName(), ranges);
+
   CHPERedirectionChunk *entryPoints = make<CHPERedirectionChunk>(exportThunks);
   a64xrmSec->addChunk(entryPoints);
   Symbol *entryPointsSym =
@@ -2186,6 +2192,10 @@ void Writer::setECSymbols() {
                 pdata.first->getRVA());
   }
 
+  Symbol *rangesCountSym =
+      ctx.symtab.findUnderscore("__x64_code_ranges_to_entry_points_count");
+  cast<DefinedAbsolute>(rangesCountSym)->setVA(exportThunks.size());
+
   Symbol *entryPointCountSym =
       ctx.symtab.findUnderscore("__arm64x_redirection_metadata_count");
   cast<DefinedAbsolute>(entryPointCountSym)->setVA(exportThunks.size());
diff --git a/lld/test/COFF/Inputs/loadconfig-arm64ec.s b/lld/test/COFF/Inputs/loadconfig-arm64ec.s
index 62a6d0cab642e9..78e7fba43a0a4d 100644
--- a/lld/test/COFF/Inputs/loadconfig-arm64ec.s
+++ b/lld/test/COFF/Inputs/loadconfig-arm64ec.s
@@ -66,7 +66,7 @@ __chpe_metadata:
         .word 1
         .rva __hybrid_code_map
         .word __hybrid_code_map_count
-        .word 0 // __x64_code_ranges_to_entry_points
+        .rva __x64_code_ranges_to_entry_points
         .rva __arm64x_redirection_metadata
         .rva __os_arm64x_dispatch_call_no_redirect
         .rva __os_arm64x_dispatch_ret
@@ -75,7 +75,7 @@ __chpe_metadata:
         .rva __os_arm64x_check_icall_cfg
         .word 0 // __arm64x_native_entrypoint
         .word 0 // __hybrid_auxiliary_iat
-        .word 0 // __x64_code_ranges_to_entry_points_count
+        .word __x64_code_ranges_to_entry_points_count
         .word __arm64x_redirection_metadata_count
         .rva __os_arm64x_get_x64_information
         .rva __os_arm64x_set_x64_information
diff --git a/lld/test/COFF/arm64ec-export-thunks.test b/lld/test/COFF/arm64ec-export-thunks.test
index 2e4cfd6203b751..809fac1f24a7dc 100644
--- a/lld/test/COFF/arm64ec-export-thunks.test
+++ b/lld/test/COFF/arm64ec-export-thunks.test
@@ -58,7 +58,10 @@ EXP-CHPE:       CodeMap [
 EXP-CHPE-NEXT:    0x1000 - 0x100C  ARM64EC
 EXP-CHPE-NEXT:    0x2000 - 0x3020  X64
 EXP-CHPE-NEXT:  ]
-EXP-CHPE-NEXT:  CodeRangesToEntryPoints: 0
+EXP-CHPE-NEXT:  CodeRangesToEntryPoints [
+EXP-CHPE-NEXT:    0x3000 - 0x3010 -> 0x3000
+EXP-CHPE-NEXT:    0x3010 - 0x3020 -> 0x3010
+EXP-CHPE-NEXT:  ]
 EXP-CHPE-NEXT:  RedirectionMetadata [
 EXP-CHPE-NEXT:    0x3000 -> 0x1000
 EXP-CHPE-NEXT:    0x3010 -> 0x1000
@@ -121,7 +124,9 @@ ENTRY-CHPE:       CodeMap [
 ENTRY-CHPE-NEXT:    0x1000 - 0x100C  ARM64EC
 ENTRY-CHPE-NEXT:    0x2000 - 0x2010  X64
 ENTRY-CHPE-NEXT:  ]
-ENTRY-CHPE-NEXT:  CodeRangesToEntryPoints: 0
+ENTRY-CHPE-NEXT:  CodeRangesToEntryPoints [
+ENTRY-CHPE-NEXT:    0x2000 - 0x2010 -> 0x2000
+ENTRY-CHPE-NEXT:  ]
 ENTRY-CHPE-NEXT:  RedirectionMetadata [
 ENTRY-CHPE-NEXT:    0x2000 -> 0x1000
 ENTRY-CHPE-NEXT:  ]
diff --git a/lld/test/COFF/arm64ec-patchable-thunks.test b/lld/test/COFF/arm64ec-patchable-thunks.test
index 044f3c7cebdf8e..5cebe7cc27ad63 100644
--- a/lld/test/COFF/arm64ec-patchable-thunks.test
+++ b/lld/test/COFF/arm64ec-patchable-thunks.test
@@ -34,7 +34,9 @@ PATCH-CHPE:       CodeMap [
 PATCH-CHPE-NEXT:    0x1000 - 0x1008  ARM64EC
 PATCH-CHPE-NEXT:    0x2000 - 0x2010  X64
 PATCH-CHPE-NEXT:  ]
-PATCH-CHPE-NEXT:  CodeRangesToEntryPoints: 0
+PATCH-CHPE-NEXT:  CodeRangesToEntryPoints [
+PATCH-CHPE-NEXT:    0x2000 - 0x2010 -> 0x2000
+PATCH-CHPE-NEXT:  ]
 PATCH-CHPE-NEXT:  RedirectionMetadata [
 PATCH-CHPE-NEXT:    0x2000 -> 0x1000
 PATCH-CHPE-NEXT:  ]



More information about the llvm-commits mailing list