[lld] [LLD][COFF] Require explicit specification of ARM64EC target (PR #116281)

Jacek Caban via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 15 14:57:05 PST 2024


https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/116281

>From ff9f52c00f1e01d1d9a317782d8a2c22a97232a9 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Thu, 14 Nov 2024 22:00:18 +0100
Subject: [PATCH 1/2] [LLD][COFF] Require explicit specification of ARM64EC
 target

Inferring the ARM64EC target can lead to errors. The `-machine:arm64ec` option may
include x86_64 input files, and any valid ARM64EC input is also valid for `-machine:arm64x`.
MSVC requires an explicit `-machine` argument with informative diagnostics; this patch
adopts the same behavior.
---
 lld/COFF/Config.h          |  1 +
 lld/COFF/SymbolTable.cpp   | 22 ++++++++++++++++++----
 lld/test/COFF/arm64ec.test | 23 ++++++++++++++++++++++-
 3 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 3d416e6985d02c..57cb443798cd8f 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -114,6 +114,7 @@ struct Configuration {
   bool is64() const { return llvm::COFF::is64Bit(machine); }
 
   llvm::COFF::MachineTypes machine = IMAGE_FILE_MACHINE_UNKNOWN;
+  bool machineInferred = false;
   size_t wordsize;
   bool verbose = false;
   WindowsSubsystem subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 35d54d4945f7f4..0e0773e94ba2c7 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -46,6 +46,8 @@ static bool compatibleMachineType(COFFLinkerContext &ctx, MachineTypes mt) {
     return COFF::isArm64EC(mt) || mt == AMD64;
   case ARM64X:
     return COFF::isAnyArm64(mt) || mt == AMD64;
+  case IMAGE_FILE_MACHINE_UNKNOWN:
+    return true;
   default:
     return ctx.config.machine == mt;
   }
@@ -74,14 +76,26 @@ void SymbolTable::addFile(InputFile *file) {
   }
 
   MachineTypes mt = file->getMachineType();
-  if (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN) {
-    ctx.config.machine = mt;
-    ctx.driver.addWinSysRootLibSearchPaths();
-  } else if (!compatibleMachineType(ctx, mt)) {
+  // The ARM64EC target must be explicitly specified and cannot be inferred.
+  if (mt == ARM64EC &&
+      (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN ||
+       (ctx.config.machineInferred && (COFF::isAnyArm64(ctx.config.machine) ||
+                                       ctx.config.machine == AMD64)))) {
+    error(toString(file) + ": machine type arm64ec is ambiguous and cannot be "
+                           "inferred, use /machine:arm64ec or /machine:arm64x");
+    return;
+  }
+  if (!compatibleMachineType(ctx, mt)) {
     error(toString(file) + ": machine type " + machineToStr(mt) +
           " conflicts with " + machineToStr(ctx.config.machine));
     return;
   }
+  if (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN &&
+      mt != IMAGE_FILE_MACHINE_UNKNOWN) {
+    ctx.config.machineInferred = true;
+    ctx.config.machine = mt == ARM64X ? ARM64 : mt;
+    ctx.driver.addWinSysRootLibSearchPaths();
+  }
 
   ctx.driver.parseDirectives(file);
 }
diff --git a/lld/test/COFF/arm64ec.test b/lld/test/COFF/arm64ec.test
index e50b14ce0184c8..0063cd8a0383e7 100644
--- a/lld/test/COFF/arm64ec.test
+++ b/lld/test/COFF/arm64ec.test
@@ -4,6 +4,7 @@ RUN: split-file %s %t.dir && cd %t.dir
 RUN: llvm-mc -filetype=obj -triple=aarch64-windows arm64-data-sym.s -o arm64-data-sym.obj
 RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-data-sym.s -o arm64ec-data-sym.obj
 RUN: llvm-mc -filetype=obj -triple=x86_64-windows x86_64-data-sym.s -o x86_64-data-sym.obj
+RUN: llvm-mc -filetype=obj -triple=i686-windows x86_64-data-sym.s -o i686-data-sym.obj
 RUN: llvm-cvtres -machine:arm64x -out:arm64x-resource.obj %S/Inputs/resource.res
 
 RUN: lld-link -out:test.dll -machine:arm64ec arm64ec-data-sym.obj -dll -noentry
@@ -36,7 +37,7 @@ ARM64X-DATA: 03030303 01010101 02020202
 
 RUN: not lld-link -out:test.dll -machine:arm64 arm64-data-sym.obj arm64ec-data-sym.obj \
 RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT1 %s
-INCOMPAT1: lld-link: error: arm64ec-data-sym.obj: machine type arm64ec conflicts with arm64
+INCOMPAT1: arm64ec-data-sym.obj: machine type arm64ec conflicts with arm64
 
 RUN: not lld-link -out:test.dll -machine:arm64ec arm64ec-data-sym.obj arm64-data-sym.obj \
 RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT2 %s
@@ -46,6 +47,26 @@ RUN: not lld-link -out:test.dll -machine:arm64 arm64-data-sym.obj x86_64-data-sy
 RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT3 %s
 INCOMPAT3: lld-link: error: x86_64-data-sym.obj: machine type x64 conflicts with arm64
 
+arm64ec machine type can't be inferred, it must be specified explicitly.
+RUN: not lld-link -out:test.dll arm64ec-data-sym.obj \
+RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s
+INCOMPAT4: lld-link: error: arm64ec-data-sym.obj: machine type arm64ec is ambiguous and cannot be inferred, use /machine:arm64ec or /machine:arm64x
+
+RUN: not lld-link -out:test.dll x86_64-data-sym.obj arm64ec-data-sym.obj \
+RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s
+
+RUN: not lld-link -out:test.dll aarch64-data-sym.obj arm64ec-data-sym.obj \
+RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s
+
+RUN: not lld-link -out:test.dll i686-data-sym.obj arm64ec-data-sym.obj \
+RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT5 %s
+INCOMPAT5: arm64ec-data-sym.obj: machine type arm64ec conflicts with x86
+
+arm64x input implies arm64 target
+RUN: lld-link -out:test.dll -machine:arm64 arm64x-resource.obj -dll -noentry
+RUN: llvm-readobj --file-headers test.dll | FileCheck -check-prefix=ARM64-HEADER %s
+ARM64-HEADER:      Machine: IMAGE_FILE_MACHINE_ARM64 (0xAA64)
+
 #--- arm64ec-data-sym.s
     .data
     .globl arm64ec_data_sym

>From 98ffbed66a733c940d3b2722fdfc7080172c94fd Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Fri, 15 Nov 2024 23:47:58 +0100
Subject: [PATCH 2/2] Better ARM64X handling and tests

---
 lld/COFF/SymbolTable.cpp   |  4 ++--
 lld/test/COFF/arm64ec.test | 14 +++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 0e0773e94ba2c7..5394a9c248cca7 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -79,7 +79,7 @@ void SymbolTable::addFile(InputFile *file) {
   // The ARM64EC target must be explicitly specified and cannot be inferred.
   if (mt == ARM64EC &&
       (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN ||
-       (ctx.config.machineInferred && (COFF::isAnyArm64(ctx.config.machine) ||
+       (ctx.config.machineInferred && (ctx.config.machine == ARM64 ||
                                        ctx.config.machine == AMD64)))) {
     error(toString(file) + ": machine type arm64ec is ambiguous and cannot be "
                            "inferred, use /machine:arm64ec or /machine:arm64x");
@@ -93,7 +93,7 @@ void SymbolTable::addFile(InputFile *file) {
   if (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN &&
       mt != IMAGE_FILE_MACHINE_UNKNOWN) {
     ctx.config.machineInferred = true;
-    ctx.config.machine = mt == ARM64X ? ARM64 : mt;
+    ctx.config.machine = mt;
     ctx.driver.addWinSysRootLibSearchPaths();
   }
 
diff --git a/lld/test/COFF/arm64ec.test b/lld/test/COFF/arm64ec.test
index 0063cd8a0383e7..75288e97e598dd 100644
--- a/lld/test/COFF/arm64ec.test
+++ b/lld/test/COFF/arm64ec.test
@@ -37,7 +37,7 @@ ARM64X-DATA: 03030303 01010101 02020202
 
 RUN: not lld-link -out:test.dll -machine:arm64 arm64-data-sym.obj arm64ec-data-sym.obj \
 RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT1 %s
-INCOMPAT1: arm64ec-data-sym.obj: machine type arm64ec conflicts with arm64
+INCOMPAT1: lld-link: error: arm64ec-data-sym.obj: machine type arm64ec conflicts with arm64
 
 RUN: not lld-link -out:test.dll -machine:arm64ec arm64ec-data-sym.obj arm64-data-sym.obj \
 RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT2 %s
@@ -55,17 +55,17 @@ INCOMPAT4: lld-link: error: arm64ec-data-sym.obj: machine type arm64ec is ambigu
 RUN: not lld-link -out:test.dll x86_64-data-sym.obj arm64ec-data-sym.obj \
 RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s
 
-RUN: not lld-link -out:test.dll aarch64-data-sym.obj arm64ec-data-sym.obj \
+RUN: not lld-link -out:test.dll arm64-data-sym.obj arm64ec-data-sym.obj \
 RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s
 
 RUN: not lld-link -out:test.dll i686-data-sym.obj arm64ec-data-sym.obj \
 RUN:              -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT5 %s
-INCOMPAT5: arm64ec-data-sym.obj: machine type arm64ec conflicts with x86
+INCOMPAT5: lld-link: error: arm64ec-data-sym.obj: machine type arm64ec conflicts with x86
 
-arm64x input implies arm64 target
-RUN: lld-link -out:test.dll -machine:arm64 arm64x-resource.obj -dll -noentry
-RUN: llvm-readobj --file-headers test.dll | FileCheck -check-prefix=ARM64-HEADER %s
-ARM64-HEADER:      Machine: IMAGE_FILE_MACHINE_ARM64 (0xAA64)
+arm64x can be inferred and when mixed with ARM64, the first one wins
+RUN: lld-link -out:test.dll -dll -noentry arm64x-resource.obj arm64-data-sym.obj x86_64-data-sym.obj arm64ec-data-sym.obj
+RUN: not lld-link -out:test.dll -dll -noentry arm64-data-sym.obj arm64x-resource.obj x86_64-data-sym.obj 2>&1 | FileCheck -check-prefix=INCOMPAT3 %s
+RUN: not lld-link -out:test.dll -dll -noentry arm64-data-sym.obj arm64x-resource.obj arm64ec-data-sym.obj 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s
 
 #--- arm64ec-data-sym.s
     .data



More information about the llvm-commits mailing list