[lld] 513e0af - [LLD][COFF] Detect weak reference cycles. (#104463)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 20 01:21:04 PDT 2024


Author: Jacek Caban
Date: 2024-08-20T10:21:00+02:00
New Revision: 513e0af0a940f3a823f8f0e83189cb33cb81496f

URL: https://github.com/llvm/llvm-project/commit/513e0af0a940f3a823f8f0e83189cb33cb81496f
DIFF: https://github.com/llvm/llvm-project/commit/513e0af0a940f3a823f8f0e83189cb33cb81496f.diff

LOG: [LLD][COFF] Detect weak reference cycles. (#104463)

Instead of entering an infinite loop.

Added: 
    lld/test/COFF/weak-external-cycle.test

Modified: 
    lld/COFF/Symbols.cpp

Removed: 
    


################################################################################
diff  --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp
index f4efcf2266cd6b..ff8ad1e619116f 100644
--- a/lld/COFF/Symbols.cpp
+++ b/lld/COFF/Symbols.cpp
@@ -126,9 +126,13 @@ DefinedImportThunk::DefinedImportThunk(COFFLinkerContext &ctx, StringRef name,
 
 Defined *Undefined::getWeakAlias() {
   // A weak alias may be a weak alias to another symbol, so check recursively.
-  for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias)
+  DenseSet<Symbol *> weakChain;
+  for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias) {
     if (auto *d = dyn_cast<Defined>(a))
       return d;
+    if (!weakChain.insert(a).second)
+      break; // We have a cycle.
+  }
   return nullptr;
 }
 

diff  --git a/lld/test/COFF/weak-external-cycle.test b/lld/test/COFF/weak-external-cycle.test
new file mode 100644
index 00000000000000..65f483350790f7
--- /dev/null
+++ b/lld/test/COFF/weak-external-cycle.test
@@ -0,0 +1,41 @@
+REQUIRES: x86
+RUN: split-file %s %t.dir && cd %t.dir
+
+RUN: llvm-mc -filetype=obj -triple=x86_64-windows test.s -o test.obj
+RUN: llvm-mc -filetype=obj -triple=x86_64-windows sym2.s -o sym2.obj
+RUN: llvm-mc -filetype=obj -triple=x86_64-windows def.s -o def.obj
+
+RUN: not lld-link -machine:amd64 -dll -noentry -out:test.dll test.obj sym2.obj 2>&1 | FileCheck -check-prefix=ERR %s
+
+ERR:      error: undefined symbol: testsym
+ERR-NEXT: >>> referenced by test.obj
+ERR-EMPTY:
+ERR-NEXT: error: undefined symbol: sym1
+ERR-NEXT: >>> referenced by test.obj
+ERR-NEXT: >>> referenced by sym2.obj
+ERR-EMPTY:
+ERR-NEXT: error: undefined symbol: sym2
+ERR-NEXT: >>> referenced by test.obj
+ERR-NEXT: >>> referenced by sym2.obj
+
+Depending on symbol processing order, we may have temporary weak reference cycles:
+
+RUN: lld-link -machine:amd64 -dll -noentry -out:test.dll test.obj sym2.obj def.obj
+RUN: lld-link -machine:amd64 -dll -noentry -out:test.dll test.obj def.obj sym2.obj
+RUN: lld-link -machine:amd64 -dll -noentry -out:test.dll def.obj test.obj sym2.obj
+
+#--- test.s
+    .weak testsym
+.set testsym, sym1
+    .weak sym1
+.set sym1, sym2
+
+#--- sym2.s
+    .weak sym2
+.set sym2, sym1
+
+#--- def.s
+    .globl sym1
+    .data
+sym1:
+    .word 0


        


More information about the llvm-commits mailing list