-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[LLD][COFF] Add support for CHPE code ranges metadata. #105741
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lld-coff @llvm/pr-subscribers-platform-windows Author: Jacek Caban (cjacek) ChangesThis is part of CHPE metadata containing a sorted list of x86_64 export thunks RVAs and sizes. Full diff: https://github.com/llvm/llvm-project/pull/105741.diff 7 Files Affected:
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index be44950a1720e3..72a9ad05ca11c1 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -1078,4 +1078,33 @@ 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);
+}
+
+void CHPERedirectionChunk::writeTo(uint8_t *buf) const {
+ auto entries = reinterpret_cast<chpe_redirection_entry *>(buf);
+
+ for (uint32_t i = 0; i < exportThunks.size(); i++) {
+ entries[i].Source = exportThunks[i].first->getRVA();
+ entries[i].Destination = exportThunks[i].second->getRVA();
+ }
+}
+
} // namespace lld::coff
diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index 5443d4619a977e..fe202008971a54 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -749,6 +749,28 @@ 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)
+ : exportThunks(exportThunks) {}
+ size_t getSize() const override;
+ void writeTo(uint8_t *buf) const override;
+
+private:
+ std::vector<std::pair<Chunk *, Defined *>> &exportThunks;
+};
+
static const uint8_t ECExportThunkCode[] = {
0x48, 0x8b, 0xc4, // movq %rsp, %rax
0x48, 0x89, 0x58, 0x20, // movq %rbx, 0x20(%rax)
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index c09c91fe4b1719..3ef9fa3f65c6a6 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2440,8 +2440,12 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (isArm64EC(config->machine)) {
ctx.symtab.addAbsolute("__arm64x_extra_rfe_table", 0);
ctx.symtab.addAbsolute("__arm64x_extra_rfe_table_size", 0);
+ ctx.symtab.addAbsolute("__arm64x_redirection_metadata", 0);
+ 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 776595d98c391d..0360e186ecf0cf 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -298,6 +298,9 @@ class Writer {
CVDebugRecordChunk *buildId = nullptr;
ArrayRef<uint8_t> sectionTable;
+ // List of Arm64EC export thunks.
+ std::vector<std::pair<Chunk *, Defined *>> exportThunks;
+
uint64_t fileSize;
uint32_t pointerToSymbolTable = 0;
uint64_t sizeOfImage;
@@ -312,6 +315,7 @@ class Writer {
OutputSection *idataSec;
OutputSection *edataSec;
OutputSection *didatSec;
+ OutputSection *a64xrmSec;
OutputSection *rsrcSec;
OutputSection *relocSec;
OutputSection *ctorsSec;
@@ -995,6 +999,8 @@ void Writer::createSections() {
idataSec = createSection(".idata", data | r);
edataSec = createSection(".edata", data | r);
didatSec = createSection(".didat", data | r);
+ if (isArm64EC(ctx.config.machine))
+ a64xrmSec = createSection(".a64xrm", data | r);
rsrcSec = createSection(".rsrc", data | r);
relocSec = createSection(".reloc", data | discardable | r);
ctorsSec = createSection(".ctors", data | r | w);
@@ -2053,8 +2059,10 @@ void Writer::createECChunks() {
auto sym = dyn_cast<Defined>(s);
if (!sym || !sym->getChunk())
continue;
- if (auto thunk = dyn_cast<ECExportThunkChunk>(sym->getChunk()))
+ if (auto thunk = dyn_cast<ECExportThunkChunk>(sym->getChunk())) {
hexpthkSec->addChunk(thunk);
+ exportThunks.push_back({thunk, thunk->target});
+ }
}
auto codeMapChunk = make<ECCodeMapChunk>(codeMap);
@@ -2062,6 +2070,19 @@ void Writer::createECChunks() {
Symbol *codeMapSym = ctx.symtab.findUnderscore("__hybrid_code_map");
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 =
+ ctx.symtab.findUnderscore("__arm64x_redirection_metadata");
+ replaceSymbol<DefinedSynthetic>(entryPointsSym, entryPointsSym->getName(),
+ entryPoints);
}
// MinGW specific. Gather all relocations that are imported from a DLL even
@@ -2154,6 +2175,11 @@ void Writer::setECSymbols() {
if (!isArm64EC(ctx.config.machine))
return;
+ llvm::stable_sort(exportThunks, [](const std::pair<Chunk *, Defined *> &a,
+ const std::pair<Chunk *, Defined *> &b) {
+ return a.first->getRVA() < b.first->getRVA();
+ });
+
Symbol *rfeTableSym = ctx.symtab.findUnderscore("__arm64x_extra_rfe_table");
replaceSymbol<DefinedSynthetic>(rfeTableSym, "__arm64x_extra_rfe_table",
pdata.first);
@@ -2165,6 +2191,14 @@ void Writer::setECSymbols() {
->setVA(pdata.last->getRVA() + pdata.last->getSize() -
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());
}
// Write section contents to a mmap'ed file.
diff --git a/lld/test/COFF/Inputs/loadconfig-arm64ec.s b/lld/test/COFF/Inputs/loadconfig-arm64ec.s
index a270d281095dd6..78e7fba43a0a4d 100644
--- a/lld/test/COFF/Inputs/loadconfig-arm64ec.s
+++ b/lld/test/COFF/Inputs/loadconfig-arm64ec.s
@@ -66,8 +66,8 @@ __chpe_metadata:
.word 1
.rva __hybrid_code_map
.word __hybrid_code_map_count
- .word 0 // __x64_code_ranges_to_entry_points
- .word 0 //__arm64x_redirection_metadata
+ .rva __x64_code_ranges_to_entry_points
+ .rva __arm64x_redirection_metadata
.rva __os_arm64x_dispatch_call_no_redirect
.rva __os_arm64x_dispatch_ret
.rva __os_arm64x_check_call
@@ -75,8 +75,8 @@ __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 0 // __arm64x_redirection_metadata_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
.rva __arm64x_extra_rfe_table
diff --git a/lld/test/COFF/arm64ec-export-thunks.test b/lld/test/COFF/arm64ec-export-thunks.test
index 6ed0514d4b17f3..809fac1f24a7dc 100644
--- a/lld/test/COFF/arm64ec-export-thunks.test
+++ b/lld/test/COFF/arm64ec-export-thunks.test
@@ -49,7 +49,7 @@ EXP-DISASM-NEXT: 18000301f: cc int3
RUN: llvm-objdump -p exports.dll | FileCheck -check-prefix=EXP-EXPORT %s
EXP-EXPORT: Ordinal RVA Name
EXP-EXPORT-NEXT: 1 0x3010 arm64ec_func
-EXP-EXPORT-NEXT: 2 0x6000 data_sym
+EXP-EXPORT-NEXT: 2 0x7000 data_sym
EXP-EXPORT-NEXT: 3 0x3000 func
EXP-EXPORT-NEXT: 4 0x2000 x86_64_func
@@ -58,9 +58,33 @@ EXP-CHPE: CodeMap [
EXP-CHPE-NEXT: 0x1000 - 0x100C ARM64EC
EXP-CHPE-NEXT: 0x2000 - 0x3020 X64
EXP-CHPE-NEXT: ]
+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
+EXP-CHPE-NEXT: ]
+
+RUN: llvm-readobj --sections exports.dll | FileCheck --check-prefix=A64XRM %s
+
+A64XRM: Name: .a64xrm (2E 61 36 34 78 72 6D 00)
+A64XRM-NEXT: VirtualSize: 0x10
+A64XRM-NEXT: VirtualAddress: 0x6000
+A64XRM-NEXT: RawDataSize: 512
+A64XRM-NEXT: PointerToRawData:
+A64XRM-NEXT: PointerToRelocations: 0x0
+A64XRM-NEXT: PointerToLineNumbers: 0x0
+A64XRM-NEXT: RelocationCount: 0
+A64XRM-NEXT: LineNumberCount: 0
+A64XRM-NEXT: Characteristics [ (0x40000040)
+A64XRM-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
+A64XRM-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
+A64XRM-NEXT: ]
RUN: llvm-objdump -s --section=.test exports.dll | FileCheck --check-prefix=EXP-DATA %s
-EXP-DATA: 180006000 00300000 10300000
+EXP-DATA: 180007000 00300000 10300000
RUN: lld-link -out:exports2.dll -machine:arm64ec antidep-func.obj x86_64-func.obj loadconfig-arm64ec.obj \
RUN: arm64ec-data.obj -dll -noentry -export:arm64ec_func -export:func=arm64ec_func \
@@ -100,6 +124,12 @@ ENTRY-CHPE: CodeMap [
ENTRY-CHPE-NEXT: 0x1000 - 0x100C ARM64EC
ENTRY-CHPE-NEXT: 0x2000 - 0x2010 X64
ENTRY-CHPE-NEXT: ]
+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: ]
Test exporting data symbol as a function:
diff --git a/lld/test/COFF/arm64ec-patchable-thunks.test b/lld/test/COFF/arm64ec-patchable-thunks.test
index cccd42eebfd367..5cebe7cc27ad63 100644
--- a/lld/test/COFF/arm64ec-patchable-thunks.test
+++ b/lld/test/COFF/arm64ec-patchable-thunks.test
@@ -27,13 +27,19 @@ PATCH-DISASM-NEXT: 18000200e: cc int3
PATCH-DISASM-NEXT: 18000200f: cc int3
RUN: llvm-readobj --hex-dump=.test test.dll | FileCheck -check-prefix=RVA %s
-RVA: 0x180005000 00200000
+RVA: 0x180006000 00200000
RUN: llvm-readobj --coff-load-config test.dll | FileCheck -check-prefix=PATCH-CHPE %s
PATCH-CHPE: CodeMap [
PATCH-CHPE-NEXT: 0x1000 - 0x1008 ARM64EC
PATCH-CHPE-NEXT: 0x2000 - 0x2010 X64
PATCH-CHPE-NEXT: ]
+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: ]
RUN: lld-link -out:test2.dll -machine:arm64ec arm64ec-alias.obj test-sec.obj loadconfig-arm64ec.obj -dll -noentry
|
@llvm/pr-subscribers-lld Author: Jacek Caban (cjacek) ChangesThis is part of CHPE metadata containing a sorted list of x86_64 export thunks RVAs and sizes. Full diff: https://github.com/llvm/llvm-project/pull/105741.diff 7 Files Affected:
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index be44950a1720e3..72a9ad05ca11c1 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -1078,4 +1078,33 @@ 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);
+}
+
+void CHPERedirectionChunk::writeTo(uint8_t *buf) const {
+ auto entries = reinterpret_cast<chpe_redirection_entry *>(buf);
+
+ for (uint32_t i = 0; i < exportThunks.size(); i++) {
+ entries[i].Source = exportThunks[i].first->getRVA();
+ entries[i].Destination = exportThunks[i].second->getRVA();
+ }
+}
+
} // namespace lld::coff
diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index 5443d4619a977e..fe202008971a54 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -749,6 +749,28 @@ 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)
+ : exportThunks(exportThunks) {}
+ size_t getSize() const override;
+ void writeTo(uint8_t *buf) const override;
+
+private:
+ std::vector<std::pair<Chunk *, Defined *>> &exportThunks;
+};
+
static const uint8_t ECExportThunkCode[] = {
0x48, 0x8b, 0xc4, // movq %rsp, %rax
0x48, 0x89, 0x58, 0x20, // movq %rbx, 0x20(%rax)
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index c09c91fe4b1719..3ef9fa3f65c6a6 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2440,8 +2440,12 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (isArm64EC(config->machine)) {
ctx.symtab.addAbsolute("__arm64x_extra_rfe_table", 0);
ctx.symtab.addAbsolute("__arm64x_extra_rfe_table_size", 0);
+ ctx.symtab.addAbsolute("__arm64x_redirection_metadata", 0);
+ 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 776595d98c391d..0360e186ecf0cf 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -298,6 +298,9 @@ class Writer {
CVDebugRecordChunk *buildId = nullptr;
ArrayRef<uint8_t> sectionTable;
+ // List of Arm64EC export thunks.
+ std::vector<std::pair<Chunk *, Defined *>> exportThunks;
+
uint64_t fileSize;
uint32_t pointerToSymbolTable = 0;
uint64_t sizeOfImage;
@@ -312,6 +315,7 @@ class Writer {
OutputSection *idataSec;
OutputSection *edataSec;
OutputSection *didatSec;
+ OutputSection *a64xrmSec;
OutputSection *rsrcSec;
OutputSection *relocSec;
OutputSection *ctorsSec;
@@ -995,6 +999,8 @@ void Writer::createSections() {
idataSec = createSection(".idata", data | r);
edataSec = createSection(".edata", data | r);
didatSec = createSection(".didat", data | r);
+ if (isArm64EC(ctx.config.machine))
+ a64xrmSec = createSection(".a64xrm", data | r);
rsrcSec = createSection(".rsrc", data | r);
relocSec = createSection(".reloc", data | discardable | r);
ctorsSec = createSection(".ctors", data | r | w);
@@ -2053,8 +2059,10 @@ void Writer::createECChunks() {
auto sym = dyn_cast<Defined>(s);
if (!sym || !sym->getChunk())
continue;
- if (auto thunk = dyn_cast<ECExportThunkChunk>(sym->getChunk()))
+ if (auto thunk = dyn_cast<ECExportThunkChunk>(sym->getChunk())) {
hexpthkSec->addChunk(thunk);
+ exportThunks.push_back({thunk, thunk->target});
+ }
}
auto codeMapChunk = make<ECCodeMapChunk>(codeMap);
@@ -2062,6 +2070,19 @@ void Writer::createECChunks() {
Symbol *codeMapSym = ctx.symtab.findUnderscore("__hybrid_code_map");
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 =
+ ctx.symtab.findUnderscore("__arm64x_redirection_metadata");
+ replaceSymbol<DefinedSynthetic>(entryPointsSym, entryPointsSym->getName(),
+ entryPoints);
}
// MinGW specific. Gather all relocations that are imported from a DLL even
@@ -2154,6 +2175,11 @@ void Writer::setECSymbols() {
if (!isArm64EC(ctx.config.machine))
return;
+ llvm::stable_sort(exportThunks, [](const std::pair<Chunk *, Defined *> &a,
+ const std::pair<Chunk *, Defined *> &b) {
+ return a.first->getRVA() < b.first->getRVA();
+ });
+
Symbol *rfeTableSym = ctx.symtab.findUnderscore("__arm64x_extra_rfe_table");
replaceSymbol<DefinedSynthetic>(rfeTableSym, "__arm64x_extra_rfe_table",
pdata.first);
@@ -2165,6 +2191,14 @@ void Writer::setECSymbols() {
->setVA(pdata.last->getRVA() + pdata.last->getSize() -
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());
}
// Write section contents to a mmap'ed file.
diff --git a/lld/test/COFF/Inputs/loadconfig-arm64ec.s b/lld/test/COFF/Inputs/loadconfig-arm64ec.s
index a270d281095dd6..78e7fba43a0a4d 100644
--- a/lld/test/COFF/Inputs/loadconfig-arm64ec.s
+++ b/lld/test/COFF/Inputs/loadconfig-arm64ec.s
@@ -66,8 +66,8 @@ __chpe_metadata:
.word 1
.rva __hybrid_code_map
.word __hybrid_code_map_count
- .word 0 // __x64_code_ranges_to_entry_points
- .word 0 //__arm64x_redirection_metadata
+ .rva __x64_code_ranges_to_entry_points
+ .rva __arm64x_redirection_metadata
.rva __os_arm64x_dispatch_call_no_redirect
.rva __os_arm64x_dispatch_ret
.rva __os_arm64x_check_call
@@ -75,8 +75,8 @@ __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 0 // __arm64x_redirection_metadata_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
.rva __arm64x_extra_rfe_table
diff --git a/lld/test/COFF/arm64ec-export-thunks.test b/lld/test/COFF/arm64ec-export-thunks.test
index 6ed0514d4b17f3..809fac1f24a7dc 100644
--- a/lld/test/COFF/arm64ec-export-thunks.test
+++ b/lld/test/COFF/arm64ec-export-thunks.test
@@ -49,7 +49,7 @@ EXP-DISASM-NEXT: 18000301f: cc int3
RUN: llvm-objdump -p exports.dll | FileCheck -check-prefix=EXP-EXPORT %s
EXP-EXPORT: Ordinal RVA Name
EXP-EXPORT-NEXT: 1 0x3010 arm64ec_func
-EXP-EXPORT-NEXT: 2 0x6000 data_sym
+EXP-EXPORT-NEXT: 2 0x7000 data_sym
EXP-EXPORT-NEXT: 3 0x3000 func
EXP-EXPORT-NEXT: 4 0x2000 x86_64_func
@@ -58,9 +58,33 @@ EXP-CHPE: CodeMap [
EXP-CHPE-NEXT: 0x1000 - 0x100C ARM64EC
EXP-CHPE-NEXT: 0x2000 - 0x3020 X64
EXP-CHPE-NEXT: ]
+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
+EXP-CHPE-NEXT: ]
+
+RUN: llvm-readobj --sections exports.dll | FileCheck --check-prefix=A64XRM %s
+
+A64XRM: Name: .a64xrm (2E 61 36 34 78 72 6D 00)
+A64XRM-NEXT: VirtualSize: 0x10
+A64XRM-NEXT: VirtualAddress: 0x6000
+A64XRM-NEXT: RawDataSize: 512
+A64XRM-NEXT: PointerToRawData:
+A64XRM-NEXT: PointerToRelocations: 0x0
+A64XRM-NEXT: PointerToLineNumbers: 0x0
+A64XRM-NEXT: RelocationCount: 0
+A64XRM-NEXT: LineNumberCount: 0
+A64XRM-NEXT: Characteristics [ (0x40000040)
+A64XRM-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
+A64XRM-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
+A64XRM-NEXT: ]
RUN: llvm-objdump -s --section=.test exports.dll | FileCheck --check-prefix=EXP-DATA %s
-EXP-DATA: 180006000 00300000 10300000
+EXP-DATA: 180007000 00300000 10300000
RUN: lld-link -out:exports2.dll -machine:arm64ec antidep-func.obj x86_64-func.obj loadconfig-arm64ec.obj \
RUN: arm64ec-data.obj -dll -noentry -export:arm64ec_func -export:func=arm64ec_func \
@@ -100,6 +124,12 @@ ENTRY-CHPE: CodeMap [
ENTRY-CHPE-NEXT: 0x1000 - 0x100C ARM64EC
ENTRY-CHPE-NEXT: 0x2000 - 0x2010 X64
ENTRY-CHPE-NEXT: ]
+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: ]
Test exporting data symbol as a function:
diff --git a/lld/test/COFF/arm64ec-patchable-thunks.test b/lld/test/COFF/arm64ec-patchable-thunks.test
index cccd42eebfd367..5cebe7cc27ad63 100644
--- a/lld/test/COFF/arm64ec-patchable-thunks.test
+++ b/lld/test/COFF/arm64ec-patchable-thunks.test
@@ -27,13 +27,19 @@ PATCH-DISASM-NEXT: 18000200e: cc int3
PATCH-DISASM-NEXT: 18000200f: cc int3
RUN: llvm-readobj --hex-dump=.test test.dll | FileCheck -check-prefix=RVA %s
-RVA: 0x180005000 00200000
+RVA: 0x180006000 00200000
RUN: llvm-readobj --coff-load-config test.dll | FileCheck -check-prefix=PATCH-CHPE %s
PATCH-CHPE: CodeMap [
PATCH-CHPE-NEXT: 0x1000 - 0x1008 ARM64EC
PATCH-CHPE-NEXT: 0x2000 - 0x2010 X64
PATCH-CHPE-NEXT: ]
+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: ]
RUN: lld-link -out:test2.dll -machine:arm64ec arm64ec-alias.obj test-sec.obj loadconfig-arm64ec.obj -dll -noentry
|
Depends on #105739. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also looks good to me, thanks!
uint32_t start = thunk->getRVA(); | ||
ranges[i].StartRva = start; | ||
ranges[i].EndRva = start + thunk->getSize(); | ||
ranges[i].EntryPoint = start; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this is a similar list as #105739, with the same start RVAs, but containing the size and not the destination? And the EntryPoint
value seems pointless at this point, I presume it will seem more useful after some more future patches.
(I.e. I'm not questioning this patch, I'm questioning the usefulness of this data structure - but I guess it makes more sense when more complete.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid it doesn't make more sense even when it's more complete. I've never seen StartRva and EntryPoint differ, even with some unusual synthetic inputs that I experimented with for custom export thunks. I’m not sure why it’s structured this way. Instead of duplicating the value in EntryPoint, I imagine it could store the redirection destination here and use a single structure instead of separate ones for redirection and code ranges.
As for how these structures are used, I can only speculate, so please keep in mind that this is just a guess. I think it might be useful for auxiliary IAT handling. The loader needs to populate the auxiliary IAT with addresses of actual ARM64EC functions, where something like redirection metadata could be used. It would also need to detect runtime patching of x86 thunks to know when to revert the auxiliary IAT to go through the call checker. For that, it would additionally need to know the thunks' sizes, which is what the code ranges metadata provides.
This is part of CHPE metadata containing a sorted list of x86_64 export thunks RVAs and sizes.
ecd7bbf
to
dee0f2b
Compare
Merged, thanks for reviews! |
This is part of CHPE metadata containing a sorted list of x86_64 export thunks RVAs and sizes.