diff options
author | Jacek Caban <jacek@codeweavers.com> | 2025-04-11 16:13:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-11 16:13:46 +0200 |
commit | f8f01b5eeb61999e6bb9e8c52435f8ff08d410e7 (patch) | |
tree | 7371d89f4fb9f02d88784588ac9d133b19675065 | |
parent | cd85f5dbdf135347a9912dde148ec9fd325ba8c1 (diff) | |
download | llvm-f8f01b5eeb61999e6bb9e8c52435f8ff08d410e7.zip llvm-f8f01b5eeb61999e6bb9e8c52435f8ff08d410e7.tar.gz llvm-f8f01b5eeb61999e6bb9e8c52435f8ff08d410e7.tar.bz2 |
[LLD][COFF] Support marking sections as x86_64 code in ARM64EC object files (#135280)
On ARM64EC, the `IMAGE_SCN_GPREL` flag is repurposed to indicate that
section code is x86_64. This enables embedding x86_64 code within
ARM64EC object files. MSVC uses this for export thunks in .exp files.
-rw-r--r-- | lld/COFF/Chunks.cpp | 10 | ||||
-rw-r--r-- | lld/COFF/Chunks.h | 3 | ||||
-rw-r--r-- | lld/test/COFF/arm64ec-x86-sec.yaml | 43 |
3 files changed, 54 insertions, 2 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 3920158..ff2bc40 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -61,6 +61,16 @@ SectionChunk::SectionChunk(ObjFile *f, const coff_section *h, Kind k) live = true; } +MachineTypes SectionChunk::getMachine() const { + MachineTypes machine = file->getMachineType(); + // On ARM64EC, the IMAGE_SCN_GPREL flag is repurposed to indicate that section + // code is x86_64. This enables embedding x86_64 code within ARM64EC object + // files. MSVC uses this for export thunks in .exp files. + if (isArm64EC(machine) && (header->Characteristics & IMAGE_SCN_GPREL)) + machine = AMD64; + return machine; +} + // SectionChunk is one of the most frequently allocated classes, so it is // important to keep it as compact as possible. As of this writing, the number // below is the size of this class on x64 platforms. diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index 9f68d5a..d03a64c 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -253,8 +253,7 @@ public: size_t getSize() const { return header->SizeOfRawData; } ArrayRef<uint8_t> getContents() const; void writeTo(uint8_t *buf) const; - - MachineTypes getMachine() const { return file->getMachineType(); } + MachineTypes getMachine() const; // Defend against unsorted relocations. This may be overly conservative. void sortRelocations(); diff --git a/lld/test/COFF/arm64ec-x86-sec.yaml b/lld/test/COFF/arm64ec-x86-sec.yaml new file mode 100644 index 0000000..70a5fed --- /dev/null +++ b/lld/test/COFF/arm64ec-x86-sec.yaml @@ -0,0 +1,43 @@ +# REQUIRES: aarch64, x86 + +# RUN: yaml2obj %s -o %t.obj +# RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o %t-loadcfg.obj +# RUN: lld-link -machine:arm64ec -dll -noentry %t.obj %t-loadcfg.obj -out:%t.dll +# RUN: llvm-objdump -d %t.dll | FileCheck %s + +# CHECK: Disassembly of section .text: +# CHECK-EMPTY: +# CHECK-NEXT: 0000000180001000 <.text>: +# CHECK-NEXT: 180001000: d503201f nop +# CHECK-NEXT: 180001004: d65f03c0 ret +# CHECK-NEXT: ... +# CHECK-NEXT: 180002000: e9 ff ef ff ff jmp 0x180001004 <.text+0x4> +# CHECK-NEXT: 180002005: c3 retq +# CHECK-NEXT: 180002006: cc int3 + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_ARM64EC + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 1F2003D5C0035FD6 + SizeOfRawData: 8 + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_GPREL, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: E900000000C3CC + SizeOfRawData: 7 + Relocations: + - VirtualAddress: 1 + SymbolName: func + Type: IMAGE_REL_ARM64_PAGEBASE_REL21 # interpreted as IMAGE_REL_AMD64_REL32 +symbols: + - Name: func + Value: 4 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL |