https://github.com/llvmbot created 
https://github.com/llvm/llvm-project/pull/210382

Backport 30f270edb42c5d37e4c4a413ebfc7a6513565b30

Requested by: @cjacek

>From 574be692b665717f165d86803f9f9abc9ab5190b Mon Sep 17 00:00:00 2001
From: Jacek Caban <[email protected]>
Date: Fri, 17 Jul 2026 17:30:31 +0200
Subject: [PATCH] [LLD] [COFF] Fix linking directly against an ARM64X DLL
 without import library (#210311)

In mingw mode, when linking against a DLL, the user can either provide a
regular import library, or provide the actual DLL. When linking against
an ARM64X image, add both native and EC views to the symbol table on EC
targets. Also getMachine() on such images returns ARM64X, treat it as
ARM64 instead.

(cherry picked from commit 30f270edb42c5d37e4c4a413ebfc7a6513565b30)
---
 lld/COFF/Driver.cpp             | 16 ++++++-
 lld/COFF/InputFiles.cpp         | 18 ++------
 lld/COFF/InputFiles.h           |  6 ++-
 lld/test/COFF/link-dll-arm64x.s | 81 +++++++++++++++++++++++++++++++++
 4 files changed, 103 insertions(+), 18 deletions(-)
 create mode 100644 lld/test/COFF/link-dll-arm64x.s

diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index dc4903a5fe126..1b09b0c03abb5 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -356,7 +356,21 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> 
mb,
     break;
   case file_magic::pecoff_executable:
     if (ctx.config.mingw) {
-      addFile(make<DLLFile>(ctx.symtab, mbref));
+      std::unique_ptr<COFFObjectFile> obj =
+          ObjFile::createCOFFObject(ctx, mbref);
+      if (ctx.symtab.isEC()) {
+        // When importing an ARM64X image, add both the native and EC views.
+        if (std::unique_ptr<MemoryBuffer> hybridView =
+                obj->getHybridObjectView()) {
+          std::unique_ptr<COFFObjectFile> hybridObj =
+              ObjFile::createCOFFObject(ctx, 
takeBuffer(std::move(hybridView)));
+          addFile(make<DLLFile>(ctx.symtab, hybridObj));
+          addFile(make<DLLFile>(*ctx.hybridSymtab, obj));
+          break;
+        }
+      }
+      auto machine = static_cast<MachineTypes>(obj->getMachine());
+      addFile(make<DLLFile>(ctx.getSymtab(machine), obj));
       break;
     }
     if (filename.ends_with_insensitive(".dll")) {
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 757a0f7be9b36..fd4858581ed54 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -1506,17 +1506,6 @@ static bool isRVACode(COFFObjectFile *coffObj, uint64_t 
rva, InputFile *file) {
 }
 
 void DLLFile::parse() {
-  // Parse a memory buffer as a PE-COFF executable.
-  std::unique_ptr<Binary> bin = CHECK(createBinary(mb), this);
-
-  if (auto *obj = dyn_cast<COFFObjectFile>(bin.get())) {
-    bin.release();
-    coffObj.reset(obj);
-  } else {
-    Err(symtab.ctx) << toString(this) << " is not a COFF file";
-    return;
-  }
-
   if (!coffObj->getPE32Header() && !coffObj->getPE32PlusHeader()) {
     Err(symtab.ctx) << toString(this) << " is not a PE-COFF executable";
     return;
@@ -1564,9 +1553,8 @@ void DLLFile::parse() {
 }
 
 MachineTypes DLLFile::getMachineType() const {
-  if (coffObj)
-    return static_cast<MachineTypes>(coffObj->getMachine());
-  return IMAGE_FILE_MACHINE_UNKNOWN;
+  auto machine = static_cast<MachineTypes>(coffObj->getMachine());
+  return machine == ARM64X ? ARM64 : machine;
 }
 
 void DLLFile::makeImport(DLLFile::Symbol *s) {
@@ -1581,7 +1569,7 @@ void DLLFile::makeImport(DLLFile::Symbol *s) {
   auto *imp = reinterpret_cast<coff_import_header *>(p);
   p += sizeof(*imp);
   imp->Sig2 = 0xFFFF;
-  imp->Machine = coffObj->getMachine();
+  imp->Machine = static_cast<uint16_t>(getMachineType());
   imp->SizeOfData = impSize;
   imp->OrdinalHint = 0; // Only linking by name
   imp->TypeInfo = (s->nameType << 2) | s->importType;
diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h
index b8a2acf6e1b41..3d92de8492940 100644
--- a/lld/COFF/InputFiles.h
+++ b/lld/COFF/InputFiles.h
@@ -424,8 +424,10 @@ class BitcodeFile : public InputFile {
 // .dll file. MinGW only.
 class DLLFile : public InputFile {
 public:
-  explicit DLLFile(SymbolTable &symtab, MemoryBufferRef m)
-      : InputFile(symtab, DLLKind, m) {}
+  explicit DLLFile(SymbolTable &symtab, std::unique_ptr<COFFObjectFile> &obj)
+      : InputFile(symtab, DLLKind, obj->getMemoryBufferRef()) {
+    coffObj.swap(obj);
+  }
   static bool classof(const InputFile *f) { return f->kind() == DLLKind; }
   void parse() override;
   MachineTypes getMachineType() const override;
diff --git a/lld/test/COFF/link-dll-arm64x.s b/lld/test/COFF/link-dll-arm64x.s
new file mode 100644
index 0000000000000..b97a61aa3f5be
--- /dev/null
+++ b/lld/test/COFF/link-dll-arm64x.s
@@ -0,0 +1,81 @@
+REQUIRES: aarch64, x86
+RUN: split-file %s %t.dir && cd %t.dir
+
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows sym-ec.s -o sym-ec.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows ref-ec.s -o ref-ec.obj
+RUN: llvm-mc -filetype=obj -triple=aarch64-windows sym-native.s -o 
sym-native.obj
+RUN: llvm-mc -filetype=obj -triple=aarch64-windows ref-native.s -o 
ref-native.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows 
%S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
+RUN: llvm-mc -filetype=obj -triple=aarch64-windows 
%S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj
+
+RUN: lld-link -machine:arm64x -dll -noentry -out:import.dll sym-ec.obj 
sym-native.obj loadconfig-arm64ec.obj loadconfig-arm64.obj
+
+RUN: lld-link -machine:arm64 -dll -noentry -out:out-arm64.dll ref-native.obj 
import.dll \
+RUN:          -lldmingw -exclude-all-symbols -auto-import:no
+
+RUN: llvm-readobj --coff-imports out-arm64.dll | FileCheck 
--check-prefix=NATIVE %s
+NATIVE:      Import {
+NATIVE-NEXT:   Name: import.dll
+NATIVE-NEXT:   ImportLookupTableRVA:
+NATIVE-NEXT:   ImportAddressTableRVA:
+NATIVE-NEXT:   Symbol: native_data (0)
+NATIVE-NEXT: }
+
+RUN: lld-link -machine:arm64ec -dll -noentry -out:out-arm64ec.dll ref-ec.obj 
import.dll \
+RUN:          loadconfig-arm64ec.obj -lldmingw -exclude-all-symbols 
-auto-import:no
+
+RUN: llvm-readobj --coff-imports out-arm64ec.dll | FileCheck --check-prefix=EC 
%s
+EC:      Import {
+EC-NEXT:   Name: import.dll
+EC-NEXT:   ImportLookupTableRVA:
+EC-NEXT:   ImportAddressTableRVA:
+EC-NEXT:   Symbol: ec_data (0)
+EC-NEXT: }
+
+RUN: lld-link -machine:arm64x -dll -noentry -out:out-arm64x.dll ref-ec.obj 
ref-native.obj import.dll \
+RUN:          loadconfig-arm64ec.obj loadconfig-arm64.obj -lldmingw 
-exclude-all-symbols -auto-import:no
+
+RUN: llvm-readobj --coff-imports out-arm64x.dll | FileCheck 
--check-prefix=ARM64X %s
+ARM64X:      Import {
+ARM64X-NEXT:   Name: import.dll
+ARM64X-NEXT:   ImportLookupTableRVA:
+ARM64X-NEXT:   ImportAddressTableRVA:
+ARM64X-NEXT:   Symbol: native_data (0)
+ARM64X-NEXT: }
+ARM64X-NEXT: HybridObject {
+ARM64X-NEXT:   Format: COFF-ARM64EC
+ARM64X-NEXT:   Arch: aarch64
+ARM64X-NEXT:   AddressSize: 64bit
+ARM64X-NEXT:   Import {
+ARM64X-NEXT:     Name: import.dll
+ARM64X-NEXT:     ImportLookupTableRVA:
+ARM64X-NEXT:     ImportAddressTableRVA:
+ARM64X-NEXT:     Symbol: ec_data (0)
+ARM64X-NEXT:   }
+ARM64X-NEXT: }
+
+#--- sym-ec.s
+    .data
+    .globl ec_data
+ec_data:
+    .word 0
+
+    .section .drectve, "yn"
+    .ascii " -export:ec_data"
+
+#--- sym-native.s
+    .data
+    .globl native_data
+native_data:
+    .word 0
+
+    .section .drectve, "yn"
+    .ascii " -export:native_data"
+
+#--- ref-ec.s
+    .data
+    .rva __imp_ec_data
+
+#--- ref-native.s
+    .data
+    .rva __imp_native_data

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to