[lld] [LLD][COFF] Detect weak reference cycles. (PR #104463)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 15 08:57:51 PDT 2024
https://github.com/cjacek created https://github.com/llvm/llvm-project/pull/104463
Instead of entering an infinite loop.
>From b5976e4dcbda0dd481b6f40e060ed7ad45d9934b 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 | 8 +++++-
lld/test/COFF/weak-ref-cycle.test | 42 +++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
create mode 100644 lld/test/COFF/weak-ref-cycle.test
diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp
index f4efcf2266cd6b..2bc5476ff7f00a 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,14 @@ 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)
+ SmallSet<Symbol *, 4> weakChain;
+ for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias) {
+ if (weakChain.contains(a))
+ break; // We have a cycle.
if (auto *d = dyn_cast<Defined>(a))
return d;
+ weakChain.insert(a);
+ }
return nullptr;
}
diff --git a/lld/test/COFF/weak-ref-cycle.test b/lld/test/COFF/weak-ref-cycle.test
new file mode 100644
index 00000000000000..71d640fadaad07
--- /dev/null
+++ b/lld/test/COFF/weak-ref-cycle.test
@@ -0,0 +1,42 @@
+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 weak2.s -o weak2.obj
+RUN: llvm-mc -filetype=obj -triple=x86_64-windows weak-def.s -o weak-def.obj
+
+RUN: not lld-link -machine:amd64 -dll -noentry -out:test.dll test.obj weak2.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: weak1
+ERR-NEXT: >>> referenced by test.obj
+ERR-NEXT: >>> referenced by weak2.obj
+ERR-EMPTY:
+ERR-NEXT: error: undefined symbol: weak2
+ERR-NEXT: >>> referenced by test.obj
+ERR-NEXT: >>> referenced by weak2.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 weak2.obj weak-def.obj
+RUN: lld-link -machine:amd64 -dll -noentry -out:test.dll test.obj weak-def.obj weak2.obj
+RUN: lld-link -machine:amd64 -dll -noentry -out:test.dll weak-def.obj test.obj weak2.obj
+
+#--- test.s
+ .weak testsym
+.set testsym, weak1
+ .weak weak1
+.set weak1, weak2
+ .section .test, "r"
+
+#--- weak2.s
+ .weak weak2
+.set weak2, weak1
+
+#--- weak-def.s
+ .globl weak1
+ .data
+weak1:
+ .word 0
More information about the llvm-commits
mailing list