[lld] [LLD][COFF] Support alternate names in both symbol tables on ARM64X (PR #127619)

via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 18 03:44:36 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-coff

Author: Jacek Caban (cjacek)

<details>
<summary>Changes</summary>

The `.drectve` directive applies only to the namespace in which it is defined, while the command-line argument applies only to the EC namespace.

---
Full diff: https://github.com/llvm/llvm-project/pull/127619.diff


7 Files Affected:

- (modified) lld/COFF/Config.h (-3) 
- (modified) lld/COFF/Driver.cpp (+22-24) 
- (modified) lld/COFF/Driver.h (-1) 
- (modified) lld/COFF/DriverUtils.cpp (-12) 
- (modified) lld/COFF/SymbolTable.cpp (+11) 
- (modified) lld/COFF/SymbolTable.h (+4) 
- (added) lld/test/COFF/arm64x-altnames.s (+44) 


``````````diff
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 0c7c4e91402f1..0df848127f2cf 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -220,9 +220,6 @@ struct Configuration {
   // Used for /failifmismatch.
   std::map<StringRef, std::pair<StringRef, InputFile *>> mustMatch;
 
-  // Used for /alternatename.
-  std::map<StringRef, StringRef> alternateNames;
-
   // Used for /order.
   llvm::StringMap<int> order;
 
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 6433ce6643f9c..1589323073c09 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -490,7 +490,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
       parseAligncomm(arg->getValue());
       break;
     case OPT_alternatename:
-      parseAlternateName(arg->getValue());
+      file->symtab.parseAlternateName(arg->getValue());
       break;
     case OPT_defaultlib:
       if (std::optional<StringRef> path = findLibIfNew(arg->getValue()))
@@ -1896,7 +1896,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
 
   // Handle /alternatename
   for (auto *arg : args.filtered(OPT_alternatename))
-    parseAlternateName(arg->getValue());
+    mainSymtab.parseAlternateName(arg->getValue());
 
   // Handle /include
   for (auto *arg : args.filtered(OPT_incl))
@@ -2515,32 +2515,30 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
           if (e.source != ExportSource::Directives)
             e.symbolName = symtab.mangleMaybe(e.sym);
         }
-      });
 
-      // Add weak aliases. Weak aliases is a mechanism to give remaining
-      // undefined symbols final chance to be resolved successfully.
-      for (auto pair : config->alternateNames) {
-        StringRef from = pair.first;
-        StringRef to = pair.second;
-        Symbol *sym = ctx.symtab.find(from);
-        if (!sym)
-          continue;
-        if (auto *u = dyn_cast<Undefined>(sym)) {
-          if (u->weakAlias) {
-            // On ARM64EC, anti-dependency aliases are treated as undefined
-            // symbols unless a demangled symbol aliases a defined one, which is
-            // part of the implementation.
-            if (!isArm64EC(ctx.config.machine) || !u->isAntiDep)
-              continue;
-            if (!isa<Undefined>(u->weakAlias) &&
-                !isArm64ECMangledFunctionName(u->getName()))
-              continue;
+        // Add weak aliases. Weak aliases is a mechanism to give remaining
+        // undefined symbols final chance to be resolved successfully.
+        for (auto pair : symtab.alternateNames) {
+          StringRef from = pair.first;
+          StringRef to = pair.second;
+          Symbol *sym = symtab.find(from);
+          if (!sym)
+            continue;
+          if (auto *u = dyn_cast<Undefined>(sym)) {
+            if (u->weakAlias) {
+              // On ARM64EC, anti-dependency aliases are treated as undefined
+              // symbols unless a demangled symbol aliases a defined one, which
+              // is part of the implementation.
+              if (!symtab.isEC() || !u->isAntiDep)
+                continue;
+              if (!isa<Undefined>(u->weakAlias) &&
+                  !isArm64ECMangledFunctionName(u->getName()))
+                continue;
+            }
+            u->setWeakAlias(symtab.addUndefined(to));
           }
-          u->setWeakAlias(ctx.symtab.addUndefined(to));
         }
-      }
 
-      ctx.forEachSymtab([&](SymbolTable &symtab) {
         // If any inputs are bitcode files, the LTO code generator may create
         // references to library functions that are not explicit in the bitcode
         // file's symbol table. If any of those library functions are defined in
diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h
index 58dc5458e9a54..96f462aaff812 100644
--- a/lld/COFF/Driver.h
+++ b/lld/COFF/Driver.h
@@ -209,7 +209,6 @@ class LinkerDriver {
   void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,
                       uint32_t *minor, bool *gotVersion = nullptr);
 
-  void parseAlternateName(StringRef);
   void parseMerge(StringRef);
   void parsePDBPageSize(StringRef);
   void parseSection(StringRef);
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index 4a70c826691d1..0a9b7c410f731 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -145,18 +145,6 @@ void LinkerDriver::parseSubsystem(StringRef arg, WindowsSubsystem *sys,
     *gotVersion = !ver.empty();
 }
 
-// Parse a string of the form of "<from>=<to>".
-// Results are directly written to Config.
-void LinkerDriver::parseAlternateName(StringRef s) {
-  auto [from, to] = s.split('=');
-  if (from.empty() || to.empty())
-    Fatal(ctx) << "/alternatename: invalid argument: " << s;
-  auto it = ctx.config.alternateNames.find(from);
-  if (it != ctx.config.alternateNames.end() && it->second != to)
-    Fatal(ctx) << "/alternatename: conflicts: " << s;
-  ctx.config.alternateNames.insert(it, std::make_pair(from, to));
-}
-
 // Parse a string of the form of "<from>=<to>".
 // Results are directly written to Config.
 void LinkerDriver::parseMerge(StringRef s) {
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 307bd4a0c9411..7919e7a95a620 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -1320,6 +1320,17 @@ void SymbolTable::parseModuleDefs(StringRef path) {
   }
 }
 
+// Parse a string of the form of "<from>=<to>".
+void SymbolTable::parseAlternateName(StringRef s) {
+  auto [from, to] = s.split('=');
+  if (from.empty() || to.empty())
+    Fatal(ctx) << "/alternatename: invalid argument: " << s;
+  auto it = alternateNames.find(from);
+  if (it != alternateNames.end() && it->second != to)
+    Fatal(ctx) << "/alternatename: conflicts: " << s;
+  alternateNames.insert(it, std::make_pair(from, to));
+}
+
 Symbol *SymbolTable::addUndefined(StringRef name) {
   return addUndefined(name, nullptr, false);
 }
diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index b124998809e3c..ebd8e27419eaa 100644
--- a/lld/COFF/SymbolTable.h
+++ b/lld/COFF/SymbolTable.h
@@ -171,9 +171,13 @@ class SymbolTable {
   // A list of wrapped symbols.
   std::vector<WrappedSymbol> wrapped;
 
+  // Used for /alternatename.
+  std::map<StringRef, StringRef> alternateNames;
+
   void fixupExports();
   void assignExportOrdinals();
   void parseModuleDefs(StringRef path);
+  void parseAlternateName(StringRef);
 
   // Iterates symbols in non-determinstic hash table order.
   template <typename T> void forEachSymbol(T callback) {
diff --git a/lld/test/COFF/arm64x-altnames.s b/lld/test/COFF/arm64x-altnames.s
new file mode 100644
index 0000000000000..c161685bdc0e8
--- /dev/null
+++ b/lld/test/COFF/arm64x-altnames.s
@@ -0,0 +1,44 @@
+// REQUIRES: aarch64
+// RUN: split-file %s %t.dir && cd %t.dir
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows test.s -o test-arm64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows test.s -o test-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows drectve.s -o drectve-arm64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows drectve.s -o drectve-arm64ec.obj
+
+// Check that the -alternatename command-line argument applies only to the EC namespace.
+
+// RUN: not lld-link -out:out.dll -machine:arm64x -dll -noentry test-arm64.obj test-arm64ec.obj -alternatename:sym=altsym \
+// RUN:              2>&1 | FileCheck --check-prefix=ERR-NATIVE %s
+
+// ERR-NATIVE-NOT:  test-arm64ec.obj
+// ERR-NATIVE:      lld-link: error: undefined symbol: sym
+// ERR-NATIVE-NEXT: >>> referenced by test-arm64.obj:(.test)
+// ERR-NATIVE-NOT:  test-arm64ec.obj
+
+// Check that the -alternatename .drectve directive applies only to the namespace in which it is defined.
+
+// RUN: not lld-link -out:out.dll -machine:arm64x -dll -noentry test-arm64.obj test-arm64ec.obj drectve-arm64ec.obj \
+// RUN:              2>&1 | FileCheck --check-prefix=ERR-NATIVE %s
+
+// RUN: not lld-link -out:out.dll -machine:arm64x -dll -noentry test-arm64.obj test-arm64ec.obj drectve-arm64.obj \
+// RUN:              2>&1 | FileCheck --check-prefix=ERR-EC %s
+
+// ERR-EC-NOT:  test-arm64.obj
+// ERR-EC:      lld-link: error: undefined symbol: sym
+// ERR-EC-NEXT: >>> referenced by test-arm64ec.obj:(.test)
+// ERR-EC-NOT:  test-arm64.obj
+
+// RUN: lld-link -out:out.dll -machine:arm64x -dll -noentry test-arm64.obj test-arm64ec.obj drectve-arm64.obj drectve-arm64ec.obj
+
+#--- test.s
+        .section .test,"dr"
+        .rva sym
+        .data
+        .globl altsym
+altsym:
+        .word 0
+
+#--- drectve.s
+        .section .drectve
+        .ascii "-alternatename:sym=altsym"

``````````

</details>


https://github.com/llvm/llvm-project/pull/127619


More information about the llvm-commits mailing list