diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index f2d0111a19558..115e3457db697 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -1166,6 +1166,10 @@ uint32_t ImportThunkChunkARM64EC::extendRanges() { return sizeof(arm64Thunk) - sizeof(uint32_t); } +uint64_t Arm64XRelocVal::get() const { + return (sym ? sym->getRVA() : 0) + value; +} + size_t Arm64XDynamicRelocEntry::getSize() const { switch (type) { case IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE: @@ -1186,13 +1190,13 @@ void Arm64XDynamicRelocEntry::writeTo(uint8_t *buf) const { *out |= ((bit_width(size) - 1) << 14); // Encode the size. switch (size) { case 2: - out[1] = value; + out[1] = value.get(); break; case 4: - *reinterpret_cast(out + 1) = value; + *reinterpret_cast(out + 1) = value.get(); break; case 8: - *reinterpret_cast(out + 1) = value; + *reinterpret_cast(out + 1) = value.get(); break; default: llvm_unreachable("invalid size"); diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index 0d2b2ac0f15ea..46fd8e21dce65 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -835,18 +835,30 @@ class ECExportThunkChunk : public NonSectionCodeChunk { Defined *target; }; +// ARM64X relocation value, potentially relative to a symbol. +class Arm64XRelocVal { +public: + Arm64XRelocVal(uint64_t value = 0) : value(value) {} + Arm64XRelocVal(Defined *sym, int32_t offset = 0) : sym(sym), value(offset) {} + uint64_t get() const; + +private: + Defined *sym = nullptr; + uint64_t value; +}; + // ARM64X entry for dynamic relocations. class Arm64XDynamicRelocEntry { public: Arm64XDynamicRelocEntry(llvm::COFF::Arm64XFixupType type, uint8_t size, - uint32_t offset, uint64_t value) + uint32_t offset, Arm64XRelocVal value) : offset(offset), value(value), type(type), size(size) {} size_t getSize() const; void writeTo(uint8_t *buf) const; uint32_t offset; - uint64_t value; + Arm64XRelocVal value; private: llvm::COFF::Arm64XFixupType type; @@ -862,7 +874,7 @@ class DynamicRelocsChunk : public NonSectionChunk { void finalize(); void add(llvm::COFF::Arm64XFixupType type, uint8_t size, uint32_t offset, - uint64_t value) { + Arm64XRelocVal value) { arm64xRelocs.emplace_back(type, size, offset, value); } diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 138112f109fd4..eb82a9cc01593 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -2584,18 +2584,17 @@ void Writer::createDynamicRelocs() { coffHeaderOffset + offsetof(coff_file_header, Machine), AMD64); - // Clear the load config directory. - // FIXME: Use the hybrid load config value instead. + // Set the hybrid load config to the EC load config. ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t), dataDirOffset64 + LOAD_CONFIG_TABLE * sizeof(data_directory) + offsetof(data_directory, RelativeVirtualAddress), - 0); + ctx.hybridSymtab->loadConfigSym); ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t), dataDirOffset64 + LOAD_CONFIG_TABLE * sizeof(data_directory) + offsetof(data_directory, Size), - 0); + ctx.hybridSymtab->loadConfigSize); } PartialSection *Writer::createPartialSection(StringRef name, diff --git a/lld/test/COFF/arm64x-loadconfig.s b/lld/test/COFF/arm64x-loadconfig.s index 3b53d32a9b549..f413adff2868c 100644 --- a/lld/test/COFF/arm64x-loadconfig.s +++ b/lld/test/COFF/arm64x-loadconfig.s @@ -99,20 +99,49 @@ // LOADCFG-NEXT: RVA: 0x150 // LOADCFG-NEXT: Type: VALUE // LOADCFG-NEXT: Size: 0x4 -// LOADCFG-NEXT: Value: 0x0 +// LOADCFG-NEXT: Value: 0x1140 // LOADCFG-NEXT: ] // LOADCFG-NEXT: Entry [ // LOADCFG-NEXT: RVA: 0x154 // LOADCFG-NEXT: Type: VALUE // LOADCFG-NEXT: Size: 0x4 -// LOADCFG-NEXT: Value: 0x0 +// LOADCFG-NEXT: Value: 0x140 // LOADCFG-NEXT: ] // LOADCFG-NEXT: ] // LOADCFG-NEXT: ] // LOADCFG-NEXT: HybridObject { -// LOADCFG-NEXT: Format: COFF-x86-64 -// LOADCFG-NEXT: Arch: x86_64 +// LOADCFG-NEXT: Format: COFF-ARM64EC +// LOADCFG-NEXT: Arch: aarch64 // LOADCFG-NEXT: AddressSize: 64bit +// LOADCFG-NEXT: LoadConfig [ +// LOADCFG-NEXT: Size: 0x140 +// LOADCFG: CHPEMetadata [ +// LOADCFG-NEXT: Version: 0x2 +// LOADCFG: ] +// LOADCFG-NEXT: DynamicRelocations [ +// LOADCFG-NEXT: Version: 0x1 +// LOADCFG-NEXT: Arm64X [ +// LOADCFG-NEXT: Entry [ +// LOADCFG-NEXT: RVA: 0x7C +// LOADCFG-NEXT: Type: VALUE +// LOADCFG-NEXT: Size: 0x2 +// LOADCFG-NEXT: Value: 0x8664 +// LOADCFG-NEXT: ] +// LOADCFG-NEXT: Entry [ +// LOADCFG-NEXT: RVA: 0x150 +// LOADCFG-NEXT: Type: VALUE +// LOADCFG-NEXT: Size: 0x4 +// LOADCFG-NEXT: Value: 0x1140 +// LOADCFG-NEXT: ] +// LOADCFG-NEXT: Entry [ +// LOADCFG-NEXT: RVA: 0x154 +// LOADCFG-NEXT: Type: VALUE +// LOADCFG-NEXT: Size: 0x4 +// LOADCFG-NEXT: Value: 0x140 +// LOADCFG-NEXT: ] +// LOADCFG-NEXT: ] +// LOADCFG-NEXT: ] +// LOADCFG-NEXT: } // RUN: llvm-readobj --coff-basereloc out-hyb.dll | FileCheck --check-prefix=BASERELOC %s // BASERELOC: BaseReloc [