[lld] [LLD][COFF] Support alternate names in both symbol tables on ARM64X (PR #127619)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 18 03:44:04 PST 2025
https://github.com/cjacek created https://github.com/llvm/llvm-project/pull/127619
The `.drectve` directive applies only to the namespace in which it is defined, while the command-line argument applies only to the EC namespace.
>From 9608a0af59b243d32b5c62044d5b5b34c2f2ce72 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Tue, 18 Feb 2025 12:16:42 +0100
Subject: [PATCH] [LLD][COFF] Support alternate names in both symbol tables on
ARM64X
The .drectve directive applies only to the namespace in which it is defined, while the command-line argument applies only to the EC namespace.
---
lld/COFF/Config.h | 3 ---
lld/COFF/Driver.cpp | 46 ++++++++++++++++-----------------
lld/COFF/Driver.h | 1 -
lld/COFF/DriverUtils.cpp | 12 ---------
lld/COFF/SymbolTable.cpp | 11 ++++++++
lld/COFF/SymbolTable.h | 4 +++
lld/test/COFF/arm64x-altnames.s | 44 +++++++++++++++++++++++++++++++
7 files changed, 81 insertions(+), 40 deletions(-)
create mode 100644 lld/test/COFF/arm64x-altnames.s
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"
More information about the llvm-commits
mailing list