[Lldb-commits] [lldb] af5aa17 - [lldb][test] Avoid namespace name colliding with dyld symbols in TestAbiTagLookup (#203984)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Aug 27 05:02:31 PDT 2026
Author: Yao Qi
Date: 2026-08-27T13:02:27+01:00
New Revision: af5aa17f44bf385e3cc9e2d9ffc2156e49f1071e
URL: https://github.com/llvm/llvm-project/commit/af5aa17f44bf385e3cc9e2d9ffc2156e49f1071e
DIFF: https://github.com/llvm/llvm-project/commit/af5aa17f44bf385e3cc9e2d9ffc2156e49f1071e.diff
LOG: [lldb][test] Avoid namespace name colliding with dyld symbols in TestAbiTagLookup (#203984)
TestAbiTagLookup.py used `v1` as the inline namespace name. On macOS the
dyld shared cache contains two unrelated internal data symbols named
`v1` (one in dyld, one in libdyld.dylib). When evaluating
`v1::withImplicitTag(...)`, `ClangExpressionDeclMap` resolves `v1` as a
namespace correctly, but then still falls through to
`SymbolContext::FindBestGlobalDataSymbol`, which finds the two dyld
symbols and raises "Multiple internal symbols found for 'v1'", failing
the test.
Rename the inline namespace to `lldb_test_abi_tag_lookup_inline_ns` so
the test no longer collides with anything in dyld.
Add a new XFAIL test, namespace_data_symbol_collision, that reproduces
the underlying bug deterministically (without depending on `dyld`) by
linking two non-debug-info objects that each define a static data
symbol whose name matches a real namespace in main.cpp.
Added:
lldb/test/API/lang/cpp/namespace_data_symbol_collision/Makefile
lldb/test/API/lang/cpp/namespace_data_symbol_collision/TestNamespaceDataSymbolCollision.py
lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_a.c
lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_b.c
lldb/test/API/lang/cpp/namespace_data_symbol_collision/main.cpp
Modified:
lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py
lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp
Removed:
################################################################################
diff --git a/lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py b/lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py
index 19f4a4e14ed22..76d89cfff8e48 100644
--- a/lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py
+++ b/lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py
@@ -60,14 +60,18 @@ def test_abi_tag_lookup(self):
# Inline namespaces with ABI tags
self.expect_expr(
- "v1::withImplicitTag(Simple{.mem = 6})", result_type="int", result_value="6"
+ "lldb_test_abi_tag_lookup_inline_ns::withImplicitTag(Simple{.mem = 6})",
+ result_type="int",
+ result_value="6",
)
self.expect_expr(
"withImplicitTag(Simple{.mem = 6})", result_type="int", result_value="6"
)
self.expect_expr(
- "v1::withImplicitTag(Tagged{.mem = 6})", result_type="int", result_value="6"
+ "lldb_test_abi_tag_lookup_inline_ns::withImplicitTag(Tagged{.mem = 6})",
+ result_type="int",
+ result_value="6",
)
self.expect_expr(
"withImplicitTag(Tagged{.mem = 6})", result_type="int", result_value="6"
diff --git a/lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp b/lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp
index 4c1ff688df0cd..ab5aabaddd2c8 100644
--- a/lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp
+++ b/lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp
@@ -49,7 +49,7 @@ template <typename T> struct [[gnu::abi_tag("Quux", "Quuux")]] TaggedTemplate {
};
// clang-format off
-inline namespace [[gnu::abi_tag("Inline", "NS")]] v1 {
+inline namespace [[gnu::abi_tag("Inline", "NS")]] lldb_test_abi_tag_lookup_inline_ns {
template <typename T> int withImplicitTag(T const &t) { return t.mem; }
} // namespace
// clang-format on
diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/Makefile b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/Makefile
new file mode 100644
index 0000000000000..1573282719a1f
--- /dev/null
+++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/Makefile
@@ -0,0 +1,10 @@
+CXX_SOURCES := main.cpp
+C_SOURCES := colliding_a.c colliding_b.c
+
+include Makefile.rules
+
+# The colliding_*.c files must be built WITHOUT debug info so that lldb sees
+# them only as bare symtab entries (eSymbolTypeData), the same situation as
+# the dyld globals that triggered the original failure.
+colliding_a.o: CFLAGS = $(CFLAGS_NO_DEBUG)
+colliding_b.o: CFLAGS = $(CFLAGS_NO_DEBUG)
diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/TestNamespaceDataSymbolCollision.py b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/TestNamespaceDataSymbolCollision.py
new file mode 100644
index 0000000000000..096cf76db1742
--- /dev/null
+++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/TestNamespaceDataSymbolCollision.py
@@ -0,0 +1,32 @@
+"""
+This test plants two unrelated internal data symbols named
+`colliding_ns` in non-debug-info objects, then evaluates a qualified-id
+expression that uses `colliding_ns` as a (real) namespace prefix.
+
+Expected eventual behavior: the namespace resolution succeeds and the
+function call returns 6.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestCase(TestBase):
+ @skipIfWindows
+ @expectedFailureAll
+ def test(self):
+ self.build()
+ lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec("main.cpp", False)
+ )
+
+ # The bug: even though `colliding_ns` is a namespace in the program,
+ # lldb's expression evaluator still runs FindBestGlobalDataSymbol on
+ # the bare name, finds the two internal data symbols, and errors out.
+ self.expect_expr(
+ "colliding_ns::do_thing(5)",
+ result_type="int",
+ result_value="6",
+ )
diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_a.c b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_a.c
new file mode 100644
index 0000000000000..2c1209cebe96d
--- /dev/null
+++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_a.c
@@ -0,0 +1,6 @@
+// Internal (file-static) data symbol named `colliding_ns`. Built without
+// debug info, so lldb sees only the symtab entry, not a DWARF VarDecl.
+static const int colliding_ns __attribute__((used)) = 1;
+
+// Anchor referenced from main so the linker keeps the object alive.
+const int *colliding_a_anchor(void) { return &colliding_ns; }
diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_b.c b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_b.c
new file mode 100644
index 0000000000000..535bcf72b5e0b
--- /dev/null
+++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_b.c
@@ -0,0 +1,7 @@
+// Second internal data symbol with the SAME name as the one in
+// colliding_a.c. Two such symbols in the target's symtab is what trips
+// SymbolContext::FindBestGlobalDataSymbol -> "Multiple internal symbols
+// found".
+static const int colliding_ns __attribute__((used)) = 2;
+
+const int *colliding_b_anchor(void) { return &colliding_ns; }
diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/main.cpp b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/main.cpp
new file mode 100644
index 0000000000000..8ac25477df526
--- /dev/null
+++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/main.cpp
@@ -0,0 +1,18 @@
+// `colliding_ns` is a real (inline) namespace in this translation unit.
+// Two unrelated internal data symbols of the same name live in
+// colliding_a.o / colliding_b.o (built without debug info).
+inline namespace colliding_ns {
+int do_thing(int t) { return t + 1; }
+} // namespace colliding_ns
+
+extern "C" const int *colliding_a_anchor(void);
+extern "C" const int *colliding_b_anchor(void);
+
+int main() {
+ // Force the linker to keep both internal `colliding_ns` data symbols.
+ (void)colliding_a_anchor();
+ (void)colliding_b_anchor();
+
+ int r = do_thing(5);
+ return r; // Break here
+}
More information about the lldb-commits
mailing list