Skip to content

Commit caa844e

Browse files
authored
[LLD][COFF] Add support for CHPE redirection metadata. (llvm#105739)
This is part of CHPE metadata containing a sorted list of x86_64 export thunks RVAs and RVAs of ARM64EC functions associated with them. It's stored in a dedicated .a64xrm section.
1 parent 57b89fd commit caa844e

File tree

7 files changed

+85
-6
lines changed

7 files changed

+85
-6
lines changed

lld/COFF/Chunks.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,4 +1078,17 @@ void ECExportThunkChunk::writeTo(uint8_t *buf) const {
10781078
write32le(buf + 10, target->getRVA() - rva - 14);
10791079
}
10801080

1081+
size_t CHPERedirectionChunk::getSize() const {
1082+
return exportThunks.size() * sizeof(chpe_redirection_entry);
1083+
}
1084+
1085+
void CHPERedirectionChunk::writeTo(uint8_t *buf) const {
1086+
auto entries = reinterpret_cast<chpe_redirection_entry *>(buf);
1087+
1088+
for (uint32_t i = 0; i < exportThunks.size(); i++) {
1089+
entries[i].Source = exportThunks[i].first->getRVA();
1090+
entries[i].Destination = exportThunks[i].second->getRVA();
1091+
}
1092+
}
1093+
10811094
} // namespace lld::coff

lld/COFF/Chunks.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,17 @@ class ECCodeMapChunk : public NonSectionChunk {
749749
std::vector<ECCodeMapEntry> &map;
750750
};
751751

752+
class CHPERedirectionChunk : public NonSectionChunk {
753+
public:
754+
CHPERedirectionChunk(std::vector<std::pair<Chunk *, Defined *>> &exportThunks)
755+
: exportThunks(exportThunks) {}
756+
size_t getSize() const override;
757+
void writeTo(uint8_t *buf) const override;
758+
759+
private:
760+
std::vector<std::pair<Chunk *, Defined *>> &exportThunks;
761+
};
762+
752763
static const uint8_t ECExportThunkCode[] = {
753764
0x48, 0x8b, 0xc4, // movq %rsp, %rax
754765
0x48, 0x89, 0x58, 0x20, // movq %rbx, 0x20(%rax)

lld/COFF/Driver.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,6 +2440,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
24402440
if (isArm64EC(config->machine)) {
24412441
ctx.symtab.addAbsolute("__arm64x_extra_rfe_table", 0);
24422442
ctx.symtab.addAbsolute("__arm64x_extra_rfe_table_size", 0);
2443+
ctx.symtab.addAbsolute("__arm64x_redirection_metadata", 0);
2444+
ctx.symtab.addAbsolute("__arm64x_redirection_metadata_count", 0);
24432445
ctx.symtab.addAbsolute("__hybrid_code_map", 0);
24442446
ctx.symtab.addAbsolute("__hybrid_code_map_count", 0);
24452447
}

lld/COFF/Writer.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,9 @@ class Writer {
298298
CVDebugRecordChunk *buildId = nullptr;
299299
ArrayRef<uint8_t> sectionTable;
300300

301+
// List of Arm64EC export thunks.
302+
std::vector<std::pair<Chunk *, Defined *>> exportThunks;
303+
301304
uint64_t fileSize;
302305
uint32_t pointerToSymbolTable = 0;
303306
uint64_t sizeOfImage;
@@ -312,6 +315,7 @@ class Writer {
312315
OutputSection *idataSec;
313316
OutputSection *edataSec;
314317
OutputSection *didatSec;
318+
OutputSection *a64xrmSec;
315319
OutputSection *rsrcSec;
316320
OutputSection *relocSec;
317321
OutputSection *ctorsSec;
@@ -995,6 +999,8 @@ void Writer::createSections() {
995999
idataSec = createSection(".idata", data | r);
9961000
edataSec = createSection(".edata", data | r);
9971001
didatSec = createSection(".didat", data | r);
1002+
if (isArm64EC(ctx.config.machine))
1003+
a64xrmSec = createSection(".a64xrm", data | r);
9981004
rsrcSec = createSection(".rsrc", data | r);
9991005
relocSec = createSection(".reloc", data | discardable | r);
10001006
ctorsSec = createSection(".ctors", data | r | w);
@@ -2053,15 +2059,24 @@ void Writer::createECChunks() {
20532059
auto sym = dyn_cast<Defined>(s);
20542060
if (!sym || !sym->getChunk())
20552061
continue;
2056-
if (auto thunk = dyn_cast<ECExportThunkChunk>(sym->getChunk()))
2062+
if (auto thunk = dyn_cast<ECExportThunkChunk>(sym->getChunk())) {
20572063
hexpthkSec->addChunk(thunk);
2064+
exportThunks.push_back({thunk, thunk->target});
2065+
}
20582066
}
20592067

20602068
auto codeMapChunk = make<ECCodeMapChunk>(codeMap);
20612069
rdataSec->addChunk(codeMapChunk);
20622070
Symbol *codeMapSym = ctx.symtab.findUnderscore("__hybrid_code_map");
20632071
replaceSymbol<DefinedSynthetic>(codeMapSym, codeMapSym->getName(),
20642072
codeMapChunk);
2073+
2074+
CHPERedirectionChunk *entryPoints = make<CHPERedirectionChunk>(exportThunks);
2075+
a64xrmSec->addChunk(entryPoints);
2076+
Symbol *entryPointsSym =
2077+
ctx.symtab.findUnderscore("__arm64x_redirection_metadata");
2078+
replaceSymbol<DefinedSynthetic>(entryPointsSym, entryPointsSym->getName(),
2079+
entryPoints);
20652080
}
20662081

20672082
// MinGW specific. Gather all relocations that are imported from a DLL even
@@ -2154,6 +2169,11 @@ void Writer::setECSymbols() {
21542169
if (!isArm64EC(ctx.config.machine))
21552170
return;
21562171

2172+
llvm::stable_sort(exportThunks, [](const std::pair<Chunk *, Defined *> &a,
2173+
const std::pair<Chunk *, Defined *> &b) {
2174+
return a.first->getRVA() < b.first->getRVA();
2175+
});
2176+
21572177
Symbol *rfeTableSym = ctx.symtab.findUnderscore("__arm64x_extra_rfe_table");
21582178
replaceSymbol<DefinedSynthetic>(rfeTableSym, "__arm64x_extra_rfe_table",
21592179
pdata.first);
@@ -2165,6 +2185,10 @@ void Writer::setECSymbols() {
21652185
->setVA(pdata.last->getRVA() + pdata.last->getSize() -
21662186
pdata.first->getRVA());
21672187
}
2188+
2189+
Symbol *entryPointCountSym =
2190+
ctx.symtab.findUnderscore("__arm64x_redirection_metadata_count");
2191+
cast<DefinedAbsolute>(entryPointCountSym)->setVA(exportThunks.size());
21682192
}
21692193

21702194
// Write section contents to a mmap'ed file.

lld/test/COFF/Inputs/loadconfig-arm64ec.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ __chpe_metadata:
6767
.rva __hybrid_code_map
6868
.word __hybrid_code_map_count
6969
.word 0 // __x64_code_ranges_to_entry_points
70-
.word 0 //__arm64x_redirection_metadata
70+
.rva __arm64x_redirection_metadata
7171
.rva __os_arm64x_dispatch_call_no_redirect
7272
.rva __os_arm64x_dispatch_ret
7373
.rva __os_arm64x_check_call
@@ -76,7 +76,7 @@ __chpe_metadata:
7676
.word 0 // __arm64x_native_entrypoint
7777
.word 0 // __hybrid_auxiliary_iat
7878
.word 0 // __x64_code_ranges_to_entry_points_count
79-
.word 0 // __arm64x_redirection_metadata_count
79+
.word __arm64x_redirection_metadata_count
8080
.rva __os_arm64x_get_x64_information
8181
.rva __os_arm64x_set_x64_information
8282
.rva __arm64x_extra_rfe_table

lld/test/COFF/arm64ec-export-thunks.test

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ EXP-DISASM-NEXT: 18000301f: cc int3
4949
RUN: llvm-objdump -p exports.dll | FileCheck -check-prefix=EXP-EXPORT %s
5050
EXP-EXPORT: Ordinal RVA Name
5151
EXP-EXPORT-NEXT: 1 0x3010 arm64ec_func
52-
EXP-EXPORT-NEXT: 2 0x6000 data_sym
52+
EXP-EXPORT-NEXT: 2 0x7000 data_sym
5353
EXP-EXPORT-NEXT: 3 0x3000 func
5454
EXP-EXPORT-NEXT: 4 0x2000 x86_64_func
5555

@@ -58,9 +58,30 @@ EXP-CHPE: CodeMap [
5858
EXP-CHPE-NEXT: 0x1000 - 0x100C ARM64EC
5959
EXP-CHPE-NEXT: 0x2000 - 0x3020 X64
6060
EXP-CHPE-NEXT: ]
61+
EXP-CHPE-NEXT: CodeRangesToEntryPoints: 0
62+
EXP-CHPE-NEXT: RedirectionMetadata [
63+
EXP-CHPE-NEXT: 0x3000 -> 0x1000
64+
EXP-CHPE-NEXT: 0x3010 -> 0x1000
65+
EXP-CHPE-NEXT: ]
66+
67+
RUN: llvm-readobj --sections exports.dll | FileCheck --check-prefix=A64XRM %s
68+
69+
A64XRM: Name: .a64xrm (2E 61 36 34 78 72 6D 00)
70+
A64XRM-NEXT: VirtualSize: 0x10
71+
A64XRM-NEXT: VirtualAddress: 0x6000
72+
A64XRM-NEXT: RawDataSize: 512
73+
A64XRM-NEXT: PointerToRawData:
74+
A64XRM-NEXT: PointerToRelocations: 0x0
75+
A64XRM-NEXT: PointerToLineNumbers: 0x0
76+
A64XRM-NEXT: RelocationCount: 0
77+
A64XRM-NEXT: LineNumberCount: 0
78+
A64XRM-NEXT: Characteristics [ (0x40000040)
79+
A64XRM-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
80+
A64XRM-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
81+
A64XRM-NEXT: ]
6182

6283
RUN: llvm-objdump -s --section=.test exports.dll | FileCheck --check-prefix=EXP-DATA %s
63-
EXP-DATA: 180006000 00300000 10300000
84+
EXP-DATA: 180007000 00300000 10300000
6485

6586
RUN: lld-link -out:exports2.dll -machine:arm64ec antidep-func.obj x86_64-func.obj loadconfig-arm64ec.obj \
6687
RUN: arm64ec-data.obj -dll -noentry -export:arm64ec_func -export:func=arm64ec_func \
@@ -100,6 +121,10 @@ ENTRY-CHPE: CodeMap [
100121
ENTRY-CHPE-NEXT: 0x1000 - 0x100C ARM64EC
101122
ENTRY-CHPE-NEXT: 0x2000 - 0x2010 X64
102123
ENTRY-CHPE-NEXT: ]
124+
ENTRY-CHPE-NEXT: CodeRangesToEntryPoints: 0
125+
ENTRY-CHPE-NEXT: RedirectionMetadata [
126+
ENTRY-CHPE-NEXT: 0x2000 -> 0x1000
127+
ENTRY-CHPE-NEXT: ]
103128

104129

105130
Test exporting data symbol as a function:

lld/test/COFF/arm64ec-patchable-thunks.test

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,17 @@ PATCH-DISASM-NEXT: 18000200e: cc int3
2727
PATCH-DISASM-NEXT: 18000200f: cc int3
2828

2929
RUN: llvm-readobj --hex-dump=.test test.dll | FileCheck -check-prefix=RVA %s
30-
RVA: 0x180005000 00200000
30+
RVA: 0x180006000 00200000
3131

3232
RUN: llvm-readobj --coff-load-config test.dll | FileCheck -check-prefix=PATCH-CHPE %s
3333
PATCH-CHPE: CodeMap [
3434
PATCH-CHPE-NEXT: 0x1000 - 0x1008 ARM64EC
3535
PATCH-CHPE-NEXT: 0x2000 - 0x2010 X64
3636
PATCH-CHPE-NEXT: ]
37+
PATCH-CHPE-NEXT: CodeRangesToEntryPoints: 0
38+
PATCH-CHPE-NEXT: RedirectionMetadata [
39+
PATCH-CHPE-NEXT: 0x2000 -> 0x1000
40+
PATCH-CHPE-NEXT: ]
3741

3842

3943
RUN: lld-link -out:test2.dll -machine:arm64ec arm64ec-alias.obj test-sec.obj loadconfig-arm64ec.obj -dll -noentry

0 commit comments

Comments
 (0)