Skip to content

[LLD][COFF] Emit ARM64X relocations for CHPE ExtraRFETable entries #126713

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

Merged
merged 1 commit into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 40 additions & 9 deletions lld/COFF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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);
}
}
}
}

Expand Down Expand Up @@ -2666,21 +2680,26 @@ 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 +
offsetof(pe32plus_header, AddressOfEntryPoint),
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) {
Expand All @@ -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.
Expand Down
14 changes: 11 additions & 3 deletions lld/test/COFF/pdata-arm64ec.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down