0
0
mirror of https://github.com/llvm/llvm-project.git synced 2025-04-21 15:07:13 +00:00

[LLD][COFF] Don't dllimport from static libraries ()

This reverts commit 6a1bdd9 and re-instate behavior that matches what
MSVC link.exe does, that is, error out when trying to dllimport a symbol
from a static library.

A hint is now displayed in stdout, mentioning that we should rather dllimport the symbol
from a import library.

Fixes https://github.com/llvm/llvm-project/issues/131807
This commit is contained in:
Alexandre Ganea 2025-04-07 11:34:24 -04:00 committed by GitHub
parent 4b90f24db8
commit c75eac7c03
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 74 additions and 42 deletions

@ -2663,10 +2663,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
createECExportThunks();
// Resolve remaining undefined symbols and warn about imported locals.
ctx.forEachSymtab([&](SymbolTable &symtab) {
while (symtab.resolveRemainingUndefines())
run();
});
ctx.forEachSymtab(
[&](SymbolTable &symtab) { symtab.resolveRemainingUndefines(); });
if (errorCount())
return;

@ -231,6 +231,17 @@ void SymbolTable::reportUndefinedSymbol(const UndefinedDiag &undefDiag) {
}
if (numDisplayedRefs < numRefs)
diag << "\n>>> referenced " << numRefs - numDisplayedRefs << " more times";
// Hints
StringRef name = undefDiag.sym->getName();
if (name.consume_front("__imp_")) {
Symbol *imp = find(name);
if (imp && imp->isLazy()) {
diag << "\nNOTE: a relevant symbol '" << imp->getName()
<< "' is available in " << toString(imp->getFile())
<< " but cannot be used because it is not an import library.";
}
}
}
void SymbolTable::loadMinGWSymbols() {
@ -432,11 +443,10 @@ void SymbolTable::reportUnresolvable() {
reportProblemSymbols(undefs, /*localImports=*/nullptr, true);
}
bool SymbolTable::resolveRemainingUndefines() {
void SymbolTable::resolveRemainingUndefines() {
llvm::TimeTraceScope timeScope("Resolve remaining undefined symbols");
SmallPtrSet<Symbol *, 8> undefs;
DenseMap<Symbol *, Symbol *> localImports;
bool foundLazy = false;
for (auto &i : symMap) {
Symbol *sym = i.second;
@ -481,11 +491,6 @@ bool SymbolTable::resolveRemainingUndefines() {
imp = findLocalSym(*mangledName);
}
}
if (imp && imp->isLazy()) {
forceLazy(imp);
foundLazy = true;
continue;
}
if (imp && isa<Defined>(imp)) {
auto *d = cast<Defined>(imp);
replaceSymbol<DefinedLocalImport>(sym, ctx, name, d);
@ -513,7 +518,6 @@ bool SymbolTable::resolveRemainingUndefines() {
reportProblemSymbols(
undefs, ctx.config.warnLocallyDefinedImported ? &localImports : nullptr,
false);
return foundLazy;
}
std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) {

@ -67,10 +67,7 @@ public:
// Try to resolve any undefined symbols and update the symbol table
// accordingly, then print an error message for any remaining undefined
// symbols and warn about imported local symbols.
// Returns whether more files might need to be linked in to resolve lazy
// symbols, in which case the caller is expected to call the function again
// after linking those files.
bool resolveRemainingUndefines();
void resolveRemainingUndefines();
// Load lazy objects that are needed for MinGW automatic import and for
// doing stdcall fixups.

@ -0,0 +1,26 @@
# REQUIRES: x86
# Pulling in on both a dllimport symbol and a static symbol should only warn.
# RUN: split-file %s %t.dir
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/other.s -o %t.other.obj
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/main.s -o %t.main.obj
# RUN: llvm-lib %t.other.obj -out:%t.other.lib
# RUN: lld-link %t.other.lib %t.main.obj -out:%t.dll -dll 2>&1 | FileCheck %s
CHECK: warning: {{.*}} locally defined symbol imported: foo {{.*}} [LNK4217]
#--- other.s
.text
.globl other
.globl foo
other:
ret
foo:
ret
#--- main.s
.text
.global _DllMainCRTStartup
_DllMainCRTStartup:
call *other(%rip)
call *__imp_foo(%rip)
ret

@ -0,0 +1,33 @@
# REQUIRES: x86
# Ensure that we don't import dllimport symbols from static (non-import) libraries
# RUN: split-file %s %t.dir
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/foo.s -o %t.foo.obj
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/main.s -o %t.main.obj
# RUN: llvm-lib %t.foo.obj -out:%t.foo.lib
# RUN: not lld-link %t.foo.lib %t.main.obj -out:%t.dll -dll 2>&1 | FileCheck %s
CHECK: error: undefined symbol: __declspec(dllimport) foo
CHECK: NOTE: a relevant symbol 'foo' is available in {{.*}}.foo.lib but cannot be used because it is not an import library.
# Now do the same thing, but import the symbol from a import library.
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/foo_dll_main.s -o %t.foo_dll_main.obj
# RUN: lld-link /out:%t.dll /dll %t.foo.obj %t.foo_dll_main.obj /export:foo /implib:%t.foo.imp.lib
# RUN: lld-link %t.main.obj %t.foo.imp.lib -out:%t.exe -dll
#--- foo.s
.text
.globl foo
foo:
ret
#--- foo_dll_main.s
.text
.global _DllMainCRTStartup
_DllMainCRTStartup:
ret
#--- main.s
.text
.global _DllMainCRTStartup
_DllMainCRTStartup:
call *__imp_foo(%rip)
ret

@ -1,26 +0,0 @@
# REQUIRES: x86
# RUN: split-file %s %t.dir
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/foo.s -o %t.foo.obj
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/bar.s -o %t.bar.obj
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/qux.s -o %t.qux.obj
# RUN: llvm-lib %t.foo.obj -out:%t.foo.lib
# RUN: llvm-lib %t.bar.obj -out:%t.bar.lib
# RUN: lld-link %t.foo.lib %t.bar.lib %t.qux.obj -out:%t.dll -dll
#
#--- foo.s
.text
.globl foo
foo:
call bar
#--- bar.s
.text
.globl bar
bar:
ret
#--- qux.s
.text
.global _DllMainCRTStartup
_DllMainCRTStartup:
call *__imp_foo(%rip)
ret