[lld] [LLD][COFF] Detect weak reference cycles. (PR #104463)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 16 04:15:13 PDT 2024
https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/104463
>From 1c373b5f401b22fbf06902ea64f1bdce10919ddb Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Sun, 10 Sep 2023 22:22:12 +0200
Subject: [PATCH] [LLD][COFF] Detect weak reference cycles.
---
lld/COFF/Symbols.cpp | 7 ++++-
lld/test/COFF/weak-external-cycle.test | 41 ++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 1 deletion(-)
create mode 100644 lld/test/COFF/weak-external-cycle.test
diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp
index f4efcf2266cd6b..bf84c46ef0b2d4 100644
--- a/lld/COFF/Symbols.cpp
+++ b/lld/COFF/Symbols.cpp
@@ -13,6 +13,7 @@
#include "lld/Common/Memory.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -126,9 +127,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)
+ DenseMap<Symbol *, bool> weakChain;
+ for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias) {
+ if (!weakChain.try_emplace(a, true).second)
+ break; // We have a cycle.
if (auto *d = dyn_cast<Defined>(a))
return d;
+ }
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