Skip to content

Commit 009f3c1

Browse files
aganeatstellar
authored andcommitted
[LLD][COFF] Don't dllimport from static libraries (llvm#134443)
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 llvm#131807
1 parent 70eed33 commit 009f3c1

6 files changed

+77
-44
lines changed

lld/COFF/Driver.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -2639,10 +2639,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
26392639
createECExportThunks();
26402640

26412641
// Resolve remaining undefined symbols and warn about imported locals.
2642-
ctx.forEachSymtab([&](SymbolTable &symtab) {
2643-
while (symtab.resolveRemainingUndefines())
2644-
run();
2645-
});
2642+
ctx.forEachSymtab(
2643+
[&](SymbolTable &symtab) { symtab.resolveRemainingUndefines(); });
26462644

26472645
if (errorCount())
26482646
return;

lld/COFF/SymbolTable.cpp

+15-10
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ struct UndefinedDiag {
214214
std::vector<File> files;
215215
};
216216

217-
static void reportUndefinedSymbol(COFFLinkerContext &ctx,
217+
static void reportUndefinedSymbol(SymbolTable *symTab,
218+
COFFLinkerContext &ctx,
218219
const UndefinedDiag &undefDiag) {
219220
auto diag = errorOrWarn(ctx);
220221
diag << "undefined symbol: " << undefDiag.sym;
@@ -232,6 +233,17 @@ static void reportUndefinedSymbol(COFFLinkerContext &ctx,
232233
}
233234
if (numDisplayedRefs < numRefs)
234235
diag << "\n>>> referenced " << numRefs - numDisplayedRefs << " more times";
236+
237+
// Hints
238+
StringRef name = undefDiag.sym->getName();
239+
if (name.consume_front("__imp_")) {
240+
Symbol *imp = symTab->find(name);
241+
if (imp && imp->isLazy()) {
242+
diag << "\nNOTE: a relevant symbol '" << imp->getName()
243+
<< "' is available in " << toString(imp->getFile())
244+
<< " but cannot be used because it is not an import library.";
245+
}
246+
}
235247
}
236248

237249
void SymbolTable::loadMinGWSymbols() {
@@ -402,7 +414,7 @@ void SymbolTable::reportProblemSymbols(
402414
processFile(file, file->getSymbols());
403415

404416
for (const UndefinedDiag &undefDiag : undefDiags)
405-
reportUndefinedSymbol(ctx, undefDiag);
417+
reportUndefinedSymbol(this, ctx, undefDiag);
406418
}
407419

408420
void SymbolTable::reportUnresolvable() {
@@ -432,11 +444,10 @@ void SymbolTable::reportUnresolvable() {
432444
reportProblemSymbols(undefs, /*localImports=*/nullptr, true);
433445
}
434446

435-
bool SymbolTable::resolveRemainingUndefines() {
447+
void SymbolTable::resolveRemainingUndefines() {
436448
llvm::TimeTraceScope timeScope("Resolve remaining undefined symbols");
437449
SmallPtrSet<Symbol *, 8> undefs;
438450
DenseMap<Symbol *, Symbol *> localImports;
439-
bool foundLazy = false;
440451

441452
for (auto &i : symMap) {
442453
Symbol *sym = i.second;
@@ -481,11 +492,6 @@ bool SymbolTable::resolveRemainingUndefines() {
481492
imp = findLocalSym(*mangledName);
482493
}
483494
}
484-
if (imp && imp->isLazy()) {
485-
forceLazy(imp);
486-
foundLazy = true;
487-
continue;
488-
}
489495
if (imp && isa<Defined>(imp)) {
490496
auto *d = cast<Defined>(imp);
491497
replaceSymbol<DefinedLocalImport>(sym, ctx, name, d);
@@ -513,7 +519,6 @@ bool SymbolTable::resolveRemainingUndefines() {
513519
reportProblemSymbols(
514520
undefs, ctx.config.warnLocallyDefinedImported ? &localImports : nullptr,
515521
false);
516-
return foundLazy;
517522
}
518523

519524
std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) {

lld/COFF/SymbolTable.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,7 @@ class SymbolTable {
5858
// Try to resolve any undefined symbols and update the symbol table
5959
// accordingly, then print an error message for any remaining undefined
6060
// symbols and warn about imported local symbols.
61-
// Returns whether more files might need to be linked in to resolve lazy
62-
// symbols, in which case the caller is expected to call the function again
63-
// after linking those files.
64-
bool resolveRemainingUndefines();
61+
void resolveRemainingUndefines();
6562

6663
// Load lazy objects that are needed for MinGW automatic import and for
6764
// doing stdcall fixups.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# REQUIRES: x86
2+
3+
# Pulling in on both a dllimport symbol and a static symbol should only warn.
4+
# RUN: split-file %s %t.dir
5+
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/other.s -o %t.other.obj
6+
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/main.s -o %t.main.obj
7+
# RUN: llvm-lib %t.other.obj -out:%t.other.lib
8+
# RUN: lld-link %t.other.lib %t.main.obj -out:%t.dll -dll 2>&1 | FileCheck %s
9+
10+
CHECK: warning: {{.*}} locally defined symbol imported: foo {{.*}} [LNK4217]
11+
12+
#--- other.s
13+
.text
14+
.globl other
15+
.globl foo
16+
other:
17+
ret
18+
foo:
19+
ret
20+
#--- main.s
21+
.text
22+
.global _DllMainCRTStartup
23+
_DllMainCRTStartup:
24+
call *other(%rip)
25+
call *__imp_foo(%rip)
26+
ret

lld/test/COFF/imports-static-lib.test

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# REQUIRES: x86
2+
3+
# Ensure that we don't import dllimport symbols from static (non-import) libraries
4+
# RUN: split-file %s %t.dir
5+
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/foo.s -o %t.foo.obj
6+
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/main.s -o %t.main.obj
7+
# RUN: llvm-lib %t.foo.obj -out:%t.foo.lib
8+
# RUN: not lld-link %t.foo.lib %t.main.obj -out:%t.dll -dll 2>&1 | FileCheck %s
9+
10+
CHECK: error: undefined symbol: __declspec(dllimport) foo
11+
CHECK: NOTE: a relevant symbol 'foo' is available in {{.*}}.foo.lib but cannot be used because it is not an import library.
12+
13+
# Now do the same thing, but import the symbol from a import library.
14+
# RUN: llvm-mc --filetype=obj -triple=x86_64-windows-msvc %t.dir/foo_dll_main.s -o %t.foo_dll_main.obj
15+
# RUN: lld-link /out:%t.dll /dll %t.foo.obj %t.foo_dll_main.obj /export:foo /implib:%t.foo.imp.lib
16+
# RUN: lld-link %t.main.obj %t.foo.imp.lib -out:%t.exe -dll
17+
18+
#--- foo.s
19+
.text
20+
.globl foo
21+
foo:
22+
ret
23+
#--- foo_dll_main.s
24+
.text
25+
.global _DllMainCRTStartup
26+
_DllMainCRTStartup:
27+
ret
28+
#--- main.s
29+
.text
30+
.global _DllMainCRTStartup
31+
_DllMainCRTStartup:
32+
call *__imp_foo(%rip)
33+
ret

lld/test/COFF/undefined_lazy.test

-26
This file was deleted.

0 commit comments

Comments
 (0)