[LLD][COFF] Emit ARM64X relocations for CHPE ExtraRFETable entries (#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.
This commit is contained in:
Jacek Caban 2025-02-13 19:22:57 +01:00 committed by GitHub
parent 7d9a12cec2
commit 8252e0ef82
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 51 additions and 12 deletions

View File

@ -343,6 +343,9 @@ private:
// 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.

View File

@ -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