From f6a6060a4cedaaa18e58770edcbce3a9549d3245 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 18 Sep 2024 18:03:43 +0900 Subject: [PATCH] [LLD][COFF] Do as many passes of resolveRemainingUndefines as necessary for undefined lazy symbols --- lld/COFF/Driver.cpp | 4 +++- lld/COFF/SymbolTable.cpp | 9 ++++++++- lld/COFF/SymbolTable.h | 5 ++++- lld/test/COFF/undefined_lazy.test | 26 ++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 lld/test/COFF/undefined_lazy.test diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 1b94f10acf80e..0e31cb91c59e1 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -2601,7 +2601,9 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { createECExportThunks(); // Resolve remaining undefined symbols and warn about imported locals. - ctx.symtab.resolveRemainingUndefines(); + while (ctx.symtab.resolveRemainingUndefines()) + run(); + if (errorCount()) return; diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 1488ad95d0da6..6dc777de13daf 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -479,10 +479,11 @@ void SymbolTable::reportUnresolvable() { /* localImports */ nullptr, true); } -void SymbolTable::resolveRemainingUndefines() { +bool SymbolTable::resolveRemainingUndefines() { llvm::TimeTraceScope timeScope("Resolve remaining undefined symbols"); SmallPtrSet undefs; DenseMap localImports; + bool foundLazy = false; for (auto &i : symMap) { Symbol *sym = i.second; @@ -510,6 +511,11 @@ void SymbolTable::resolveRemainingUndefines() { undef->resolveWeakAlias(); } } + if (imp && imp->isLazy()) { + forceLazy(imp); + foundLazy = true; + continue; + } if (imp && isa(imp)) { auto *d = cast(imp); replaceSymbol(sym, ctx, name, d); @@ -537,6 +543,7 @@ void SymbolTable::resolveRemainingUndefines() { reportProblemSymbols( ctx, undefs, ctx.config.warnLocallyDefinedImported ? &localImports : nullptr, false); + return foundLazy; } std::pair SymbolTable::insert(StringRef name) { diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index bf97cf442039e..1ab35a87cb9fa 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -57,7 +57,10 @@ class SymbolTable { // 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. - void resolveRemainingUndefines(); + // 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(); // Load lazy objects that are needed for MinGW automatic import and for // doing stdcall fixups. diff --git a/lld/test/COFF/undefined_lazy.test b/lld/test/COFF/undefined_lazy.test new file mode 100644 index 0000000000000..ed5cd358b5cd9 --- /dev/null +++ b/lld/test/COFF/undefined_lazy.test @@ -0,0 +1,26 @@ +# 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