-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[LLD][COFF] Support marking sections as x86_64 code in ARM64EC object files #135280
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
Conversation
… files 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.
|
@llvm/pr-subscribers-platform-windows @llvm/pr-subscribers-lld-coff Author: Jacek Caban (cjacek) ChangesOn ARM64EC, the Full diff: https://github.com/llvm/llvm-project/pull/135280.diff 3 Files Affected:
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 3494d1ba0ac02..9d376d0dea96f 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 9f68d5a325cc5..d03a64cc6b812 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -253,8 +253,7 @@ class SectionChunk : public Chunk {
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 0000000000000..70a5fedd9f5ca
--- /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
|
|
@llvm/pr-subscribers-lld Author: Jacek Caban (cjacek) ChangesOn ARM64EC, the Full diff: https://github.com/llvm/llvm-project/pull/135280.diff 3 Files Affected:
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 3494d1ba0ac02..9d376d0dea96f 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 9f68d5a325cc5..d03a64cc6b812 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -253,8 +253,7 @@ class SectionChunk : public Chunk {
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 0000000000000..70a5fedd9f5ca
--- /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
|
|
I first noticed this feature in .exp files generated by the MSVC linker when building DLLs. It appears to be useful for embedding simple x86_64 assembly code without needing to create standalone x86_64 object files. I'm considering using it for In any case, that part seems worth having in LLD for completeness. |
mstorsjo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. This is quite a tricky concept, especially wrt relocations being interpreted according to another standard. (Although that's only an issue with the yaml representation.) The implementation looks good!
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/18/builds/14354 Here is the relevant piece of the build log for the reference |
On ARM64EC, the
IMAGE_SCN_GPRELflag 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.