[lld] [LLD][COFF] Emit base relocation for native CHPE metadata pointer on ARM64X (PR #121500)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Sun Jan 5 07:03:07 PST 2025
================
@@ -2594,6 +2594,38 @@ void Writer::createDynamicRelocs() {
LOAD_CONFIG_TABLE * sizeof(data_directory) +
offsetof(data_directory, Size),
0);
+
+ // Insert a 64-bit relocation for CHPEMetadataPointer. Its value will be set
+ // later in prepareLoadConfig to match the value in the EC load config.
+ // However, a base relocation must be allocated in advance, so we handle it
+ // here.
+ if (ctx.symtab.loadConfigSym && ctx.hybridSymtab->loadConfigSym &&
+ ctx.symtab.loadConfigSize >=
+ offsetof(coff_load_configuration64, CHPEMetadataPointer) +
+ sizeof(coff_load_configuration64::CHPEMetadataPointer)) {
+ DefinedRegular *sym = ctx.symtab.loadConfigSym;
+ SectionChunk *chunk = sym->getChunk();
+ ArrayRef<coff_relocation> curRelocs = chunk->getRelocs();
+ MutableArrayRef<coff_relocation> newRelocs(
+ bAlloc().Allocate<coff_relocation>(curRelocs.size() + 1),
+ curRelocs.size() + 1);
+ size_t chpeOffset = sym->getValue() + offsetof(coff_load_configuration64,
+ CHPEMetadataPointer);
+ size_t i;
+ for (i = 0;
+ i < curRelocs.size() && curRelocs[i].VirtualAddress < chpeOffset; ++i)
+ newRelocs[i] = curRelocs[i];
+ newRelocs[i].VirtualAddress = chpeOffset;
+ // The specific symbol used here is irrelevant as long as it's valid, since
+ // it will be overridden by prepareLoadConfig. Use the load config symbol
+ // itself.
+ newRelocs[i].SymbolTableIndex =
----------------
cjacek wrote:
The approach was kept localized since this is the only known case requiring the addition of extra base relocation to a section chunk, and the associated reallocation overhead seemed acceptable to me. While a similar relocation rewrite mechanism exists for range extension thunks and I used it as a reference, the differences were substantial enough that there was not much to share.
I revised the MR with a simpler solution and plan to extract the first commit into a standalone PR, as it appears independently valid. This change represents more of a special case than an abstraction. Section chunks were left unmodified due to their sensitivity to memory usage, and addressing the issue at the `OutputSection` level proved impractical because those assignments occur too late in the process.
For context, hybrid ARM64X uses two load configs but a single CHPE metadata structure. The metadata resides in the EC namespace, where the CRT initializes the EC load config’s CHPE metadata pointer as a relocatable value, while the native load config's pointer remains unset. The linker has three tasks related to CHPE metadata:
1. Copying the pointer value from the EC load config to the native one (as implemented by #120328 in lld-link).
2. Emitting a base relocation for the updated native load config (which MSVC linker always does, even when the EC load config lacks a similar relocation).
3. Emitting an ARM64X relocation for the hybrid entry point in the CHPE metadata. Here, the MSVC linker references the `__chpe_metadata` symbol.
The logic for tasks 1 and 3 differs, although they could theoretically rely on the same approach to identify the CHPE metadata. However, aligning with MSVC's behavior was straightforward and ensures compatibility.
Additionally, entire load configurations in the PE header are modified using ARM64X relocations, as addressed by #121337.
Thanks for the review.
https://github.com/llvm/llvm-project/pull/121500
More information about the llvm-commits
mailing list