diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index ff3c89884c24d..11e7cf4346b23 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -1167,7 +1167,7 @@ uint32_t ImportThunkChunkARM64EC::extendRanges() { } uint64_t Arm64XRelocVal::get() const { - return (sym ? sym->getRVA() : 0) + value; + return (sym ? sym->getRVA() : 0) + (chunk ? chunk->getRVA() : 0) + value; } size_t Arm64XDynamicRelocEntry::getSize() const { @@ -1230,6 +1230,17 @@ void DynamicRelocsChunk::finalize() { size = alignTo(size, sizeof(uint32_t)); } +// Set the reloc value. The reloc entry must be allocated beforehand. +void DynamicRelocsChunk::set(uint32_t rva, Arm64XRelocVal value) { + auto entry = + llvm::find_if(arm64xRelocs, [rva](const Arm64XDynamicRelocEntry &e) { + return e.offset.get() == rva; + }); + assert(entry != arm64xRelocs.end()); + assert(!entry->value.get()); + entry->value = value; +} + void DynamicRelocsChunk::writeTo(uint8_t *buf) const { auto table = reinterpret_cast(buf); table->Version = 1; diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index 7ba58e336451f..d6216efdd90bd 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -840,10 +840,13 @@ class Arm64XRelocVal { public: Arm64XRelocVal(uint64_t value = 0) : value(value) {} Arm64XRelocVal(Defined *sym, int32_t offset = 0) : sym(sym), value(offset) {} + Arm64XRelocVal(Chunk *chunk, int32_t offset = 0) + : chunk(chunk), value(offset) {} uint64_t get() const; private: Defined *sym = nullptr; + Chunk *chunk = nullptr; uint64_t value; }; @@ -874,10 +877,12 @@ class DynamicRelocsChunk : public NonSectionChunk { void finalize(); void add(llvm::COFF::Arm64XFixupType type, uint8_t size, - Arm64XRelocVal offset, Arm64XRelocVal value) { + Arm64XRelocVal offset, Arm64XRelocVal value = Arm64XRelocVal()) { arm64xRelocs.emplace_back(type, size, offset, value); } + void set(uint32_t rva, Arm64XRelocVal value); + private: std::vector arm64xRelocs; size_t size; diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 3d95d219a493c..507621d1e95f8 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -2392,6 +2392,13 @@ void Writer::setECSymbols() { symtab->findUnderscore("__arm64x_native_entrypoint") ->replaceKeepingName(altEntrySym, sizeof(SymbolUnion)); } + + 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()); } } @@ -2644,6 +2651,19 @@ void Writer::createDynamicRelocs() { Warn(ctx) << "'__chpe_metadata' is missing for ARM64X target"; } + if (pdata.first != hybridPdata.first) { + ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t), + dataDirOffset64 + + EXCEPTION_TABLE * sizeof(data_directory) + + offsetof(data_directory, RelativeVirtualAddress), + hybridPdata.first); + // The Size value is assigned after addresses are finalized. + ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t), + dataDirOffset64 + + EXCEPTION_TABLE * sizeof(data_directory) + + offsetof(data_directory, Size)); + } + // Set the hybrid load config to the EC load config. ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t), dataDirOffset64 + diff --git a/lld/test/COFF/pdata-arm64ec.test b/lld/test/COFF/pdata-arm64ec.test index 7f20c460dc109..fbec797525f7f 100644 --- a/lld/test/COFF/pdata-arm64ec.test +++ b/lld/test/COFF/pdata-arm64ec.test @@ -6,6 +6,7 @@ Test handlign of hybrid .pdata section on ARM64EC target. RUN: llvm-mc -filetype=obj -triple=arm64-windows arm64-func-sym.s -o arm64-func-sym.obj RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-func-sym.s -o arm64ec-func-sym.obj RUN: llvm-mc -filetype=obj -triple=x86_64-windows x86_64-func-sym.s -o x86_64-func-sym.obj +RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %p/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj Only arm64ec code: @@ -55,11 +56,21 @@ DATA3: 180005000 00100000 11000001 00200000 0e200000 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-arm64ec.obj -dll -noentry +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 -DIR3: ExceptionTableRVA: 0x6000 -DIR3-NEXT: ExceptionTableSize: 0x10 +DIR3: ImageOptionalHeader { +DIR3: DataDirectory { +DIR3: ExceptionTableRVA: 0x6000 +DIR3-NEXT: ExceptionTableSize: 0x10 +DIR3: } +DIR3: } +DIR3: HybridObject { +DIR3: ImageOptionalHeader { +DIR3: ExceptionTableRVA: 0x6010 +DIR3-NEXT: ExceptionTableSize: 0xC +DIR3: } +DIR3: } RUN: llvm-objdump -s --section=.pdata test4.dll | FileCheck -check-prefix=DATA4 %s DATA4: 180006000 00100000 11000001 00200000 11000001 ......... ...... @@ -74,12 +85,12 @@ RUN: llvm-readobj --headers test5.dll | FileCheck -check-prefix=DIR2 %s RUN: llvm-objdump -s --section=.pdata test5.dll | FileCheck -check-prefix=DATA3 %s RUN: lld-link -out:test6.dll -machine:arm64x arm64ec-func-sym.obj x86_64-func-sym.obj \ -RUN: arm64-func-sym.obj loadconfig-arm64ec.obj -dll -noentry +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-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-arm64ec.obj -dll -noentry +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-objdump -s --section=.pdata test7.dll | FileCheck -check-prefix=DATA4 %s