aboutsummaryrefslogtreecommitdiff
path: root/lldb/test/API
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/test/API')
-rw-r--r--lldb/test/API/commands/expression/weak_symbols/TestWeakSymbols.py2
-rw-r--r--lldb/test/API/commands/frame/select-hidden/Makefile3
-rw-r--r--lldb/test/API/commands/frame/select-hidden/TestNavigateHiddenFrame.py32
-rw-r--r--lldb/test/API/commands/frame/select-hidden/main.cpp13
-rw-r--r--lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py2
-rw-r--r--lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile3
-rw-r--r--lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py46
-rw-r--r--lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp23
-rw-r--r--lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/Makefile3
-rw-r--r--lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/TestFrameVarDILExprPointerArithmetic.py29
-rw-r--r--lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/main.cpp11
-rw-r--r--lldb/test/API/commands/target/auto-install-main-executable/Makefile2
-rw-r--r--lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py33
-rw-r--r--lldb/test/API/commands/target/stop-hooks/stop_hook.py25
-rw-r--r--lldb/test/API/functionalities/abbreviation/TestAbbreviations.py2
-rw-r--r--lldb/test/API/functionalities/ambigous_commands/TestAmbiguousCommands.py2
-rw-r--r--lldb/test/API/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py19
-rw-r--r--lldb/test/API/functionalities/breakpoint/breakpoint_locations/after_rebuild/TestLocationsAfterRebuild.py22
-rw-r--r--lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py31
-rw-r--r--lldb/test/API/functionalities/breakpoint/serialize/TestBreakpointSerialization.py9
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterGenericForwardList.py2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/TestDataFormatterStdInitializerList.py16
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/main.cpp1
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/loop/TestDataFormatterGenericListLoop.py1
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py14
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/shared_ptr/TestDataFormatterStdSharedPtr.py14
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/span/TestDataFormatterStdSpan.py26
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py81
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py78
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/tuple/TestDataFormatterStdTuple.py2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py16
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py16
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py12
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/invalid-string/TestDataFormatterLibcxxInvalidString.py2
-rw-r--r--lldb/test/API/functionalities/gdb_remote_client/TestConnectRemoteDetach.py67
-rw-r--r--lldb/test/API/functionalities/scripted_frame_provider/Makefile3
-rw-r--r--lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py555
-rw-r--r--lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/Makefile3
-rw-r--r--lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/TestFrameProviderCircularDependency.py119
-rw-r--r--lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/frame_provider.py102
-rw-r--r--lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/main.c21
-rw-r--r--lldb/test/API/functionalities/scripted_frame_provider/main.cpp53
-rw-r--r--lldb/test/API/functionalities/scripted_frame_provider/python_helper.py36
-rw-r--r--lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py316
-rw-r--r--lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py43
-rw-r--r--lldb/test/API/functionalities/statusline/TestStatusline.py6
-rw-r--r--lldb/test/API/functionalities/thread/step_until/function.list5
-rw-r--r--lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile6
-rw-r--r--lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py177
-rw-r--r--lldb/test/API/functionalities/unwind/libunwind_ret_injection/main.cpp45
-rw-r--r--lldb/test/API/functionalities/wrong_commands/TestWrongCommands.py4
-rw-r--r--lldb/test/API/lang/BoundsSafety/soft_trap/Makefile10
-rw-r--r--lldb/test/API/lang/BoundsSafety/soft_trap/TestBoundsSafetyInstrumentationPlugin.py148
-rw-r--r--lldb/test/API/lang/BoundsSafety/soft_trap/main.c10
-rw-r--r--lldb/test/API/lang/BoundsSafety/soft_trap/mockSoftTrapRuntime.c17
-rw-r--r--lldb/test/API/lang/cpp/inline-namespace-in-typename/Makefile3
-rw-r--r--lldb/test/API/lang/cpp/inline-namespace-in-typename/TestInlineNamespaceInTypename.py30
-rw-r--r--lldb/test/API/lang/cpp/inline-namespace-in-typename/main.cpp13
-rw-r--r--lldb/test/API/lang/cpp/libcxx-internals-recognizer/TestLibcxxInternalsRecognizer.py3
-rw-r--r--lldb/test/API/lang/cpp/template-alias/Makefile3
-rw-r--r--lldb/test/API/lang/cpp/template-alias/TestTemplateAlias.py50
-rw-r--r--lldb/test/API/lang/cpp/template-alias/main.cpp16
-rw-r--r--lldb/test/API/lang/objc/foundation/TestFoundationDisassembly.py46
-rw-r--r--lldb/test/API/lang/objc/modules-auto-import/TestModulesAutoImport.py1
-rw-r--r--lldb/test/API/lang/objc/modules-compile-error/Makefile5
-rw-r--r--lldb/test/API/lang/objc/modules-compile-error/TestModulesCompileError.py28
-rw-r--r--lldb/test/API/lang/objc/modules-compile-error/main.m5
-rw-r--r--lldb/test/API/lang/objc/modules-compile-error/module.h5
-rw-r--r--lldb/test/API/lang/objc/modules-compile-error/module.modulemap1
-rw-r--r--lldb/test/API/lang/objc/modules-objc-property/TestModulesObjCProperty.py1
-rw-r--r--lldb/test/API/lang/rust/enum-variant-same-name/RustEnumValue.py69
-rw-r--r--lldb/test/API/lang/rust/enum-variant-same-name/TestRustEnumVariantSameName.py36
-rw-r--r--lldb/test/API/lang/rust/enum-variant-same-name/main.rs15
-rw-r--r--lldb/test/API/lang/rust/enum-variant-same-name/main.yaml1137
-rw-r--r--lldb/test/API/macosx/find-dsym/bundle-with-dot-in-filename/Makefile4
-rw-r--r--lldb/test/API/macosx/find-dsym/deep-bundle/Makefile4
-rw-r--r--lldb/test/API/macosx/posix_spawn/Makefile6
-rw-r--r--lldb/test/API/python_api/command_script_output/TestCommandScriptOutput.py47
-rw-r--r--lldb/test/API/python_api/exprpath_register/Makefile3
-rw-r--r--lldb/test/API/python_api/exprpath_register/TestExprPathRegisters.py64
-rw-r--r--lldb/test/API/python_api/exprpath_register/main.c10
-rw-r--r--lldb/test/API/python_api/frame_list/Makefile3
-rw-r--r--lldb/test/API/python_api/frame_list/TestSBFrameList.py194
-rw-r--r--lldb/test/API/python_api/frame_list/main.cpp22
-rw-r--r--lldb/test/API/python_api/sblineentry/TestSBLineEntry.py144
-rw-r--r--lldb/test/API/python_api/target/TestTargetAPI.py18
-rw-r--r--lldb/test/API/python_api/unified_section_list/Makefile5
-rw-r--r--lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py285
-rw-r--r--lldb/test/API/python_api/unified_section_list/main.cpp3
-rw-r--r--lldb/test/API/python_api/unified_section_list/main.largercomment.yaml46
-rw-r--r--lldb/test/API/python_api/unified_section_list/main.largertext.yaml46
-rw-r--r--lldb/test/API/python_api/unified_section_list/main.reversedtext.yaml45
-rw-r--r--lldb/test/API/python_api/unified_section_list/main.yaml45
-rw-r--r--lldb/test/API/symbol_ondemand/breakpoint_source_regex/TestSourceTextRegexBreakpoint.py4
-rw-r--r--lldb/test/API/terminal/TestEditline.py2
-rw-r--r--lldb/test/API/test_utils/pdb/Makefile3
-rw-r--r--lldb/test/API/test_utils/pdb/TestPdb.py18
-rw-r--r--lldb/test/API/test_utils/pdb/main.cpp1
-rw-r--r--lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py35
-rw-r--r--lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py111
-rw-r--r--lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py9
-rw-r--r--lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py203
-rw-r--r--lldb/test/API/tools/lldb-dap/server/TestDAP_server.py3
-rw-r--r--lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/Makefile3
-rw-r--r--lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/TestDAP_stackTraceCompilerGeneratedCode.py66
-rw-r--r--lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/main.c19
-rw-r--r--lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py51
113 files changed, 5051 insertions, 289 deletions
diff --git a/lldb/test/API/commands/expression/weak_symbols/TestWeakSymbols.py b/lldb/test/API/commands/expression/weak_symbols/TestWeakSymbols.py
index 50efecb..bed129a 100644
--- a/lldb/test/API/commands/expression/weak_symbols/TestWeakSymbols.py
+++ b/lldb/test/API/commands/expression/weak_symbols/TestWeakSymbols.py
@@ -15,7 +15,7 @@ class TestWeakSymbolsInExpressions(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@skipUnlessDarwin
- @skipIf(compiler="clang", compiler_version=["<", "7.0"])
+ @skipIf(compiler="clang", compiler_version=["<", "19.0"])
def test_weak_symbol_in_expr(self):
"""Tests that we can refer to weak symbols in expressions."""
self.build()
diff --git a/lldb/test/API/commands/frame/select-hidden/Makefile b/lldb/test/API/commands/frame/select-hidden/Makefile
new file mode 100644
index 0000000..99998b2
--- /dev/null
+++ b/lldb/test/API/commands/frame/select-hidden/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/commands/frame/select-hidden/TestNavigateHiddenFrame.py b/lldb/test/API/commands/frame/select-hidden/TestNavigateHiddenFrame.py
new file mode 100644
index 0000000..698447b5
--- /dev/null
+++ b/lldb/test/API/commands/frame/select-hidden/TestNavigateHiddenFrame.py
@@ -0,0 +1,32 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class NavigateHiddenFrameTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @add_test_categories(["libc++"])
+ def test(self):
+ """Test going up/down a backtrace but we started in a hidden frame."""
+ self.build()
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec("main.cpp")
+ )
+ # up
+ self.assertIn("__impl2", thread.selected_frame.GetFunctionName())
+ self.expect("up")
+ self.assertIn("__impl1", thread.selected_frame.GetFunctionName())
+ self.expect("up")
+ self.assertIn("__impl", thread.selected_frame.GetFunctionName())
+ self.expect("up")
+ self.assertIn("non_impl", thread.selected_frame.GetFunctionName())
+
+ # Back down again.
+ self.expect("down")
+ self.assertIn("__impl", thread.selected_frame.GetFunctionName())
+ self.expect("down")
+ self.assertIn("__impl1", thread.selected_frame.GetFunctionName())
+ self.expect("down")
+ self.assertIn("__impl2", thread.selected_frame.GetFunctionName())
diff --git a/lldb/test/API/commands/frame/select-hidden/main.cpp b/lldb/test/API/commands/frame/select-hidden/main.cpp
new file mode 100644
index 0000000..dc97abb
--- /dev/null
+++ b/lldb/test/API/commands/frame/select-hidden/main.cpp
@@ -0,0 +1,13 @@
+namespace std {
+namespace __1 {
+static const char *__impl2() { return "Break here"; }
+static const char *__impl1() { return __impl2(); }
+static const char *__impl() { return __impl1(); }
+static const char *non_impl() { return __impl(); }
+} // namespace __1
+} // namespace std
+
+int main() {
+ std::__1::non_impl();
+ __builtin_debugtrap();
+}
diff --git a/lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py b/lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py
index 4d55767..5c91755 100644
--- a/lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py
+++ b/lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py
@@ -19,7 +19,7 @@ class TestFrameVarDILGlobalVariableLookup(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@skipIf(macos_version=["<", "15.0"], archs=["arm64", "arm64e"])
- @expectedFailureAll(
+ @skipIf(
dwarf_version=["<", "5"],
oslist=[lldbplatformutil.getDarwinOSTriples()],
)
diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile
new file mode 100644
index 0000000..99998b2
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py
new file mode 100644
index 0000000..53a85fe
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py
@@ -0,0 +1,46 @@
+"""
+Test DIL arithmetic.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test import lldbutil
+
+
+class TestFrameVarDILArithmetic(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_arithmetic(self):
+ self.build()
+ lldbutil.run_to_source_breakpoint(
+ self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
+ )
+
+ self.runCmd("settings set target.experimental.use-DIL true")
+
+ # Check unary results and integral promotion
+ self.expect_var_path("+0", value="0")
+ self.expect_var_path("-0", value="0")
+ self.expect_var_path("+1", value="1")
+ self.expect_var_path("-1", value="-1")
+ self.expect_var_path("-9223372036854775808", value="9223372036854775808")
+ self.expect_var_path("s", value="10", type="short")
+ self.expect_var_path("+s", value="10", type="int")
+ self.expect_var_path("-s", value="-10", type="int")
+ self.expect_var_path("+us", value="1", type="int")
+ self.expect_var_path("-us", value="-1", type="int")
+ self.expect_var_path("+ref", value="2", type="int")
+ self.expect_var_path("-ref", value="-2", type="int")
+ self.expect_var_path("+0.0", value="0")
+ self.expect_var_path("-0.0", value="-0")
+ self.expect_var_path("+enum_one", value="1")
+ self.expect_var_path("-enum_one", value="-1")
+ self.expect_var_path("+wchar", value="1")
+ self.expect_var_path("+char16", value="2")
+ self.expect_var_path("+char32", value="3")
+ self.expect_var_path("-bitfield.a", value="-1", type="int")
+ self.expect_var_path("+bitfield.a", value="1", type="int")
+ self.expect_var_path("+bitfield.b", value="2", type="int")
+ self.expect_var_path("+bitfield.c", value="3", type="unsigned int")
+ self.expect_var_path("+bitfield.d", value="4", type="uint64_t")
diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp
new file mode 100644
index 0000000..2c70e93
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp
@@ -0,0 +1,23 @@
+#include <cstdint>
+
+int main(int argc, char **argv) {
+ short s = 10;
+ unsigned short us = 1;
+
+ int x = 2;
+ int &ref = x;
+ enum Enum { kZero, kOne } enum_one = kOne;
+ wchar_t wchar = 1;
+ char16_t char16 = 2;
+ char32_t char32 = 3;
+
+ struct BitFieldStruct {
+ char a : 4;
+ int b : 32;
+ unsigned int c : 32;
+ uint64_t d : 48;
+ };
+ BitFieldStruct bitfield = {1, 2, 3, 4};
+
+ return 0; // Set a breakpoint here
+}
diff --git a/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/Makefile b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/Makefile
new file mode 100644
index 0000000..99998b2
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/TestFrameVarDILExprPointerArithmetic.py b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/TestFrameVarDILExprPointerArithmetic.py
new file mode 100644
index 0000000..448cd5b
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/TestFrameVarDILExprPointerArithmetic.py
@@ -0,0 +1,29 @@
+"""
+Test DIL pointer arithmetic.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test import lldbutil
+
+
+class TestFrameVarDILExprPointerArithmetic(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_pointer_arithmetic(self):
+ self.build()
+ lldbutil.run_to_source_breakpoint(
+ self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
+ )
+
+ self.runCmd("settings set target.experimental.use-DIL true")
+
+ self.expect_var_path("+array", type="int *")
+ self.expect_var_path("+array_ref", type="int *")
+ self.expect_var_path("+p_int0", type="int *")
+ self.expect(
+ "frame var -- '-p_int0'",
+ error=True,
+ substrs=["invalid argument type 'int *' to unary expression"],
+ )
diff --git a/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/main.cpp b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/main.cpp
new file mode 100644
index 0000000..b4e0e88
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/main.cpp
@@ -0,0 +1,11 @@
+void stop() {}
+
+int main(int argc, char **argv) {
+ int array[10];
+ array[0] = 0;
+ int (&array_ref)[10] = array;
+ int *p_int0 = &array[0];
+
+ stop(); // Set a breakpoint here
+ return 0;
+}
diff --git a/lldb/test/API/commands/target/auto-install-main-executable/Makefile b/lldb/test/API/commands/target/auto-install-main-executable/Makefile
index 07e6c9a..d0578fb 100644
--- a/lldb/test/API/commands/target/auto-install-main-executable/Makefile
+++ b/lldb/test/API/commands/target/auto-install-main-executable/Makefile
@@ -6,4 +6,4 @@ a.out: a.device.out
include Makefile.rules
a.device.out:
- $(CXX) $(CXXFLAGS) -DBUILD=74 -o $@ $(SRCDIR)/main.cpp
+ $(CXX) $(ASAN_LDFLAGS) $(CXXFLAGS) -DBUILD=74 -o $@ $(SRCDIR)/main.cpp
diff --git a/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py b/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py
index 954cac1..8e91781 100644
--- a/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py
+++ b/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py
@@ -48,6 +48,39 @@ class TestStopHooks(TestBase):
"Got the right error",
)
+ def test_self_deleting(self):
+ """Test that we can handle a stop hook that deletes itself"""
+ self.script_setup()
+ # Run to the first breakpoint before setting the stop hook
+ # so we don't have to figure out where it showed up in the new
+ # target.
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "Stop here first", self.main_source_file
+ )
+
+ # Now add our stop hook and register it:
+ result = lldb.SBCommandReturnObject()
+ command = "target stop-hook add -P stop_hook.self_deleting_stop"
+ self.interp.HandleCommand(command, result)
+ self.assertCommandReturn(result, f"Added my stop hook: {result.GetError()}")
+
+ result_str = result.GetOutput()
+ p = re.compile("Stop hook #([0-9]+) added.")
+ m = p.match(result_str)
+ current_stop_hook_id = m.group(1)
+ command = "command script add -o -f stop_hook.handle_stop_hook_id handle_id"
+ self.interp.HandleCommand(command, result)
+ self.assertCommandReturn(result, "Added my command")
+
+ command = f"handle_id {current_stop_hook_id}"
+ self.interp.HandleCommand(command, result)
+ self.assertCommandReturn(result, "Registered my stop ID")
+
+ # Now step the process and make sure the stop hook was deleted.
+ thread.StepOver()
+ self.interp.HandleCommand("target stop-hook list", result)
+ self.assertEqual(result.GetOutput().rstrip(), "No stop hooks.", "Deleted hook")
+
def test_stop_hooks_scripted(self):
"""Test that a scripted stop hook works with no specifiers"""
self.stop_hooks_scripted(5, "-I false")
diff --git a/lldb/test/API/commands/target/stop-hooks/stop_hook.py b/lldb/test/API/commands/target/stop-hooks/stop_hook.py
index cb7a433..a41190ba 100644
--- a/lldb/test/API/commands/target/stop-hooks/stop_hook.py
+++ b/lldb/test/API/commands/target/stop-hooks/stop_hook.py
@@ -48,3 +48,28 @@ class bad_handle_stop:
class no_handle_stop:
def __init__(self, target, extra_args, dict):
print("I am okay")
+
+
+class self_deleting_stop:
+ def __init__(self, target, extra_args, dict):
+ self.target = target
+
+ def handle_stop(self, exe_ctx, stream):
+ interp = exe_ctx.target.debugger.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+ interp.HandleCommand("handle_id", result)
+ id_str = result.GetOutput().rstrip()
+
+ command = f"target stop-hook delete {id_str}"
+ interp.HandleCommand(command, result)
+
+
+stop_hook_id = 0
+
+
+def handle_stop_hook_id(debugger, command, exe_ctx, result, extra_args):
+ global stop_hook_id
+ if command == "":
+ result.AppendMessage(str(stop_hook_id))
+ else:
+ stop_hook_id = int(command)
diff --git a/lldb/test/API/functionalities/abbreviation/TestAbbreviations.py b/lldb/test/API/functionalities/abbreviation/TestAbbreviations.py
index cc767ed..5dd4f6b 100644
--- a/lldb/test/API/functionalities/abbreviation/TestAbbreviations.py
+++ b/lldb/test/API/functionalities/abbreviation/TestAbbreviations.py
@@ -41,7 +41,7 @@ class AbbreviationsTestCase(TestBase):
# "pl" could be "platform" or "plugin".
command_interpreter.ResolveCommand("pl", result)
self.assertFalse(result.Succeeded())
- self.assertTrue(result.GetError().startswith("Ambiguous command"))
+ self.assertTrue(result.GetError().startswith("error: Ambiguous command"))
# Make sure an unabbreviated command is not mangled.
command_interpreter.ResolveCommand(
diff --git a/lldb/test/API/functionalities/ambigous_commands/TestAmbiguousCommands.py b/lldb/test/API/functionalities/ambigous_commands/TestAmbiguousCommands.py
index 14c66fe..31b67d7 100644
--- a/lldb/test/API/functionalities/ambigous_commands/TestAmbiguousCommands.py
+++ b/lldb/test/API/functionalities/ambigous_commands/TestAmbiguousCommands.py
@@ -24,7 +24,7 @@ class AmbiguousCommandTestCase(TestBase):
self.assertFalse(result.Succeeded())
self.assertEqual(
result.GetError(),
- "Ambiguous command 'co'. Possible matches:\n\tcommand\n\tcontinue\n\tcorefile\n",
+ "error: Ambiguous command 'co'. Possible matches:\n\tcommand\n\tcontinue\n\tcorefile\n",
)
command_interpreter.HandleCommand("command unalias continue", result)
diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py b/lldb/test/API/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
index 5798c8f..1f57181 100644
--- a/lldb/test/API/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
+++ b/lldb/test/API/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
@@ -27,6 +27,25 @@ class BreakpointByLineAndColumnTestCase(TestBase):
in_then |= b_loc.GetColumn() == 50
self.assertTrue(in_then)
+ def testBreakpointByLineAndColumnUsingCLI(self):
+ self.build()
+ src_file = lldb.SBFileSpec("main.cpp")
+ line = (
+ line_number("main.cpp", "At the beginning of a function name (col:50)") + 1
+ ) # Next line after comment
+ target, process, _, _ = lldbutil.run_to_source_breakpoint(self, "This is a random comment", src_file)
+ bkpt_no = lldbutil.run_break_set_by_file_and_line(self, "main.cpp", line, "--column 50")
+ breakpoint = target.FindBreakpointByID(bkpt_no)
+ threads = lldbutil.continue_to_breakpoint(process, breakpoint)
+ self.assertEqual(len(threads), 1, "Stopped at our breakpoint")
+ self.expect("fr v did_call", substrs=["1"])
+ in_then = False
+ for i in range(breakpoint.GetNumLocations()):
+ b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry()
+ self.assertEqual(b_loc.GetLine(), line)
+ in_then |= b_loc.GetColumn() == 50
+ self.assertTrue(in_then)
+
## Skip gcc version less 7.1 since it doesn't support -gcolumn-info
@skipIf(compiler="gcc", compiler_version=["<", "7.1"])
def testBreakpointByLine(self):
diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/after_rebuild/TestLocationsAfterRebuild.py b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/after_rebuild/TestLocationsAfterRebuild.py
index 1c7bb53..bc53fea 100644
--- a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/after_rebuild/TestLocationsAfterRebuild.py
+++ b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/after_rebuild/TestLocationsAfterRebuild.py
@@ -54,6 +54,24 @@ class TestLocationsAfterRebuild(TestBase):
self, target, bkpt
)
+ # After enabling locate_module callback for main executables,
+ # the number of locations may vary depending on the platform.
+ num_locs = bkpt.GetNumLocations()
bkpt_id = bkpt.GetID()
- loc_string = f"{bkpt_id}.3"
- self.runCmd(f"break disable {loc_string}")
+
+ self.assertGreater(
+ num_locs,
+ 0,
+ f"Expected at least one breakpoint location, but found {num_locs}",
+ )
+
+ # Iterate through all valid locations and verify we can disable each one.
+ # This tests that breakpoint location IDs remain valid after rebuilds.
+ for loc_idx in range(num_locs):
+ loc = bkpt.GetLocationAtIndex(loc_idx)
+ self.assertTrue(loc.IsValid(), f"Location at index {loc_idx} is not valid")
+
+ # Get the actual location ID from the location object
+ loc_id = loc.GetID()
+ loc_string = f"{bkpt_id}.{loc_id}"
+ self.runCmd(f"break disable {loc_string}")
diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py
index ccbb235..acf75df 100644
--- a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py
+++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py
@@ -7,13 +7,7 @@ from functionalities.breakpoint.hardware_breakpoints.base import *
class SimpleHWBreakpointTest(HardwareBreakpointTestBase):
- def does_not_support_hw_breakpoints(self):
- # FIXME: Use HardwareBreakpointTestBase.supports_hw_breakpoints
- if super().supports_hw_breakpoints() is None:
- return "Hardware breakpoints are unsupported"
- return None
-
- @skipTestIfFn(does_not_support_hw_breakpoints)
+ @skipTestIfFn(HardwareBreakpointTestBase.hw_breakpoints_unsupported)
def test(self):
"""Test SBBreakpoint::SetIsHardware"""
self.build()
@@ -35,16 +29,13 @@ class SimpleHWBreakpointTest(HardwareBreakpointTestBase):
# breakpoint will be marked as a hardware breakpoint.
self.assertTrue(break_on_me_bp.IsHardware())
- if super().supports_hw_breakpoints():
- self.assertSuccess(error)
-
- # Continue to our Hardware breakpoint and verify that's the reason
- # we're stopped.
- process.Continue()
- self.expect(
- "thread list",
- STOPPED_DUE_TO_BREAKPOINT,
- substrs=["stopped", "stop reason = breakpoint"],
- )
- else:
- self.assertFailure(error)
+ self.assertSuccess(error)
+
+ # Continue to our Hardware breakpoint and verify that's the reason
+ # we're stopped.
+ process.Continue()
+ self.expect(
+ "thread list",
+ STOPPED_DUE_TO_BREAKPOINT,
+ substrs=["stopped", "stop reason = breakpoint"],
+ )
diff --git a/lldb/test/API/functionalities/breakpoint/serialize/TestBreakpointSerialization.py b/lldb/test/API/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
index 411ce9c..55cc12e 100644
--- a/lldb/test/API/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
+++ b/lldb/test/API/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
@@ -210,6 +210,11 @@ class BreakpointSerialization(TestBase):
"Source and dest breakpoints are not identical: \nsource: %s\ndest: %s"
% (source_text, copy_text),
)
+ self.assertEqual(
+ source_bp.GetNumLocations(),
+ copy_bp.GetNumLocations(),
+ "Source and dest num locations are not the same",
+ )
def do_check_resolvers(self):
"""Use Python APIs to check serialization of breakpoint resolvers"""
@@ -386,7 +391,7 @@ class BreakpointSerialization(TestBase):
source_bps.Clear()
bkpt = self.orig_target.BreakpointCreateByName(
- "blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list
+ "main", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list
)
bkpt.SetIgnoreCount(10)
bkpt.SetThreadName("grubby")
@@ -394,7 +399,7 @@ class BreakpointSerialization(TestBase):
all_bps.Append(bkpt)
bkpt = self.orig_target.BreakpointCreateByName(
- "blubby", lldb.eFunctionNameTypeFull, empty_module_list, empty_cu_list
+ "main", lldb.eFunctionNameTypeFull, empty_module_list, empty_cu_list
)
bkpt.SetCondition("something != something_else")
bkpt.SetQueueName("grubby")
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterGenericForwardList.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterGenericForwardList.py
index 45695c4..1db0c48 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterGenericForwardList.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/forward_list/TestDataFormatterGenericForwardList.py
@@ -9,6 +9,8 @@ from lldbsuite.test import lldbutil
class TestDataFormatterGenericForwardList(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
TestBase.setUp(self)
self.line = line_number("main.cpp", "// break here")
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/TestDataFormatterStdInitializerList.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/TestDataFormatterStdInitializerList.py
index 133f8f7d..38d8cdb 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/TestDataFormatterStdInitializerList.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/TestDataFormatterStdInitializerList.py
@@ -28,13 +28,25 @@ class InitializerListTestCase(TestBase):
substrs=["stopped", "stop reason = breakpoint"],
)
- self.expect("frame variable ili", substrs=["[1] = 2", "[4] = 5"])
+ self.expect(
+ "frame variable ili",
+ substrs=["ili = size=5", "[0] = 1", "[1] = 2", "[4] = 5"],
+ )
self.expect(
"frame variable ils",
- substrs=['[4] = "surprise it is a long string!! yay!!"'],
+ substrs=[
+ "ils = size=5",
+ '[0] = "1"',
+ '[4] = "surprise it is a long string!! yay!!"',
+ ],
)
@add_test_categories(["libc++"])
def test_libcxx(self):
self.build(dictionary={"USE_LIBCPP": 1})
self.do_test()
+
+ @add_test_categories(["libstdcxx"])
+ def test_libstdcpp(self):
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/main.cpp
index a9d159e..7c62cac 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/initializer_list/main.cpp
@@ -1,6 +1,5 @@
#include <initializer_list>
#include <string>
-#include <vector>
int main() {
std::initializer_list<int> ili{1, 2, 3, 4, 5};
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py
index c0207e6..fbd0211 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py
@@ -10,6 +10,8 @@ from lldbsuite.test import lldbutil
class GenericListDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/loop/TestDataFormatterGenericListLoop.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/loop/TestDataFormatterGenericListLoop.py
index f6174dd..9c5daf7 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/loop/TestDataFormatterGenericListLoop.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/list/loop/TestDataFormatterGenericListLoop.py
@@ -11,6 +11,7 @@ from lldbsuite.test import lldbutil
class GenericListDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
NO_DEBUG_INFO_TESTCASE = True
def do_test_with_run_command(self):
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py
index 07d6c96..ca2d2d6 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py
@@ -9,6 +9,8 @@ from lldbsuite.test import lldbutil
class StdMapDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
TestBase.setUp(self)
ns = "ndk" if lldbplatformutil.target_is_android() else ""
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py
index 7ac7971..4b0854b 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py
@@ -11,6 +11,8 @@ from lldbsuite.test import lldbutil
class GenericMultiMapDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
TestBase.setUp(self)
self.namespace = "std"
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py
index 7e922fc..e846e07 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py
@@ -10,6 +10,8 @@ from lldbsuite.test import lldbutil
class GenericMultiSetDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
TestBase.setUp(self)
self.namespace = "std"
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py
index 7bb4f75..c88e83b 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py
@@ -5,6 +5,8 @@ from lldbsuite.test import lldbutil
class GenericOptionalDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def do_test_with_run_command(self):
"""Test that that file and class static variables display correctly."""
@@ -55,7 +57,11 @@ class GenericOptionalDataFormatterTestCase(TestBase):
self.expect(
"frame var numbers",
substrs=[
- "(optional_int_vect) numbers = Has Value=true {",
+ (
+ "(std::optional<std::vector<int, std::allocator<int>>>) numbers = Has Value=true {"
+ if self.getDebugInfo() == "pdb"
+ else "(optional_int_vect) numbers = Has Value=true {"
+ ),
"Value = size=4 {",
"[0] = 1",
"[1] = 2",
@@ -69,7 +75,11 @@ class GenericOptionalDataFormatterTestCase(TestBase):
self.expect(
"frame var ostring",
substrs=[
- "(optional_string) ostring = Has Value=true {",
+ (
+ "(std::optional<std::basic_string<char, std::char_traits<char>, std::allocator<char>>>) ostring = Has Value=true {"
+ if self.getDebugInfo() == "pdb"
+ else "(optional_string) ostring = Has Value=true {"
+ ),
'Value = "hello"',
"}",
],
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py
index 1ac5e32..355f0c6 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py
@@ -10,6 +10,8 @@ from lldbsuite.test import lldbutil
class GenericSetDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
TestBase.setUp(self)
self.namespace = "std"
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/shared_ptr/TestDataFormatterStdSharedPtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/shared_ptr/TestDataFormatterStdSharedPtr.py
index d71fbf8..fa03fc1 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/shared_ptr/TestDataFormatterStdSharedPtr.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/shared_ptr/TestDataFormatterStdSharedPtr.py
@@ -9,6 +9,8 @@ from lldbsuite.test import lldbutil
class TestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def do_test(self):
"""Test `frame variable` output for `std::shared_ptr` types."""
(_, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
@@ -62,7 +64,7 @@ class TestCase(TestBase):
valobj = self.expect_var_path("sp_user", type="std::shared_ptr<User>")
self.assertRegex(
valobj.summary,
- "element_type @ 0x0*[1-9a-f][0-9a-f]+( strong=1)? weak=0",
+ f"{'User' if self.getDebugInfo() == 'pdb' else 'element_type'} @ 0x0*[1-9a-f][0-9a-f]+( strong=1)? weak=0",
)
self.assertNotEqual(valobj.child[0].unsigned, 0)
@@ -77,7 +79,15 @@ class TestCase(TestBase):
self.assertEqual(str(valobj), '(User) *pointer = (id = 30, name = "steph")')
self.expect_var_path("sp_user->id", type="int", value="30")
- self.expect_var_path("sp_user->name", type="std::string", summary='"steph"')
+ self.expect_var_path(
+ "sp_user->name",
+ type=(
+ "std::basic_string<char, std::char_traits<char>, std::allocator<char>>"
+ if self.getDebugInfo() == "pdb"
+ else "std::string"
+ ),
+ summary='"steph"',
+ )
valobj = self.expect_var_path(
"si", type="std::shared_ptr<int>", summary="47 strong=2 weak=0"
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/span/TestDataFormatterStdSpan.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/span/TestDataFormatterStdSpan.py
index a45c0ff..f586fb3 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/span/TestDataFormatterStdSpan.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/span/TestDataFormatterStdSpan.py
@@ -74,7 +74,7 @@ class StdSpanDataFormatterTestCase(TestBase):
result_summary="item 0 is 1",
)
- self.runCmd("type summary delete span")
+ self.runCmd("type summary clear")
# New span with strings
lldbutil.continue_to_breakpoint(process, bkpt)
@@ -155,12 +155,6 @@ class StdSpanDataFormatterTestCase(TestBase):
)
self.check_size("nested", 2)
- @skipIf(compiler="clang", compiler_version=["<", "11.0"])
- @add_test_categories(["libc++"])
- def test_libcxx(self):
- self.build(dictionary={"USE_LIBCPP": 1})
- self.do_test()
-
def do_test_ref_and_ptr(self):
"""Test that std::span is correctly formatted when passed by ref and ptr"""
(self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
@@ -176,6 +170,24 @@ class StdSpanDataFormatterTestCase(TestBase):
@skipIf(compiler="clang", compiler_version=["<", "11.0"])
@add_test_categories(["libc++"])
+ def test_libcxx(self):
+ self.build(dictionary={"USE_LIBCPP": 1})
+ self.do_test()
+
+ @skipIf(compiler="clang", compiler_version=["<", "11.0"])
+ @add_test_categories(["libc++"])
def test_ref_and_ptr_libcxx(self):
self.build(dictionary={"USE_LIBCPP": 1})
self.do_test_ref_and_ptr()
+
+ @skipIf(compiler="clang", compiler_version=["<", "11.0"])
+ @add_test_categories(["libstdcxx"])
+ def test_libstdcxx(self):
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test()
+
+ @skipIf(compiler="clang", compiler_version=["<", "11.0"])
+ @add_test_categories(["libstdcxx"])
+ def test_ref_and_ptr_libstdcxx(self):
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test_ref_and_ptr()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
index 6a27b5d..00047e41 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
@@ -11,6 +11,8 @@ from lldbsuite.test import lldbutil
class StdStringDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
@@ -18,6 +20,17 @@ class StdStringDataFormatterTestCase(TestBase):
self.main_spec = lldb.SBFileSpec("main.cpp")
self.namespace = "std"
+ def _makeStringName(self, typedef: str, char_type: str, allocator=None):
+ if allocator is None:
+ allocator = self.namespace + "::allocator"
+
+ if self.getDebugInfo() == "pdb":
+ return f"{self.namespace}::basic_string<{char_type}, std::char_traits<{char_type}>, {allocator}<{char_type}>>"
+
+ if typedef.startswith("::"):
+ return self.namespace + typedef
+ return typedef
+
def do_test(self):
"""Test that that file and class static variables display correctly."""
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
@@ -36,10 +49,17 @@ class StdStringDataFormatterTestCase(TestBase):
# Execute the cleanup function during test case tear down.
self.addTearDownHook(cleanup)
- ns = self.namespace
+ string_name = self._makeStringName("::string", "char")
+ wstring_name = self._makeStringName("::wstring", "wchar_t")
+ custom_string_name = self._makeStringName(
+ "CustomString", "char", allocator="CustomAlloc"
+ )
+ custom_wstring_name = self._makeStringName(
+ "CustomWString", "wchar_t", allocator="CustomAlloc"
+ )
# Check 'S' pre-assignment.
- self.expect("frame variable S", substrs=['(%s::wstring) S = L"!!!!"' % ns])
+ self.expect("frame variable S", substrs=[f'({wstring_name}) S = L"!!!!"'])
thread.StepOver()
@@ -54,34 +74,31 @@ class StdStringDataFormatterTestCase(TestBase):
)
self.expect_expr(
- "s", result_type=ns + "::wstring", result_summary='L"hello world! מזל טוב!"'
+ "s", result_type=wstring_name, result_summary='L"hello world! מזל טוב!"'
)
- self.expect_expr(
- "q", result_type=ns + "::string", result_summary='"hello world"'
- )
+ self.expect_expr("q", result_type=string_name, result_summary='"hello world"')
self.expect_expr(
"Q",
- result_type=ns + "::string",
+ result_type=string_name,
result_summary='"quite a long std::strin with lots of info inside it"',
)
self.expect(
"frame variable",
substrs=[
- '(%s::wstring) wempty = L""' % ns,
- '(%s::wstring) s = L"hello world! מזל טוב!"' % ns,
- '(%s::wstring) S = L"!!!!!"' % ns,
+ f'({wstring_name}) wempty = L""',
+ f'({wstring_name}) s = L"hello world! מזל טוב!"',
+ f'({wstring_name}) S = L"!!!!!"',
"(const wchar_t *) mazeltov = 0x",
'L"מזל טוב"',
- '(%s::string) empty = ""' % ns,
- '(%s::string) q = "hello world"' % ns,
- '(%s::string) Q = "quite a long std::strin with lots of info inside it"'
- % ns,
- "(%s::string *) null_str = nullptr" % ns,
- '(CustomString) custom_str = "hello!"',
- '(CustomWString) custom_wstr = L"hello!"',
+ f'({string_name}) empty = ""',
+ f'({string_name}) q = "hello world"',
+ f'({string_name}) Q = "quite a long std::strin with lots of info inside it"',
+ f"({string_name} *) null_str = nullptr",
+ f'({custom_string_name}) custom_str = "hello!"',
+ f'({custom_wstring_name}) custom_wstr = L"hello!"',
],
)
@@ -136,19 +153,26 @@ class StdStringDataFormatterTestCase(TestBase):
self, "Set break point at this line.", self.main_spec
)
- ns = self.namespace
+ u16string_name = self._makeStringName("::u16string", "char16_t")
+ u32string_name = self._makeStringName("::u32string", "char32_t")
+ custom_u16string_name = self._makeStringName(
+ "CustomStringU16", "char16_t", allocator="CustomAlloc"
+ )
+ custom_u32string_name = self._makeStringName(
+ "CustomStringU32", "char32_t", allocator="CustomAlloc"
+ )
self.expect(
"frame variable",
substrs=[
- '(%s::u16string) u16_string = u"ß水氶"' % ns,
- '(%s::u16string) u16_empty = u""' % ns,
- '(%s::u32string) u32_string = U"🍄🍅🍆🍌"' % ns,
- '(%s::u32string) u32_empty = U""' % ns,
- '(CustomStringU16) custom_u16 = u"ß水氶"',
- '(CustomStringU16) custom_u16_empty = u""',
- '(CustomStringU32) custom_u32 = U"🍄🍅🍆🍌"',
- '(CustomStringU32) custom_u32_empty = U""',
+ f'({u16string_name}) u16_string = u"ß水氶"',
+ f'({u16string_name}) u16_empty = u""',
+ f'({u32string_name}) u32_string = U"🍄🍅🍆🍌"',
+ f'({u32string_name}) u32_empty = U""',
+ f'({custom_u16string_name}) custom_u16 = u"ß水氶"',
+ f'({custom_u16string_name}) custom_u16_empty = u""',
+ f'({custom_u32string_name}) custom_u32 = U"🍄🍅🍆🍌"',
+ f'({custom_u32string_name}) custom_u32_empty = U""',
],
)
@@ -271,9 +295,8 @@ class StdStringDataFormatterTestCase(TestBase):
self.expect(
"frame variable",
substrs=[
- '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"' % ns,
- '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'
- % ns,
+ f'({self._makeStringName("::string", "char")}) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"',
+ f'({self._makeStringName("::wstring", "wchar_t")}) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"',
],
)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py
index 1811418..5c915b6 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py
@@ -11,6 +11,8 @@ from lldbsuite.test import lldbutil
class StdStringViewDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
@@ -20,6 +22,12 @@ class StdStringViewDataFormatterTestCase(TestBase):
"main.cpp", "// Break here to look at bad string view."
)
+ def _makeStringName(self, typedef: str, char_type: str):
+ if self.getDebugInfo() == "pdb":
+ return f"std::basic_string_view<{char_type}, std::char_traits<{char_type}>>"
+
+ return typedef
+
def do_test(self):
"""Test that that file and class static variables display correctly."""
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
@@ -51,39 +59,47 @@ class StdStringViewDataFormatterTestCase(TestBase):
# Execute the cleanup function during test case tear down.
self.addTearDownHook(cleanup)
- self.expect_var_path("wempty", type="std::wstring_view", summary='L""')
+ string_view_name = self._makeStringName("std::string_view", "char")
+ wstring_view_name = self._makeStringName("std::wstring_view", "wchar_t")
+ u16string_view_name = self._makeStringName("std::u16string_view", "char16_t")
+ u32string_view_name = self._makeStringName("std::u32string_view", "char32_t")
+ string_name = (
+ "std::basic_string<char, std::char_traits<char>, std::allocator<char>>"
+ if self.getDebugInfo() == "pdb"
+ else "std::string"
+ )
+
+ self.expect_var_path("wempty", type=wstring_view_name, summary='L""')
self.expect_var_path(
- "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"'
+ "s", type=wstring_view_name, summary='L"hello world! מזל טוב!"'
)
- self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"')
- self.expect_var_path("empty", type="std::string_view", summary='""')
- self.expect_var_path("q_source", type="std::string", summary='"hello world"')
- self.expect_var_path("q", type="std::string_view", summary='"hello world"')
+ self.expect_var_path("S", type=wstring_view_name, summary='L"!!!!"')
+ self.expect_var_path("empty", type=string_view_name, summary='""')
+ self.expect_var_path("q_source", type=string_name, summary='"hello world"')
+ self.expect_var_path("q", type=string_view_name, summary='"hello world"')
self.expect_var_path(
"Q",
- type="std::string_view",
+ type=string_view_name,
summary='"quite a long std::strin with lots of info inside it"',
)
self.expect_var_path(
- "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"'
+ "IHaveEmbeddedZeros", type=string_view_name, summary='"a\\0b\\0c\\0d"'
)
self.expect_var_path(
"IHaveEmbeddedZerosToo",
- type="std::wstring_view",
+ type=wstring_view_name,
summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"',
)
- self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"')
- self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""')
- self.expect_var_path(
- "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"'
- )
- self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""')
+ self.expect_var_path("u16_string", type=u16string_view_name, summary='u"ß水氶"')
+ self.expect_var_path("u16_empty", type=u16string_view_name, summary='u""')
+ self.expect_var_path("u32_string", type=u32string_view_name, summary='U"🍄🍅🍆🍌"')
+ self.expect_var_path("u32_empty", type=u32string_view_name, summary='U""')
# GetSummary returns None so can't be checked by expect_var_path, so we
# use the str representation instead
null_obj = self.frame().GetValueForVariablePath("null_str")
self.assertEqual(null_obj.GetSummary(), "Summary Unavailable")
- self.assertEqual(str(null_obj), "(std::string_view *) null_str = nullptr")
+ self.assertEqual(str(null_obj), f"({string_view_name} *) null_str = nullptr")
self.runCmd("n")
@@ -108,37 +124,35 @@ class StdStringViewDataFormatterTestCase(TestBase):
self.expect_expr(
"s",
- result_type="std::wstring_view",
+ result_type=wstring_view_name,
result_summary='L"hello world! מזל טוב!"',
)
- self.expect_var_path("wempty", type="std::wstring_view", summary='L""')
+ self.expect_var_path("wempty", type=wstring_view_name, summary='L""')
self.expect_var_path(
- "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"'
+ "s", type=wstring_view_name, summary='L"hello world! מזל טוב!"'
)
- self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"')
- self.expect_var_path("empty", type="std::string_view", summary='""')
- self.expect_var_path("q_source", type="std::string", summary='"Hello world"')
- self.expect_var_path("q", type="std::string_view", summary='"Hello world"')
+ self.expect_var_path("S", type=wstring_view_name, summary='L"!!!!"')
+ self.expect_var_path("empty", type=string_view_name, summary='""')
+ self.expect_var_path("q_source", type=string_name, summary='"Hello world"')
+ self.expect_var_path("q", type=string_view_name, summary='"Hello world"')
self.expect_var_path(
"Q",
- type="std::string_view",
+ type=string_view_name,
summary='"quite a long std::strin with lots of info inside it"',
)
self.expect_var_path(
- "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"'
+ "IHaveEmbeddedZeros", type=string_view_name, summary='"a\\0b\\0c\\0d"'
)
self.expect_var_path(
"IHaveEmbeddedZerosToo",
- type="std::wstring_view",
+ type=wstring_view_name,
summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"',
)
- self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"')
- self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""')
- self.expect_var_path(
- "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"'
- )
- self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""')
+ self.expect_var_path("u16_string", type=u16string_view_name, summary='u"ß水氶"')
+ self.expect_var_path("u16_empty", type=u16string_view_name, summary='u""')
+ self.expect_var_path("u32_string", type=u32string_view_name, summary='U"🍄🍅🍆🍌"')
+ self.expect_var_path("u32_empty", type=u32string_view_name, summary='U""')
self.runCmd("cont")
self.expect(
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/tuple/TestDataFormatterStdTuple.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/tuple/TestDataFormatterStdTuple.py
index b23d549..8984387 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/tuple/TestDataFormatterStdTuple.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/tuple/TestDataFormatterStdTuple.py
@@ -9,6 +9,8 @@ from lldbsuite.test import lldbutil
class TestDataFormatterStdTuple(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
TestBase.setUp(self)
self.line = line_number("main.cpp", "// break here")
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py
index b983ee1..dda97945f 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string/TestDataFormatterStdU8String.py
@@ -11,18 +11,26 @@ from lldbsuite.test import lldbutil
class StdU8StringDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def do_test(self):
lldbutil.run_to_source_breakpoint(
self, "Set break point at this line.", lldb.SBFileSpec("main.cpp")
)
+ string_name = (
+ "std::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t>>"
+ if self.getDebugInfo() == "pdb"
+ else "std::u8string"
+ )
+
self.expect(
"frame variable",
substrs=[
- '(std::u8string) u8_string_small = u8"🍄"',
- '(std::u8string) u8_string = u8"❤️👍📄📁😃🧑‍🌾"',
- '(std::u8string) u8_empty = u8""',
- '(std::u8string) u8_text = u8"ABCd"',
+ f'({string_name}) u8_string_small = u8"🍄"',
+ f'({string_name}) u8_string = u8"❤️👍📄📁😃🧑‍🌾"',
+ f'({string_name}) u8_empty = u8""',
+ f'({string_name}) u8_text = u8"ABCd"',
],
)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py
index 1e35a0f..6cf72d1 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py
@@ -11,18 +11,26 @@ from lldbsuite.test import lldbutil
class StdU8StringViewDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def do_test(self):
lldbutil.run_to_source_breakpoint(
self, "Set break point at this line.", lldb.SBFileSpec("main.cpp")
)
+ string_view_name = (
+ "std::basic_string_view<char8_t, std::char_traits<char8_t>>"
+ if self.getDebugInfo() == "pdb"
+ else "std::u8string_view"
+ )
+
self.expect(
"frame variable",
substrs=[
- '(std::u8string_view) u8_string_small = u8"🍄"',
- '(std::u8string_view) u8_string = u8"❤️👍📄📁😃🧑‍🌾"',
- '(std::u8string_view) u8_empty = u8""',
- '(std::u8string_view) u8_text = u8"ABCd"',
+ f'({string_view_name}) u8_string_small = u8"🍄"',
+ f'({string_view_name}) u8_string = u8"❤️👍📄📁😃🧑‍🌾"',
+ f'({string_view_name}) u8_empty = u8""',
+ f'({string_view_name}) u8_text = u8"ABCd"',
],
)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py
index 0b68b1b..1516db6 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py
@@ -9,6 +9,8 @@ from lldbsuite.test import lldbutil
class TestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def do_test(self):
"""Test `frame variable` output for `std::unique_ptr` types."""
@@ -84,7 +86,15 @@ class TestCase(TestBase):
self.assertNotEqual(valobj.child[0].unsigned, 0)
self.expect_var_path("up_user->id", type="int", value="30")
- self.expect_var_path("up_user->name", type="std::string", summary='"steph"')
+ self.expect_var_path(
+ "up_user->name",
+ type=(
+ "std::basic_string<char, std::char_traits<char>, std::allocator<char>>"
+ if self.getDebugInfo() == "pdb"
+ else "std::string"
+ ),
+ summary='"steph"',
+ )
self.runCmd("settings set target.experimental.use-DIL true")
self.expect_var_path("ptr_node->value", value="1")
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py
index dd142d2..f74092c 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/vbool/TestDataFormatterStdVBool.py
@@ -9,6 +9,8 @@ from lldbsuite.test import lldbutil
class StdVBoolDataFormatterTestCase(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/invalid-string/TestDataFormatterLibcxxInvalidString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/invalid-string/TestDataFormatterLibcxxInvalidString.py
index ae8e0ac..b504c01 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/invalid-string/TestDataFormatterLibcxxInvalidString.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/invalid-string/TestDataFormatterLibcxxInvalidString.py
@@ -20,7 +20,7 @@ class LibcxxInvalidStringDataFormatterTestCase(TestBase):
frame = thread.frames[0]
if not self.process().GetAddressByteSize() == 8:
- self.skip()
+ self.skipTest("The test requires a 64-bit process")
# The test assumes that std::string is in its cap-size-data layout.
self.expect(
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestConnectRemoteDetach.py b/lldb/test/API/functionalities/gdb_remote_client/TestConnectRemoteDetach.py
new file mode 100644
index 0000000..4380455
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestConnectRemoteDetach.py
@@ -0,0 +1,67 @@
+"""
+Test that ConnectRemote sets ShouldDetach flag correctly.
+
+When connecting to a remote process that stops after connection,
+the process should be marked for detach (not kill) on destruction.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test.gdbclientutils import *
+from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
+from lldbsuite.test import lldbutil
+
+
+class TestConnectRemoteDetach(GDBRemoteTestBase):
+ """Test that ConnectRemote properly sets ShouldDetach flag."""
+
+ class StoppedResponder(MockGDBServerResponder):
+ """A responder that returns a stopped process."""
+
+ def qfThreadInfo(self):
+ return "m1"
+
+ def qsThreadInfo(self):
+ return "l"
+
+ def qC(self):
+ return "QC1"
+
+ def haltReason(self):
+ # Return that we're stopped
+ return "T05thread:1;"
+
+ def cont(self):
+ # Stay stopped
+ return "T05thread:1;"
+
+ def D(self):
+ # Detach packet: this is what we want to verify gets called.
+ return "OK"
+
+ def k(self):
+ # Kill packet: this is what we want to verify doesn't get called.
+ raise RuntimeError("should not receive k(ill) packet")
+
+ def test_connect_remote_sets_detach(self):
+ """Test that ConnectRemote to a stopped process sets ShouldDetach."""
+ self.server.responder = self.StoppedResponder()
+
+ target = self.createTarget("a.yaml")
+ process = self.connect(target)
+
+ # Wait for the process to be in stopped state after connecting.
+ # When ConnectRemote connects to a remote process that is stopped,
+ # it should call SetShouldDetach(true) before CompleteAttach().
+ lldbutil.expect_state_changes(
+ self, self.dbg.GetListener(), process, [lldb.eStateStopped]
+ )
+
+ # Now destroy the process. Because ShouldDetach was set to true
+ # during ConnectRemote, this should send a 'D' (detach) packet
+ # rather than a 'k' (kill) packet when the process is destroyed.
+ process.Destroy()
+
+ # Verify that the (D)etach packet was sent.
+ self.assertPacketLogReceived(["D"])
diff --git a/lldb/test/API/functionalities/scripted_frame_provider/Makefile b/lldb/test/API/functionalities/scripted_frame_provider/Makefile
new file mode 100644
index 0000000..99998b2
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_frame_provider/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py b/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
new file mode 100644
index 0000000..922cb7f
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
@@ -0,0 +1,555 @@
+"""
+Test scripted frame provider functionality.
+"""
+
+import os
+
+import lldb
+import lldbsuite.test.lldbplatformutil as lldbplatformutil
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import TestBase
+from lldbsuite.test import lldbutil
+
+@skipIf(oslist=["linux"], archs=["arm$"])
+class ScriptedFrameProviderTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.source = "main.cpp"
+
+ def test_replace_all_frames(self):
+ """Test that we can replace the entire stack."""
+ self.build()
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec(self.source), only_one_thread=False
+ )
+
+ # Import the test frame provider.
+ script_path = os.path.join(self.getSourceDir(), "test_frame_providers.py")
+ self.runCmd("command script import " + script_path)
+
+ # Attach the Replace provider.
+ error = lldb.SBError()
+ provider_id = target.RegisterScriptedFrameProvider(
+ "test_frame_providers.ReplaceFrameProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+ self.assertTrue(error.Success(), f"Failed to register provider: {error}")
+ self.assertNotEqual(provider_id, 0, "Provider ID should be non-zero")
+
+ # Verify we have exactly 3 synthetic frames.
+ self.assertEqual(thread.GetNumFrames(), 3, "Should have 3 synthetic frames")
+
+ # Verify frame indices and PCs (dictionary-based frames don't have custom function names).
+ frame0 = thread.GetFrameAtIndex(0)
+ self.assertIsNotNone(frame0)
+ self.assertEqual(frame0.GetPC(), 0x1000)
+
+ frame1 = thread.GetFrameAtIndex(1)
+ self.assertIsNotNone(frame1)
+ self.assertIn("thread_func", frame1.GetFunctionName())
+
+ frame2 = thread.GetFrameAtIndex(2)
+ self.assertIsNotNone(frame2)
+ self.assertEqual(frame2.GetPC(), 0x3000)
+
+ def test_prepend_frames(self):
+ """Test that we can add frames before real stack."""
+ self.build()
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec(self.source), only_one_thread=False
+ )
+
+ # Get original frame count and PC.
+ original_frame_count = thread.GetNumFrames()
+ self.assertGreaterEqual(
+ original_frame_count, 2, "Should have at least 2 real frames"
+ )
+
+ # Import and attach Prepend provider.
+ script_path = os.path.join(self.getSourceDir(), "test_frame_providers.py")
+ self.runCmd("command script import " + script_path)
+
+ error = lldb.SBError()
+ provider_id = target.RegisterScriptedFrameProvider(
+ "test_frame_providers.PrependFrameProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+ self.assertTrue(error.Success(), f"Failed to register provider: {error}")
+ self.assertNotEqual(provider_id, 0, "Provider ID should be non-zero")
+
+ # Verify we have 2 more frames.
+ new_frame_count = thread.GetNumFrames()
+ self.assertEqual(new_frame_count, original_frame_count + 2)
+
+ # Verify first 2 frames are synthetic (check PCs, not function names).
+ frame0 = thread.GetFrameAtIndex(0)
+ self.assertEqual(frame0.GetPC(), 0x9000)
+
+ frame1 = thread.GetFrameAtIndex(1)
+ self.assertEqual(frame1.GetPC(), 0xA000)
+
+ # Verify frame 2 is the original real frame 0.
+ frame2 = thread.GetFrameAtIndex(2)
+ self.assertIn("thread_func", frame2.GetFunctionName())
+
+ def test_append_frames(self):
+ """Test that we can add frames after real stack."""
+ self.build()
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec(self.source), only_one_thread=False
+ )
+
+ # Get original frame count.
+ original_frame_count = thread.GetNumFrames()
+
+ # Import and attach Append provider.
+ script_path = os.path.join(self.getSourceDir(), "test_frame_providers.py")
+ self.runCmd("command script import " + script_path)
+
+ error = lldb.SBError()
+ provider_id = target.RegisterScriptedFrameProvider(
+ "test_frame_providers.AppendFrameProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+ self.assertTrue(error.Success(), f"Failed to register provider: {error}")
+ self.assertNotEqual(provider_id, 0, "Provider ID should be non-zero")
+
+ # Verify we have 1 more frame.
+ new_frame_count = thread.GetNumFrames()
+ self.assertEqual(new_frame_count, original_frame_count + 1)
+
+ # Verify first frames are still real.
+ frame0 = thread.GetFrameAtIndex(0)
+ self.assertIn("thread_func", frame0.GetFunctionName())
+
+ frame_n_plus_1 = thread.GetFrameAtIndex(new_frame_count - 1)
+ self.assertEqual(frame_n_plus_1.GetPC(), 0x10)
+
+ def test_scripted_frame_objects(self):
+ """Test that provider can return ScriptedFrame objects."""
+ self.build()
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec(self.source), only_one_thread=False
+ )
+
+ # Import the provider that returns ScriptedFrame objects.
+ script_path = os.path.join(self.getSourceDir(), "test_frame_providers.py")
+ self.runCmd("command script import " + script_path)
+
+ error = lldb.SBError()
+ provider_id = target.RegisterScriptedFrameProvider(
+ "test_frame_providers.ScriptedFrameObjectProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+ self.assertTrue(error.Success(), f"Failed to register provider: {error}")
+ self.assertNotEqual(provider_id, 0, "Provider ID should be non-zero")
+
+ # Verify we have 5 frames.
+ self.assertEqual(
+ thread.GetNumFrames(), 5, "Should have 5 custom scripted frames"
+ )
+
+ # Verify frame properties from CustomScriptedFrame.
+ frame0 = thread.GetFrameAtIndex(0)
+ self.assertIsNotNone(frame0)
+ self.assertEqual(frame0.GetFunctionName(), "custom_scripted_frame_0")
+ self.assertEqual(frame0.GetPC(), 0x5000)
+ self.assertTrue(frame0.IsSynthetic(), "Frame should be marked as synthetic")
+
+ frame1 = thread.GetFrameAtIndex(1)
+ self.assertIsNotNone(frame1)
+ self.assertEqual(frame1.GetPC(), 0x6000)
+
+ frame2 = thread.GetFrameAtIndex(2)
+ self.assertIsNotNone(frame2)
+ self.assertEqual(frame2.GetFunctionName(), "custom_scripted_frame_2")
+ self.assertEqual(frame2.GetPC(), 0x7000)
+ self.assertTrue(frame2.IsSynthetic(), "Frame should be marked as synthetic")
+
+ def test_applies_to_thread(self):
+ """Test that applies_to_thread filters which threads get the provider."""
+ self.build()
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec(self.source), only_one_thread=False
+ )
+
+ # We should have at least 2 threads (worker threads) at the breakpoint.
+ num_threads = process.GetNumThreads()
+ self.assertGreaterEqual(
+ num_threads, 2, "Should have at least 2 threads at breakpoint"
+ )
+
+ # Import the test frame provider.
+ script_path = os.path.join(self.getSourceDir(), "test_frame_providers.py")
+ self.runCmd("command script import " + script_path)
+
+ # Collect original thread info before applying provider.
+ thread_info = {}
+ for i in range(num_threads):
+ t = process.GetThreadAtIndex(i)
+ thread_info[t.GetIndexID()] = {
+ "frame_count": t.GetNumFrames(),
+ "pc": t.GetFrameAtIndex(0).GetPC(),
+ }
+
+ # Register the ThreadFilterFrameProvider which only applies to thread ID 1.
+ error = lldb.SBError()
+ provider_id = target.RegisterScriptedFrameProvider(
+ "test_frame_providers.ThreadFilterFrameProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+ self.assertTrue(error.Success(), f"Failed to register provider: {error}")
+ self.assertNotEqual(provider_id, 0, "Provider ID should be non-zero")
+
+ # Check each thread.
+ thread_id_1_found = False
+ # On ARM32, FixCodeAddress clears bit 0, so synthetic PCs get modified.
+ is_arm_32bit = lldbplatformutil.getArchitecture() == "arm"
+ expected_synthetic_pc = 0xFFFE if is_arm_32bit else 0xFFFF
+
+ for i in range(num_threads):
+ t = process.GetThreadAtIndex(i)
+ thread_id = t.GetIndexID()
+
+ if thread_id == 1:
+ # Thread with ID 1 should have synthetic frame.
+ thread_id_1_found = True
+ self.assertEqual(
+ t.GetNumFrames(),
+ 1,
+ f"Thread with ID 1 should have 1 synthetic frame",
+ )
+ self.assertEqual(
+ t.GetFrameAtIndex(0).GetPC(),
+ expected_synthetic_pc,
+ f"Thread with ID 1 should have synthetic PC {expected_synthetic_pc:#x}",
+ )
+ else:
+ # Other threads should keep their original frames.
+ self.assertEqual(
+ t.GetNumFrames(),
+ thread_info[thread_id]["frame_count"],
+ f"Thread with ID {thread_id} should not be affected by provider",
+ )
+ self.assertEqual(
+ t.GetFrameAtIndex(0).GetPC(),
+ thread_info[thread_id]["pc"],
+ f"Thread with ID {thread_id} should have its original PC",
+ )
+
+ # We should have found at least one thread with ID 1.
+ self.assertTrue(
+ thread_id_1_found,
+ "Should have found a thread with ID 1 to test filtering",
+ )
+
+ def test_remove_frame_provider_by_id(self):
+ """Test that RemoveScriptedFrameProvider removes a specific provider by ID."""
+ self.build()
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec(self.source), only_one_thread=False
+ )
+
+ # Import the test frame providers.
+ script_path = os.path.join(self.getSourceDir(), "test_frame_providers.py")
+ self.runCmd("command script import " + script_path)
+
+ # Get original frame count.
+ original_frame_count = thread.GetNumFrames()
+ original_pc = thread.GetFrameAtIndex(0).GetPC()
+
+ # Register the first provider and get its ID.
+ error = lldb.SBError()
+ provider_id_1 = target.RegisterScriptedFrameProvider(
+ "test_frame_providers.ReplaceFrameProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+ self.assertTrue(error.Success(), f"Failed to register provider 1: {error}")
+
+ # Verify first provider is active (3 synthetic frames).
+ self.assertEqual(thread.GetNumFrames(), 3, "Should have 3 synthetic frames")
+ self.assertEqual(
+ thread.GetFrameAtIndex(0).GetPC(), 0x1000, "Should have first provider's PC"
+ )
+
+ # Register a second provider and get its ID.
+ provider_id_2 = target.RegisterScriptedFrameProvider(
+ "test_frame_providers.PrependFrameProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+ self.assertTrue(error.Success(), f"Failed to register provider 2: {error}")
+
+ # Verify IDs are different
+ self.assertNotEqual(
+ provider_id_1, provider_id_2, "Provider IDs should be unique"
+ )
+
+ # Now remove the first provider by ID
+ result = target.RemoveScriptedFrameProvider(provider_id_1)
+ self.assertSuccess(
+ result, f"Should successfully remove provider with ID {provider_id_1}"
+ )
+
+ # After removing the first provider, the second provider should still be
+ # active. The PrependFrameProvider adds 2 frames before the real stack.
+ # Since ReplaceFrameProvider had 3 frames, and we removed it, we should now
+ # have the original frames (from real stack) with PrependFrameProvider applied.
+ new_frame_count = thread.GetNumFrames()
+ self.assertEqual(
+ new_frame_count,
+ original_frame_count + 2,
+ "Should have original frames + 2 prepended frames",
+ )
+
+ # First two frames should be from PrependFrameProvider.
+ self.assertEqual(
+ thread.GetFrameAtIndex(0).GetPC(),
+ 0x9000,
+ "First frame should be from PrependFrameProvider",
+ )
+ self.assertEqual(
+ thread.GetFrameAtIndex(1).GetPC(),
+ 0xA000,
+ "Second frame should be from PrependFrameProvider",
+ )
+
+ # Remove the second provider.
+ result = target.RemoveScriptedFrameProvider(provider_id_2)
+ self.assertSuccess(
+ result, f"Should successfully remove provider with ID {provider_id_2}"
+ )
+
+ # After removing both providers, frames should be back to original.
+ self.assertEqual(
+ thread.GetNumFrames(),
+ original_frame_count,
+ "Should restore original frame count",
+ )
+ self.assertEqual(
+ thread.GetFrameAtIndex(0).GetPC(),
+ original_pc,
+ "Should restore original PC",
+ )
+
+ # Try to remove a provider that doesn't exist.
+ result = target.RemoveScriptedFrameProvider(999999)
+ self.assertTrue(result.Fail(), "Should fail to remove non-existent provider")
+
+ def test_circular_dependency_fix(self):
+ """Test that accessing input_frames in __init__ doesn't cause circular dependency.
+
+ This test verifies the fix for the circular dependency issue where:
+ 1. Thread::GetStackFrameList() creates the frame provider
+ 2. Provider's __init__ accesses input_frames and calls methods on frames
+ 3. SBFrame methods trigger ExecutionContextRef::GetFrameSP()
+ 4. Before the fix: GetFrameSP() would call Thread::GetStackFrameList() again -> circular dependency!
+ 5. After the fix: GetFrameSP() uses the remembered frame list -> no circular dependency
+
+ The fix works by:
+ - StackFrame stores m_frame_list_wp (weak pointer to originating list)
+ - ExecutionContextRef stores m_frame_list_wp when created from a frame
+ - ExecutionContextRef::GetFrameSP() tries the remembered list first before asking the thread
+ """
+ self.build()
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec(self.source), only_one_thread=False
+ )
+
+ # Get original frame count and PC.
+ original_frame_count = thread.GetNumFrames()
+ original_pc = thread.GetFrameAtIndex(0).GetPC()
+ self.assertGreaterEqual(
+ original_frame_count, 2, "Should have at least 2 real frames"
+ )
+
+ # Import the provider that accesses input frames in __init__.
+ script_path = os.path.join(self.getSourceDir(), "test_frame_providers.py")
+ self.runCmd("command script import " + script_path)
+
+ # Register the CircularDependencyTestProvider.
+ # Before the fix, this would crash or hang due to circular dependency.
+ error = lldb.SBError()
+ provider_id = target.RegisterScriptedFrameProvider(
+ "test_frame_providers.CircularDependencyTestProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+
+ # If we get here without crashing, the fix is working!
+ self.assertTrue(error.Success(), f"Failed to register provider: {error}")
+ self.assertNotEqual(provider_id, 0, "Provider ID should be non-zero")
+
+ # Verify the provider worked correctly,
+ # Should have 1 synthetic frame + all original frames.
+ new_frame_count = thread.GetNumFrames()
+ self.assertEqual(
+ new_frame_count,
+ original_frame_count + 1,
+ "Should have original frames + 1 synthetic frame",
+ )
+
+ # On ARM32, FixCodeAddress clears bit 0, so synthetic PCs get modified.
+ is_arm_32bit = lldbplatformutil.getArchitecture() == "arm"
+ expected_synthetic_pc = 0xDEADBEEE if is_arm_32bit else 0xDEADBEEF
+
+ # First frame should be synthetic.
+ frame0 = thread.GetFrameAtIndex(0)
+ self.assertIsNotNone(frame0)
+ self.assertEqual(
+ frame0.GetPC(),
+ expected_synthetic_pc,
+ f"First frame should be synthetic frame with PC {expected_synthetic_pc:#x}",
+ )
+
+ # Second frame should be the original first frame.
+ frame1 = thread.GetFrameAtIndex(1)
+ self.assertIsNotNone(frame1)
+ self.assertEqual(
+ frame1.GetPC(),
+ original_pc,
+ "Second frame should be original first frame",
+ )
+
+ # Verify we can still call methods on frames (no circular dependency!).
+ for i in range(min(3, new_frame_count)):
+ frame = thread.GetFrameAtIndex(i)
+ self.assertIsNotNone(frame)
+ # These calls should not trigger circular dependency.
+ pc = frame.GetPC()
+ self.assertNotEqual(pc, 0, f"Frame {i} should have valid PC")
+
+ def test_python_source_frames(self):
+ """Test that frames can point to Python source files and display properly."""
+ self.build()
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Break here", lldb.SBFileSpec(self.source), only_one_thread=False
+ )
+
+ # Get original frame count.
+ original_frame_count = thread.GetNumFrames()
+ self.assertGreaterEqual(
+ original_frame_count, 2, "Should have at least 2 real frames"
+ )
+
+ # Import the provider.
+ script_path = os.path.join(self.getSourceDir(), "test_frame_providers.py")
+ self.runCmd("command script import " + script_path)
+
+ # Register the PythonSourceFrameProvider.
+ error = lldb.SBError()
+ provider_id = target.RegisterScriptedFrameProvider(
+ "test_frame_providers.PythonSourceFrameProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+ self.assertTrue(error.Success(), f"Failed to register provider: {error}")
+ self.assertNotEqual(provider_id, 0, "Provider ID should be non-zero")
+
+ # Verify we have 3 more frames (Python frames).
+ new_frame_count = thread.GetNumFrames()
+ self.assertEqual(
+ new_frame_count,
+ original_frame_count + 3,
+ "Should have original frames + 3 Python frames",
+ )
+
+ # Verify first three frames are Python source frames.
+ frame0 = thread.GetFrameAtIndex(0)
+ self.assertIsNotNone(frame0)
+ self.assertEqual(
+ frame0.GetFunctionName(),
+ "compute_fibonacci",
+ "First frame should be compute_fibonacci",
+ )
+ self.assertTrue(frame0.IsSynthetic(), "Frame should be marked as synthetic")
+ # PC-less frames should show invalid address and not crash.
+ self.assertEqual(
+ frame0.GetPC(),
+ lldb.LLDB_INVALID_ADDRESS,
+ "PC-less frame should have LLDB_INVALID_ADDRESS",
+ )
+
+ self.assertEqual(
+ frame0.GetFP(),
+ lldb.LLDB_INVALID_ADDRESS,
+ "PC-less frame FP should return LLDB_INVALID_ADDRESS",
+ )
+ self.assertEqual(
+ frame0.GetSP(),
+ lldb.LLDB_INVALID_ADDRESS,
+ "PC-less frame SP should return LLDB_INVALID_ADDRESS",
+ )
+ self.assertEqual(
+ frame0.GetCFA(),
+ 0,
+ "PC-less frame CFA should return 0",
+ )
+
+ frame1 = thread.GetFrameAtIndex(1)
+ self.assertIsNotNone(frame1)
+ self.assertEqual(
+ frame1.GetFunctionName(),
+ "process_data",
+ "Second frame should be process_data",
+ )
+ self.assertTrue(frame1.IsSynthetic(), "Frame should be marked as synthetic")
+
+ frame2 = thread.GetFrameAtIndex(2)
+ self.assertIsNotNone(frame2)
+ self.assertEqual(frame2.GetFunctionName(), "main", "Third frame should be main")
+ self.assertTrue(frame2.IsSynthetic(), "Frame should be marked as synthetic")
+
+ # Verify line entry information is present.
+ line_entry0 = frame0.GetLineEntry()
+ self.assertTrue(line_entry0.IsValid(), "Frame 0 should have a valid line entry")
+ self.assertEqual(line_entry0.GetLine(), 7, "Frame 0 should point to line 7")
+ file_spec0 = line_entry0.GetFileSpec()
+ self.assertTrue(file_spec0.IsValid(), "Frame 0 should have valid file spec")
+ self.assertEqual(
+ file_spec0.GetFilename(),
+ "python_helper.py",
+ "Frame 0 should point to python_helper.py",
+ )
+
+ line_entry1 = frame1.GetLineEntry()
+ self.assertTrue(line_entry1.IsValid(), "Frame 1 should have a valid line entry")
+ self.assertEqual(line_entry1.GetLine(), 16, "Frame 1 should point to line 16")
+
+ line_entry2 = frame2.GetLineEntry()
+ self.assertTrue(line_entry2.IsValid(), "Frame 2 should have a valid line entry")
+ self.assertEqual(line_entry2.GetLine(), 27, "Frame 2 should point to line 27")
+
+ # Verify the frames display properly in backtrace.
+ # This tests that PC-less frames don't show 0xffffffffffffffff.
+ self.runCmd("bt")
+ output = self.res.GetOutput()
+
+ # Should show function names.
+ self.assertIn("compute_fibonacci", output)
+ self.assertIn("process_data", output)
+ self.assertIn("main", output)
+
+ # Should show Python file.
+ self.assertIn("python_helper.py", output)
+
+ # Should show line numbers.
+ self.assertIn(":7", output) # compute_fibonacci line.
+ self.assertIn(":16", output) # process_data line.
+ self.assertIn(":27", output) # main line.
+
+ # Should NOT show invalid address (0xffffffffffffffff).
+ self.assertNotIn("0xffffffffffffffff", output.lower())
+
+ # Verify frame 3 is the original real frame 0.
+ frame3 = thread.GetFrameAtIndex(3)
+ self.assertIsNotNone(frame3)
+ self.assertIn("thread_func", frame3.GetFunctionName())
diff --git a/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/Makefile b/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/Makefile
new file mode 100644
index 0000000..1049594
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/TestFrameProviderCircularDependency.py b/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/TestFrameProviderCircularDependency.py
new file mode 100644
index 0000000..b15bfb2
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/TestFrameProviderCircularDependency.py
@@ -0,0 +1,119 @@
+"""
+Test that frame providers wouldn't cause a hang due to a circular dependency
+during its initialization.
+"""
+
+import os
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import TestBase
+from lldbsuite.test import lldbutil
+
+@skipIf(oslist=["linux"], archs=["arm$"])
+class FrameProviderCircularDependencyTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.source = "main.c"
+
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
+ def test_circular_dependency_with_function_replacement(self):
+ """
+ Test the circular dependency fix with a provider that replaces function names.
+ """
+ self.build()
+
+ target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+ self.assertTrue(target, "Target should be valid")
+
+ bkpt = target.BreakpointCreateBySourceRegex(
+ "break here", lldb.SBFileSpec(self.source)
+ )
+ self.assertTrue(bkpt.IsValid(), "Breakpoint should be valid")
+ self.assertEqual(bkpt.GetNumLocations(), 1, "Should have 1 breakpoint location")
+
+ process = target.LaunchSimple(None, None, self.get_process_working_directory())
+ self.assertTrue(process, "Process should be valid")
+ self.assertEqual(
+ process.GetState(), lldb.eStateStopped, "Process should be stopped"
+ )
+
+ thread = process.GetSelectedThread()
+ self.assertTrue(thread.IsValid(), "Thread should be valid")
+
+ frame0 = thread.GetFrameAtIndex(0)
+ self.assertIn("bar", frame0.GetFunctionName(), "Should be stopped in bar()")
+
+ original_frame_count = thread.GetNumFrames()
+ self.assertGreaterEqual(
+ original_frame_count, 3, "Should have at least 3 frames: bar, foo, main"
+ )
+
+ frame_names = [thread.GetFrameAtIndex(i).GetFunctionName() for i in range(3)]
+ self.assertEqual(frame_names[0], "bar", "Frame 0 should be bar")
+ self.assertEqual(frame_names[1], "foo", "Frame 1 should be foo")
+ self.assertEqual(frame_names[2], "main", "Frame 2 should be main")
+
+ script_path = os.path.join(self.getSourceDir(), "frame_provider.py")
+ self.runCmd("command script import " + script_path)
+
+ # Register the frame provider that accesses input_frames.
+ # Before the fix, this registration would trigger the circular dependency:
+ # - Thread::GetStackFrameList() creates provider
+ # - Provider's get_frame_at_index() accesses input_frames[0]
+ # - Calls frame.GetFunctionName() -> ExecutionContextRef::GetFrameSP()
+ # - Before fix: Calls Thread::GetStackFrameList() again -> CIRCULAR!
+ # - After fix: Uses remembered m_frame_list_wp -> Works!
+ error = lldb.SBError()
+ provider_id = target.RegisterScriptedFrameProvider(
+ "frame_provider.ScriptedFrameObjectProvider",
+ lldb.SBStructuredData(),
+ error,
+ )
+
+ # If we reach here without crashing/hanging, the fix is working!
+ self.assertTrue(
+ error.Success(),
+ f"Should successfully register provider (if this fails, circular dependency!): {error}",
+ )
+ self.assertNotEqual(provider_id, 0, "Provider ID should be non-zero")
+
+ # Verify the provider is working correctly.
+ # Frame count should be unchanged (we're replacing frames, not adding).
+ new_frame_count = thread.GetNumFrames()
+ self.assertEqual(
+ new_frame_count,
+ original_frame_count,
+ "Frame count should be unchanged (replacement, not addition)",
+ )
+
+ # Verify that "bar" was replaced with "baz".
+ frame0_new = thread.GetFrameAtIndex(0)
+ self.assertIsNotNone(frame0_new, "Frame 0 should exist")
+ self.assertEqual(
+ frame0_new.GetFunctionName(),
+ "baz",
+ "Frame 0 function should be replaced: bar -> baz",
+ )
+
+ # Verify other frames are unchanged.
+ frame1_new = thread.GetFrameAtIndex(1)
+ self.assertEqual(
+ frame1_new.GetFunctionName(), "foo", "Frame 1 should still be foo"
+ )
+
+ frame2_new = thread.GetFrameAtIndex(2)
+ self.assertEqual(
+ frame2_new.GetFunctionName(), "main", "Frame 2 should still be main"
+ )
+
+ # Verify we can call methods on all frames (no circular dependency!).
+ for i in range(new_frame_count):
+ frame = thread.GetFrameAtIndex(i)
+ self.assertIsNotNone(frame, f"Frame {i} should exist")
+ # These calls should not trigger circular dependency.
+ pc = frame.GetPC()
+ self.assertNotEqual(pc, 0, f"Frame {i} should have valid PC")
+ func_name = frame.GetFunctionName()
+ self.assertIsNotNone(func_name, f"Frame {i} should have function name")
diff --git a/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/frame_provider.py b/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/frame_provider.py
new file mode 100644
index 0000000..f27f18c
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/frame_provider.py
@@ -0,0 +1,102 @@
+"""
+Frame provider that reproduces the circular dependency issue.
+
+This provider accesses input_frames and calls methods on them,
+which before the fix would cause a circular dependency.
+"""
+
+import lldb
+from lldb.plugins.scripted_process import ScriptedFrame
+from lldb.plugins.scripted_frame_provider import ScriptedFrameProvider
+
+
+class CustomScriptedFrame(ScriptedFrame):
+ """Custom scripted frame with full control over frame behavior."""
+
+ def __init__(self, thread, idx, pc, function_name):
+ args = lldb.SBStructuredData()
+ super().__init__(thread, args)
+
+ self.idx = idx
+ self.pc = pc
+ self.function_name = function_name
+
+ def get_id(self):
+ """Return the frame index."""
+ return self.idx
+
+ def get_pc(self):
+ """Return the program counter."""
+ return self.pc
+
+ def get_function_name(self):
+ """Return the function name."""
+ return self.function_name
+
+ def is_artificial(self):
+ """Mark as artificial frame."""
+ return False
+
+ def is_hidden(self):
+ """Not hidden."""
+ return False
+
+ def get_register_context(self):
+ return None
+
+
+class ScriptedFrameObjectProvider(ScriptedFrameProvider):
+ """
+ Provider that returns ScriptedFrame objects and accesses input_frames.
+
+ This provider demonstrates the circular dependency bug fix:
+ 1. During get_frame_at_index(), we access input_frames[idx]
+ 2. We call frame.GetFunctionName() and frame.GetPC() on input frames
+ 3. Before the fix: These calls would trigger ExecutionContextRef::GetFrameSP()
+ which would call Thread::GetStackFrameList() -> circular dependency!
+ 4. After the fix: ExecutionContextRef uses the remembered frame list -> no circular dependency
+ """
+
+ def __init__(self, input_frames, args):
+ super().__init__(input_frames, args)
+ self.replacement_count = 0
+ if self.target.process:
+ baz_symbol_ctx = self.target.FindFunctions("baz")
+ self.baz_symbol_ctx = None
+ if len(baz_symbol_ctx) == 1:
+ self.baz_symbol_ctx = baz_symbol_ctx[0]
+
+ @staticmethod
+ def get_description():
+ """Return a description of this provider."""
+ return "Provider that replaces 'bar' function with 'baz'"
+
+ def get_frame_at_index(self, idx):
+ """
+ Replace frames named 'bar' with custom frames named 'baz'.
+
+ This accesses input_frames and calls methods on them, which would
+ trigger the circular dependency bug before the fix.
+ """
+ if idx < len(self.input_frames):
+ # This access and method calls would cause circular dependency before fix!
+ frame = self.input_frames[idx]
+
+ # Calling GetFunctionName() triggers ExecutionContextRef resolution.
+ function_name = frame.GetFunctionName()
+
+ if function_name == "bar" and self.baz_symbol_ctx:
+ # Replace "bar" with "baz".
+ baz_func = self.baz_symbol_ctx.GetFunction()
+ new_function_name = baz_func.GetName()
+ pc = baz_func.GetStartAddress().GetLoadAddress(self.target)
+ custom_frame = CustomScriptedFrame(
+ self.thread, idx, pc, new_function_name
+ )
+ self.replacement_count += 1
+ return custom_frame
+
+ # Pass through other frames by returning their index.
+ return idx
+
+ return None
diff --git a/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/main.c b/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/main.c
new file mode 100644
index 0000000..bbd1028
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_frame_provider/circular_dependency/main.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+int baz() {
+ printf("baz\n");
+ return 666;
+}
+
+int bar() {
+ printf("bar\n");
+ return 42; // break here.
+}
+
+int foo() {
+ printf("foo\n");
+ return bar();
+}
+
+int main() {
+ printf("main\n");
+ return foo();
+}
diff --git a/lldb/test/API/functionalities/scripted_frame_provider/main.cpp b/lldb/test/API/functionalities/scripted_frame_provider/main.cpp
new file mode 100644
index 0000000..0298e88
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_frame_provider/main.cpp
@@ -0,0 +1,53 @@
+// Multi-threaded test program for testing frame providers.
+
+#include <condition_variable>
+#include <iostream>
+#include <mutex>
+#include <thread>
+
+std::mutex mtx;
+std::condition_variable cv;
+int ready_count = 0;
+constexpr int NUM_THREADS = 2;
+
+void thread_func(int thread_num) {
+ std::cout << "Thread " << thread_num << " started\n";
+
+ {
+ std::unique_lock<std::mutex> lock(mtx);
+ ready_count++;
+ if (ready_count == NUM_THREADS + 1) {
+ cv.notify_all();
+ } else {
+ cv.wait(lock, [] { return ready_count == NUM_THREADS + 1; });
+ }
+ }
+
+ std::cout << "Thread " << thread_num << " at breakpoint\n"; // Break here.
+}
+
+int main(int argc, char **argv) {
+ std::thread threads[NUM_THREADS];
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ threads[i] = std::thread(thread_func, i);
+ }
+
+ {
+ std::unique_lock<std::mutex> lock(mtx);
+ ready_count++;
+ if (ready_count == NUM_THREADS + 1) {
+ cv.notify_all();
+ } else {
+ cv.wait(lock, [] { return ready_count == NUM_THREADS + 1; });
+ }
+ }
+
+ std::cout << "Main thread at barrier\n";
+
+ for (int i = 0; i < NUM_THREADS; i++)
+ threads[i].join();
+
+ std::cout << "All threads completed\n";
+ return 0;
+}
diff --git a/lldb/test/API/functionalities/scripted_frame_provider/python_helper.py b/lldb/test/API/functionalities/scripted_frame_provider/python_helper.py
new file mode 100644
index 0000000..27f3816
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_frame_provider/python_helper.py
@@ -0,0 +1,36 @@
+"""
+Sample Python module to demonstrate Python source display in scripted frames.
+"""
+
+
+def compute_fibonacci(n):
+ """Compute the nth Fibonacci number."""
+ if n <= 1:
+ return n
+ a, b = 0, 1
+ for _ in range(n - 1):
+ a, b = b, a + b
+ return b
+
+
+def process_data(data):
+ """Process some data and return result."""
+ result = []
+ for item in data:
+ if isinstance(item, int):
+ result.append(item * 2)
+ elif isinstance(item, str):
+ result.append(item.upper())
+ return result
+
+
+def main():
+ """Main entry point for testing."""
+ fib_10 = compute_fibonacci(10)
+ data = [1, 2, "hello", 3, "world"]
+ processed = process_data(data)
+ return fib_10, processed
+
+
+if __name__ == "__main__":
+ main()
diff --git a/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py b/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
new file mode 100644
index 0000000..76f8597
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
@@ -0,0 +1,316 @@
+"""
+Test frame providers for scripted frame provider functionality.
+
+These providers demonstrate various merge strategies:
+- Replace: Replace entire stack
+- Prepend: Add frames before real stack
+- Append: Add frames after real stack
+
+It also shows the ability to mix a dictionary, a ScriptedFrame or an SBFrame
+index to create stackframes
+"""
+
+import os
+import lldb
+from lldb.plugins.scripted_process import ScriptedFrame
+from lldb.plugins.scripted_frame_provider import ScriptedFrameProvider
+
+
+class ReplaceFrameProvider(ScriptedFrameProvider):
+ """Replace entire stack with custom frames."""
+
+ def __init__(self, input_frames, args):
+ super().__init__(input_frames, args)
+ self.frames = [
+ {
+ "idx": 0,
+ "pc": 0x1000,
+ },
+ 0,
+ {
+ "idx": 2,
+ "pc": 0x3000,
+ },
+ ]
+
+ @staticmethod
+ def get_description():
+ """Return a description of this provider."""
+ return "Replace entire stack with 3 custom frames"
+
+ def get_frame_at_index(self, index):
+ if index >= len(self.frames):
+ return None
+ return self.frames[index]
+
+
+class PrependFrameProvider(ScriptedFrameProvider):
+ """Prepend synthetic frames before real stack."""
+
+ def __init__(self, input_frames, args):
+ super().__init__(input_frames, args)
+
+ @staticmethod
+ def get_description():
+ """Return a description of this provider."""
+ return "Prepend 2 synthetic frames before real stack"
+
+ def get_frame_at_index(self, index):
+ if index == 0:
+ return {"pc": 0x9000}
+ elif index == 1:
+ return {"pc": 0xA000}
+ elif index - 2 < len(self.input_frames):
+ return index - 2 # Return real frame index.
+ return None
+
+
+class AppendFrameProvider(ScriptedFrameProvider):
+ """Append synthetic frames after real stack."""
+
+ def __init__(self, input_frames, args):
+ super().__init__(input_frames, args)
+
+ @staticmethod
+ def get_description():
+ """Return a description of this provider."""
+ return "Append 1 synthetic frame after real stack"
+
+ def get_frame_at_index(self, index):
+ if index < len(self.input_frames):
+ return index # Return real frame index.
+ elif index == len(self.input_frames):
+ return {
+ "idx": 1,
+ "pc": 0x10,
+ }
+ return None
+
+
+class CustomScriptedFrame(ScriptedFrame):
+ """Custom scripted frame with full control over frame behavior."""
+
+ def __init__(self, thread, idx, pc, function_name):
+ args = lldb.SBStructuredData()
+ super().__init__(thread, args)
+
+ self.idx = idx
+ self.pc = pc
+ self.function_name = function_name
+
+ def get_id(self):
+ """Return the frame index."""
+ return self.idx
+
+ def get_pc(self):
+ """Return the program counter."""
+ return self.pc
+
+ def get_function_name(self):
+ """Return the function name."""
+ return self.function_name
+
+ def is_artificial(self):
+ """Mark as artificial frame."""
+ return False
+
+ def is_hidden(self):
+ """Not hidden."""
+ return False
+
+ def get_register_context(self):
+ """No register context for this test."""
+ return None
+
+
+class ScriptedFrameObjectProvider(ScriptedFrameProvider):
+ """Provider that returns ScriptedFrame objects instead of dictionaries."""
+
+ def __init__(self, input_frames, args):
+ super().__init__(input_frames, args)
+
+ @staticmethod
+ def get_description():
+ """Return a description of this provider."""
+ return "Provider returning custom ScriptedFrame objects"
+
+ def get_frame_at_index(self, index):
+ """Return ScriptedFrame objects or dictionaries based on index."""
+ if index == 0:
+ return CustomScriptedFrame(
+ self.thread, 0, 0x5000, "custom_scripted_frame_0"
+ )
+ elif index == 1:
+ return {"pc": 0x6000}
+ elif index == 2:
+ return CustomScriptedFrame(
+ self.thread, 2, 0x7000, "custom_scripted_frame_2"
+ )
+ elif index == 3:
+ return len(self.input_frames) - 2 # Real frame index.
+ elif index == 4:
+ return len(self.input_frames) - 1 # Real frame index.
+ return None
+
+
+class ThreadFilterFrameProvider(ScriptedFrameProvider):
+ """Provider that only applies to thread with ID 1."""
+
+ @staticmethod
+ def applies_to_thread(thread):
+ """Only apply to thread with index ID 1."""
+ return thread.GetIndexID() == 1
+
+ def __init__(self, input_frames, args):
+ super().__init__(input_frames, args)
+
+ @staticmethod
+ def get_description():
+ """Return a description of this provider."""
+ return "Provider that only applies to thread ID 1"
+
+ def get_frame_at_index(self, index):
+ """Return a single synthetic frame."""
+ if index == 0:
+ return {"pc": 0xFFFF}
+ return None
+
+
+class CircularDependencyTestProvider(ScriptedFrameProvider):
+ """
+ Provider that tests the circular dependency fix.
+
+ This provider accesses input_frames during __init__ and calls methods
+ on those frames. Before the fix, this would cause a circular dependency:
+ - Thread::GetStackFrameList() creates provider
+ - Provider's __init__ accesses input_frames[0]
+ - SBFrame::GetPC() tries to resolve ExecutionContextRef
+ - ExecutionContextRef::GetFrameSP() calls Thread::GetStackFrameList()
+ - Re-enters initialization -> circular dependency!
+
+ With the fix, ExecutionContextRef remembers the frame list, so it doesn't
+ re-enter Thread::GetStackFrameList().
+ """
+
+ def __init__(self, input_frames, args):
+ super().__init__(input_frames, args)
+
+ # This would cause circular dependency before the fix!
+ # Accessing frames and calling methods on them during __init__
+ self.original_frame_count = len(input_frames)
+ self.original_pcs = []
+
+ # Call GetPC() on each input frame - this triggers ExecutionContextRef resolution.
+ for i in range(min(3, len(input_frames))):
+ frame = input_frames[i]
+ if frame.IsValid():
+ pc = frame.GetPC()
+ self.original_pcs.append(pc)
+
+ @staticmethod
+ def get_description():
+ """Return a description of this provider."""
+ return "Provider that tests circular dependency fix by accessing frames in __init__"
+
+ def get_frame_at_index(self, index):
+ """Prepend a synthetic frame, then pass through original frames."""
+ if index == 0:
+ # Synthetic frame at index 0.
+ return {"pc": 0xDEADBEEF}
+ elif index - 1 < self.original_frame_count:
+ # Pass through original frames at indices 1, 2, 3, ...
+ return index - 1
+ return None
+
+
+class PythonSourceFrame(ScriptedFrame):
+ """Scripted frame that points to Python source code."""
+
+ def __init__(self, thread, idx, function_name, python_file, line_number):
+ args = lldb.SBStructuredData()
+ super().__init__(thread, args)
+
+ self.idx = idx
+ self.function_name = function_name
+ self.python_file = python_file
+ self.line_number = line_number
+
+ def get_id(self):
+ """Return the frame index."""
+ return self.idx
+
+ def get_pc(self):
+ """PC-less frame - return invalid address."""
+ return lldb.LLDB_INVALID_ADDRESS
+
+ def get_function_name(self):
+ """Return the function name."""
+ return self.function_name
+
+ def get_symbol_context(self):
+ """Return a symbol context with LineEntry pointing to Python source."""
+ # Create a LineEntry pointing to the Python source file
+ line_entry = lldb.SBLineEntry()
+ line_entry.SetFileSpec(lldb.SBFileSpec(self.python_file, True))
+ line_entry.SetLine(self.line_number)
+ line_entry.SetColumn(0)
+
+ # Create a symbol context with the line entry
+ sym_ctx = lldb.SBSymbolContext()
+ sym_ctx.SetLineEntry(line_entry)
+
+ return sym_ctx
+
+ def is_artificial(self):
+ """Not artificial."""
+ return False
+
+ def is_hidden(self):
+ """Not hidden."""
+ return False
+
+ def get_register_context(self):
+ """No register context for PC-less frames."""
+ return None
+
+
+class PythonSourceFrameProvider(ScriptedFrameProvider):
+ """
+ Provider that demonstrates Python source display in scripted frames.
+
+ This provider prepends frames pointing to Python source code, showing
+ that PC-less frames can display Python source files with proper line
+ numbers and module/compile unit information.
+ """
+
+ def __init__(self, input_frames, args):
+ super().__init__(input_frames, args)
+
+ # Find the python_helper.py file
+ current_dir = os.path.dirname(os.path.abspath(__file__))
+ self.python_file = os.path.join(current_dir, "python_helper.py")
+
+ @staticmethod
+ def get_description():
+ """Return a description of this provider."""
+ return "Provider that prepends frames pointing to Python source"
+
+ def get_frame_at_index(self, index):
+ """Return Python source frames followed by original frames."""
+ if index == 0:
+ # Frame pointing to compute_fibonacci function (line 7)
+ return PythonSourceFrame(
+ self.thread, 0, "compute_fibonacci", self.python_file, 7
+ )
+ elif index == 1:
+ # Frame pointing to process_data function (line 16)
+ return PythonSourceFrame(
+ self.thread, 1, "process_data", self.python_file, 16
+ )
+ elif index == 2:
+ # Frame pointing to main function (line 27)
+ return PythonSourceFrame(self.thread, 2, "main", self.python_file, 27)
+ elif index - 3 < len(self.input_frames):
+ # Pass through original frames
+ return index - 3
+ return None
diff --git a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
index 8352672..f676cfb 100644
--- a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
+++ b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
@@ -8,6 +8,15 @@ from lldb.plugins.scripted_process import ScriptedThread
from lldb.plugins.scripted_process import ScriptedFrame
+def my_python_function(x, y):
+ """A sample Python function to demonstrate Python source display in scripted frames."""
+ result = x + y
+ if result > 100:
+ return result * 2
+ else:
+ return result
+
+
class DummyStopHook:
def __init__(self, target, args):
self.target = target
@@ -74,6 +83,40 @@ class DummyScriptedThread(ScriptedThread):
self.frames.append(DummyScriptedFrame(self, args, len(self.frames), "bar"))
self.frames.append(DummyScriptedFrame(self, args, len(self.frames), "foo"))
+ cwd = os.path.dirname(os.path.abspath(__file__))
+
+ le = lldb.SBLineEntry()
+ le.SetFileSpec(lldb.SBFileSpec(os.path.join(cwd, "baz.cpp"), True))
+ le.SetLine(9)
+ le.SetColumn(10)
+
+ sym_ctx = lldb.SBSymbolContext()
+ sym_ctx.SetLineEntry(le)
+
+ self.frames.append(
+ DummyScriptedFrame(self, args, len(self.frames), "baz", sym_ctx)
+ )
+
+ # Add a frame with Python source
+ code = my_python_function.__code__
+ lineno = code.co_firstlineno
+ col_offset = getattr(
+ code, "co_firstcol_offset", 0
+ ) # Python ≥3.11 has column info
+ py_le = lldb.SBLineEntry()
+ py_le.SetFileSpec(lldb.SBFileSpec(__file__, True))
+ py_le.SetLine(lineno) # Line where my_python_function is defined
+ py_le.SetColumn(col_offset)
+
+ py_sym_ctx = lldb.SBSymbolContext()
+ py_sym_ctx.SetLineEntry(py_le)
+
+ self.frames.append(
+ DummyScriptedFrame(
+ self, args, len(self.frames), "my_python_function", py_sym_ctx
+ )
+ )
+
def get_thread_id(self) -> int:
return 0x19
diff --git a/lldb/test/API/functionalities/statusline/TestStatusline.py b/lldb/test/API/functionalities/statusline/TestStatusline.py
index ca376cc..4ffa864 100644
--- a/lldb/test/API/functionalities/statusline/TestStatusline.py
+++ b/lldb/test/API/functionalities/statusline/TestStatusline.py
@@ -71,8 +71,10 @@ class TestStatusline(PExpectTest):
)
self.expect('set set separator "| "')
- # Hide the statusline and check or the control character.
- self.expect("set set show-statusline false", ["\x1b[1;0r"])
+ # Hide the statusline and check for the control character.
+ self.expect(
+ "set set show-statusline false", ["\x1b[1;{}r".format(self.TERMINAL_HEIGHT)]
+ )
def test_no_color(self):
"""Basic test for the statusline with colors disabled."""
diff --git a/lldb/test/API/functionalities/thread/step_until/function.list b/lldb/test/API/functionalities/thread/step_until/function.list
index 5900fe8..d8caa20 100644
--- a/lldb/test/API/functionalities/thread/step_until/function.list
+++ b/lldb/test/API/functionalities/thread/step_until/function.list
@@ -1 +1,4 @@
-!call_me
+v1
+f call_me
+c 0
+c 1
diff --git a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile
new file mode 100644
index 0000000..4698eaa
--- /dev/null
+++ b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/Makefile
@@ -0,0 +1,6 @@
+CXX_SOURCES := main.cpp
+
+# Build with C++ exceptions enabled
+CXXFLAGS := -g -O0 -fexceptions
+
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py
new file mode 100644
index 0000000..e03234d
--- /dev/null
+++ b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/TestLibUnwindRetInjection.py
@@ -0,0 +1,177 @@
+"""
+Test that libunwind correctly injects 'ret' instructions to rebalance execution flow
+when unwinding C++ exceptions. This is important for Apple Processor Trace analysis.
+"""
+
+import lldb
+import os
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+from lldbsuite.test import configuration
+
+
+class LibunwindRetInjectionTestCase(TestBase):
+ @skipIf(archs=no_match(["arm64", "arm64e", "aarch64"]))
+ @skipUnlessDarwin
+ @skipIfOutOfTreeLibunwind
+ def test_ret_injection_on_exception_unwind(self):
+ """Test that __libunwind_Registers_arm64_jumpto receives correct walkedFrames count and injects the right number of ret instructions."""
+ self.build()
+
+ exe = self.getBuildArtifact("a.out")
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ # Find the just-built libunwind, not the system one.
+ # llvm_tools_dir is typically <build>/bin, so lib is a sibling.
+ self.assertIsNotNone(
+ configuration.llvm_tools_dir,
+ "llvm_tools_dir must be set to find in-tree libunwind",
+ )
+
+ llvm_lib_dir = os.path.join(
+ os.path.dirname(configuration.llvm_tools_dir), "lib"
+ )
+
+ # Find the libunwind library (platform-agnostic).
+ libunwind_path = None
+ for filename in os.listdir(llvm_lib_dir):
+ if filename.startswith("libunwind.") or filename.startswith("unwind."):
+ libunwind_path = os.path.join(llvm_lib_dir, filename)
+ break
+
+ self.assertIsNotNone(
+ libunwind_path, f"Could not find libunwind in {llvm_lib_dir}"
+ )
+
+ # Set breakpoint in __libunwind_Registers_arm64_jumpto.
+ # This is the function that performs the actual jump and ret injection.
+ bp = target.BreakpointCreateByName("__libunwind_Registers_arm64_jumpto")
+ self.assertTrue(bp.IsValid())
+ self.assertGreater(bp.GetNumLocations(), 0)
+
+ # Set up DYLD_INSERT_LIBRARIES to use the just-built libunwind.
+ launch_info = lldb.SBLaunchInfo(None)
+ env = target.GetEnvironment()
+ env.Set("DYLD_INSERT_LIBRARIES", libunwind_path, True)
+ launch_info.SetEnvironment(env, False)
+
+ # Launch the process with our custom libunwind.
+ error = lldb.SBError()
+ process = target.Launch(launch_info, error)
+ self.assertSuccess(
+ error, f"Failed to launch process with libunwind at {libunwind_path}"
+ )
+ self.assertTrue(process, PROCESS_IS_VALID)
+
+ # We should hit the breakpoint in __libunwind_Registers_arm64_jumpto
+ # during the exception unwinding phase 2.
+ threads = lldbutil.get_threads_stopped_at_breakpoint(process, bp)
+ self.assertEqual(len(threads), 1, "Should have stopped at breakpoint")
+
+ thread = threads[0]
+ frame = thread.GetFrameAtIndex(0)
+
+ # Verify we're in __libunwind_Registers_arm64_jumpto.
+ function_name = frame.GetFunctionName()
+ self.assertTrue(
+ "__libunwind_Registers_arm64_jumpto" in function_name,
+ f"Expected to be in __libunwind_Registers_arm64_jumpto, got {function_name}",
+ )
+
+ # On ARM64, the walkedFrames parameter should be in register x1 (second parameter).
+ # According to the ARM64 calling convention, integer arguments are passed in x0-x7.
+ # x0 = Registers_arm64* pointer.
+ # x1 = unsigned walkedFrames.
+ error = lldb.SBError()
+ x1_value = frame.register["x1"].GetValueAsUnsigned(error)
+ self.assertSuccess(error, "Failed to read x1 register")
+
+ # According to the code in UnwindCursor.hpp, the walkedFrames value represents:
+ # 1. The number of frames walked in unwind_phase2 to reach the landing pad.
+ # 2. Plus _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1 = 4 additional libunwind frames.
+ #
+ # From the comment in the code:
+ # frame #0: __libunwind_Registers_arm64_jumpto
+ # frame #1: Registers_arm64::returnto
+ # frame #2: UnwindCursor::jumpto
+ # frame #3: __unw_resume
+ # frame #4: __unw_resume_with_frames_walked
+ # frame #5: unwind_phase2
+ #
+ # Since __libunwind_Registers_arm64_jumpto returns to the landing pad,
+ # we subtract 1, so _EXTRA_LIBUNWIND_FRAMES_WALKED = 4.
+ #
+ # For our test program:
+ # - unwind_phase2 starts walking (frame 0 counted here).
+ # - Walks through: func_d (throw site), func_c, func_b, func_a.
+ # - Finds landing pad in main.
+ # That's approximately 4-5 frames from the user code.
+ # Plus the 4 extra libunwind frames.
+ #
+ # So we expect x1 to be roughly 8-10.
+ expected_min_frames = 8
+ expected_max_frames = 13 # Allow some variation for libc++abi frames.
+
+ self.assertGreaterEqual(
+ x1_value,
+ expected_min_frames,
+ f"walkedFrames (x1) should be >= {expected_min_frames}, got {x1_value}. "
+ "This is the number of 'ret' instructions that will be executed.",
+ )
+
+ self.assertLessEqual(
+ x1_value,
+ expected_max_frames,
+ f"walkedFrames (x1) should be <= {expected_max_frames}, got {x1_value}. "
+ "Value seems too high.",
+ )
+
+ # Now step through the ret injection loop and count the actual number of 'ret' executions.
+ # The loop injects exactly x1_value ret instructions before continuing with register restoration.
+ # We step until we hit the first 'ldp' instruction (register restoration starts with 'ldp x2, x3, [x0, #0x010]').
+ ret_executed_count = 0
+ max_steps = 100 # Safety limit to prevent infinite loops.
+
+ for step_count in range(max_steps):
+ # Get current instruction.
+ pc = frame.GetPC()
+ inst = process.ReadMemory(pc, 4, lldb.SBError())
+
+ # Disassemble current instruction.
+ current_inst = target.GetInstructions(lldb.SBAddress(pc, target), inst)[0]
+ mnemonic = current_inst.GetMnemonic(target)
+ operands = current_inst.GetOperands(target)
+
+ # Check if we've reached the register restoration part (first ldp after the loop).
+ if mnemonic == "ldp":
+ # We've exited the ret injection loop.
+ break
+
+ # Count 'ret' instructions that get executed.
+ if mnemonic == "ret":
+ self.assertEqual(operands, "x16")
+ ret_executed_count += 1
+
+ # Step one instruction.
+ thread.StepInstruction(False) # False = step over.
+
+ # Update frame reference.
+ frame = thread.GetFrameAtIndex(0)
+
+ # Verify we didn't hit the safety limit.
+ self.assertLess(
+ step_count,
+ max_steps - 1,
+ f"Stepped {max_steps} times without reaching 'ldp' instruction. Something is wrong.",
+ )
+
+ # The number of executed 'ret' instructions should match x1_value.
+ # According to the implementation, the loop executes exactly x1_value times.
+ self.assertEqual(
+ ret_executed_count,
+ x1_value,
+ f"Expected {x1_value} 'ret' instructions to be executed (matching x1 register), "
+ f"but counted {ret_executed_count} executed 'ret' instructions.",
+ )
diff --git a/lldb/test/API/functionalities/unwind/libunwind_ret_injection/main.cpp b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/main.cpp
new file mode 100644
index 0000000..00685e4
--- /dev/null
+++ b/lldb/test/API/functionalities/unwind/libunwind_ret_injection/main.cpp
@@ -0,0 +1,45 @@
+// Test program to verify libunwind ret injection feature for execution flow
+// rebalancing.
+//
+// This test creates a multi-frame call stack and throws a C++ exception to
+// trigger libunwind's two-phase exception handling. The test verifies that
+// libunwind correctly injects the right amount of 'ret' instructions to
+// rebalance the execution flow when returning to the landing pad, which is
+// important for Apple Processor Trace analysis.
+
+#include <cstdio>
+#include <exception>
+#include <stdexcept>
+
+// Marker functions with noinline to ensure they appear in the stack.
+static void __attribute__((noinline)) func_d() {
+ printf("In func_d, about to throw exception\n");
+ throw std::runtime_error("test exception");
+}
+
+static void __attribute__((noinline)) func_c() {
+ printf("In func_c\n");
+ func_d();
+}
+
+static void __attribute__((noinline)) func_b() {
+ printf("In func_b\n");
+ func_c();
+}
+
+static void __attribute__((noinline)) func_a() {
+ printf("In func_a\n");
+ func_b();
+}
+
+int main(int argc, char *argv[]) {
+ try {
+ printf("In main, about to call func_a\n");
+ func_a();
+ printf("ERROR: Should not reach here\n");
+ return 1;
+ } catch (const std::exception &e) {
+ printf("Caught exception in main: %s\n", e.what());
+ return 0;
+ }
+}
diff --git a/lldb/test/API/functionalities/wrong_commands/TestWrongCommands.py b/lldb/test/API/functionalities/wrong_commands/TestWrongCommands.py
index 6d2ce2b..25f95f3 100644
--- a/lldb/test/API/functionalities/wrong_commands/TestWrongCommands.py
+++ b/lldb/test/API/functionalities/wrong_commands/TestWrongCommands.py
@@ -17,7 +17,9 @@ class UnknownCommandTestCase(TestBase):
command_interpreter.HandleCommand("g", result)
self.assertFalse(result.Succeeded())
- self.assertRegex(result.GetError(), "Ambiguous command 'g'. Possible matches:")
+ self.assertRegex(
+ result.GetError(), "error: Ambiguous command 'g'. Possible matches:"
+ )
self.assertRegex(result.GetError(), "gui")
self.assertRegex(result.GetError(), "gdb-remote")
self.assertEqual(1, result.GetError().count("gdb-remote"))
diff --git a/lldb/test/API/lang/BoundsSafety/soft_trap/Makefile b/lldb/test/API/lang/BoundsSafety/soft_trap/Makefile
new file mode 100644
index 0000000..5e83e7a
--- /dev/null
+++ b/lldb/test/API/lang/BoundsSafety/soft_trap/Makefile
@@ -0,0 +1,10 @@
+# FIXME: mockSoftTrapRuntime.c shouldn't really be built with -fbounds-safety
+C_SOURCES := main.c mockSoftTrapRuntime.c
+
+soft-trap-test-minimal: CFLAGS_EXTRAS := -fbounds-safety -fbounds-safety-soft-traps=call-minimal
+soft-trap-test-minimal: all
+
+soft-trap-test-with-str: CFLAGS_EXTRAS := -fbounds-safety -fbounds-safety-soft-traps=call-with-str
+soft-trap-test-with-str: all
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/BoundsSafety/soft_trap/TestBoundsSafetyInstrumentationPlugin.py b/lldb/test/API/lang/BoundsSafety/soft_trap/TestBoundsSafetyInstrumentationPlugin.py
new file mode 100644
index 0000000..535a0bcf
--- /dev/null
+++ b/lldb/test/API/lang/BoundsSafety/soft_trap/TestBoundsSafetyInstrumentationPlugin.py
@@ -0,0 +1,148 @@
+"""
+Test the BoundsSafety instrumentation plugin
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+
+
+STOP_REASON_MAX_LEN = 100
+SOFT_TRAP_FUNC_MINIMAL = "__bounds_safety_soft_trap"
+SOFT_TRAP_FUNC_WITH_STR = "__bounds_safety_soft_trap_s"
+
+
+class BoundsSafetyTestSoftTrapPlugin(TestBase):
+ def _check_stop_reason_impl(
+ self,
+ expected_soft_trap_func: str,
+ expected_stop_reason: str,
+ expected_func_name: str,
+ expected_file_name: str,
+ expected_line_num: int,
+ ):
+ process = self.test_target.process
+ thread = process.GetSelectedThread()
+ self.assertEqual(
+ thread.GetStopReason(),
+ lldb.eStopReasonInstrumentation,
+ )
+
+ stop_reason = thread.GetStopDescription(STOP_REASON_MAX_LEN)
+ self.assertEqual(stop_reason, expected_stop_reason)
+
+ soft_trap_func_frame = thread.GetFrameAtIndex(0)
+ self.assertEqual(soft_trap_func_frame.name, expected_soft_trap_func)
+
+ stop_frame = thread.GetSelectedFrame()
+ self.assertEqual(stop_frame.name, expected_func_name)
+ # The stop frame isn't frame 1 because that frame is the artificial
+ # frame containing the trap reason.
+ self.assertEqual(stop_frame.idx, 2)
+ file_name = stop_frame.GetLineEntry().GetFileSpec().basename
+ self.assertEqual(file_name, expected_file_name)
+ line = stop_frame.GetLineEntry().line
+ self.assertEqual(line, expected_line_num)
+
+ def check_state_soft_trap_minimal(
+ self, stop_reason: str, func_name: str, file_name: str, line_num: int
+ ):
+ """
+ Check the program state is as expected when hitting
+ a soft trap from -fbounds-safety-soft-traps=call-minimal
+ """
+ self._check_stop_reason_impl(
+ SOFT_TRAP_FUNC_MINIMAL,
+ expected_stop_reason=stop_reason,
+ expected_func_name=func_name,
+ expected_file_name=file_name,
+ expected_line_num=line_num,
+ )
+
+ def check_state_soft_trap_with_str(
+ self, stop_reason: str, func_name: str, file_name: str, line_num: int
+ ):
+ """
+ Check the program state is as expected when hitting
+ a soft trap from -fbounds-safety-soft-traps=call-with_str
+ """
+ self._check_stop_reason_impl(
+ SOFT_TRAP_FUNC_WITH_STR,
+ expected_stop_reason=stop_reason,
+ expected_func_name=func_name,
+ expected_file_name=file_name,
+ expected_line_num=line_num,
+ )
+
+ # Skip the tests on Windows because they fail due to the stop reason
+ # being `eStopReasonNon` instead of the expected
+ # `eStopReasonInstrumentation`.
+ @skipIfWindows
+ @skipUnlessBoundsSafety
+ def test_call_minimal(self):
+ """
+ Test the plugin on code built with
+ -fbounds-safety-soft-traps=call-minimal
+ """
+ self.build(make_targets=["soft-trap-test-minimal"])
+ self.test_target = self.createTestTarget()
+ self.runCmd("run")
+
+ process = self.test_target.process
+
+ # First soft trap hit
+ self.check_state_soft_trap_minimal(
+ "Soft Bounds check failed: indexing above upper bound in 'buffer[2]'",
+ "main",
+ "main.c",
+ 7,
+ )
+
+ process.Continue()
+
+ # Second soft trap hit
+ self.check_state_soft_trap_minimal(
+ "Soft Bounds check failed: indexing below lower bound in 'buffer[-1]'",
+ "main",
+ "main.c",
+ 8,
+ )
+
+ process.Continue()
+ self.assertEqual(process.GetState(), lldb.eStateExited)
+ self.assertEqual(process.GetExitStatus(), 0)
+
+ @skipIfWindows
+ @skipUnlessBoundsSafety
+ def test_call_with_str(self):
+ """
+ Test the plugin on code built with
+ -fbounds-safety-soft-traps=call-with-str
+ """
+ self.build(make_targets=["soft-trap-test-with-str"])
+ self.test_target = self.createTestTarget()
+ self.runCmd("run")
+
+ process = self.test_target.process
+
+ # First soft trap hit
+ self.check_state_soft_trap_with_str(
+ "Soft Bounds check failed: indexing above upper bound in 'buffer[2]'",
+ "main",
+ "main.c",
+ 7,
+ )
+
+ process.Continue()
+
+ # Second soft trap hit
+ self.check_state_soft_trap_with_str(
+ "Soft Bounds check failed: indexing below lower bound in 'buffer[-1]'",
+ "main",
+ "main.c",
+ 8,
+ )
+
+ process.Continue()
+ self.assertEqual(process.GetState(), lldb.eStateExited)
+ self.assertEqual(process.GetExitStatus(), 0)
diff --git a/lldb/test/API/lang/BoundsSafety/soft_trap/main.c b/lldb/test/API/lang/BoundsSafety/soft_trap/main.c
new file mode 100644
index 0000000..518afaa
--- /dev/null
+++ b/lldb/test/API/lang/BoundsSafety/soft_trap/main.c
@@ -0,0 +1,10 @@
+#include <ptrcheck.h>
+
+int main(void) {
+ int pad;
+ int buffer[] = {0, 1};
+ int pad2;
+ int tmp = buffer[2]; // access past upper bound
+ tmp = buffer[-1]; // access below lower bound
+ return 0;
+}
diff --git a/lldb/test/API/lang/BoundsSafety/soft_trap/mockSoftTrapRuntime.c b/lldb/test/API/lang/BoundsSafety/soft_trap/mockSoftTrapRuntime.c
new file mode 100644
index 0000000..2cfbd24
--- /dev/null
+++ b/lldb/test/API/lang/BoundsSafety/soft_trap/mockSoftTrapRuntime.c
@@ -0,0 +1,17 @@
+#include <bounds_safety_soft_traps.h>
+#include <ptrcheck.h>
+#include <stdio.h>
+
+#if __CLANG_BOUNDS_SAFETY_SOFT_TRAP_API_VERSION > 0
+#error API version changed
+#endif
+
+// FIXME: The runtimes really shouldn't be built with `-fbounds-safety` in
+// soft trap mode because of the risk of infinite recursion. However,
+// there's currently no way to have source files built with different flags
+
+void __bounds_safety_soft_trap_s(const char *reason) {
+ printf("BoundsSafety check FAILED: message:\"%s\"\n", reason ? reason : "");
+}
+
+void __bounds_safety_soft_trap(void) { printf("BoundsSafety check FAILED\n"); }
diff --git a/lldb/test/API/lang/cpp/inline-namespace-in-typename/Makefile b/lldb/test/API/lang/cpp/inline-namespace-in-typename/Makefile
new file mode 100644
index 0000000..99998b2
--- /dev/null
+++ b/lldb/test/API/lang/cpp/inline-namespace-in-typename/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/inline-namespace-in-typename/TestInlineNamespaceInTypename.py b/lldb/test/API/lang/cpp/inline-namespace-in-typename/TestInlineNamespaceInTypename.py
new file mode 100644
index 0000000..1968136
--- /dev/null
+++ b/lldb/test/API/lang/cpp/inline-namespace-in-typename/TestInlineNamespaceInTypename.py
@@ -0,0 +1,30 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestInlineNamespaceInTypename(TestBase):
+ def test(self):
+ """
+ Tests that we correctly omit the inline namespace when printing
+ the type name for "display", even if omitting the inline namespace
+ would be ambiguous in the current context.
+ """
+ self.build()
+ target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+
+ t1 = target.FindGlobalVariables("t1", 1)
+ self.assertTrue(len(t1), 1)
+ self.assertEqual(t1[0].GetDisplayTypeName(), "foo::Duplicate")
+
+ # 'foo::Duplicate' would be an ambiguous reference, but we still
+ # omit the inline namespace when displaying the type.
+ t2 = target.FindGlobalVariables("t2", 1)
+ self.assertTrue(len(t2), 1)
+ self.assertEqual(t2[0].GetDisplayTypeName(), "foo::Duplicate")
+ self.assertEqual(t2[0].GetTypeName(), "foo::bar::Duplicate")
+
+ t3 = target.FindGlobalVariables("t3", 1)
+ self.assertTrue(len(t3), 1)
+ self.assertEqual(t3[0].GetDisplayTypeName(), "foo::Unique")
+ self.assertEqual(t3[0].GetTypeName(), "foo::bar::Unique")
diff --git a/lldb/test/API/lang/cpp/inline-namespace-in-typename/main.cpp b/lldb/test/API/lang/cpp/inline-namespace-in-typename/main.cpp
new file mode 100644
index 0000000..eabd93c
--- /dev/null
+++ b/lldb/test/API/lang/cpp/inline-namespace-in-typename/main.cpp
@@ -0,0 +1,13 @@
+namespace foo {
+struct Duplicate {
+} t1;
+
+inline namespace bar {
+struct Duplicate {
+} t2;
+struct Unique {
+} t3;
+} // namespace bar
+} // namespace foo
+
+int main() { return 0; }
diff --git a/lldb/test/API/lang/cpp/libcxx-internals-recognizer/TestLibcxxInternalsRecognizer.py b/lldb/test/API/lang/cpp/libcxx-internals-recognizer/TestLibcxxInternalsRecognizer.py
index 2f942da..280ac71 100644
--- a/lldb/test/API/lang/cpp/libcxx-internals-recognizer/TestLibcxxInternalsRecognizer.py
+++ b/lldb/test/API/lang/cpp/libcxx-internals-recognizer/TestLibcxxInternalsRecognizer.py
@@ -5,11 +5,12 @@ from lldbsuite.test import lldbutil
import re
+@skipIf(macos_version=[">=", "15.4"], asan=True)
class LibCxxInternalsRecognizerTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@add_test_categories(["libc++"])
- @skipIf(compiler="clang", compiler_version=["<=", "19.0"])
+ @skipIf(compiler="clang", compiler_version=["<", "21.0"])
def test_frame_recognizer(self):
"""Test that implementation details of libc++ are hidden"""
self.build()
diff --git a/lldb/test/API/lang/cpp/template-alias/Makefile b/lldb/test/API/lang/cpp/template-alias/Makefile
new file mode 100644
index 0000000..99998b2
--- /dev/null
+++ b/lldb/test/API/lang/cpp/template-alias/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/template-alias/TestTemplateAlias.py b/lldb/test/API/lang/cpp/template-alias/TestTemplateAlias.py
new file mode 100644
index 0000000..b8314eb
--- /dev/null
+++ b/lldb/test/API/lang/cpp/template-alias/TestTemplateAlias.py
@@ -0,0 +1,50 @@
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class TestTemplateAlias(TestBase):
+ def do_test(self, extra_flags):
+ self.build(dictionary=extra_flags)
+ self.main_source_file = lldb.SBFileSpec("main.cpp")
+ lldbutil.run_to_source_breakpoint(self, "return", lldb.SBFileSpec("main.cpp"))
+
+ self.expect_expr("f1", result_type="Foo<int>")
+ self.expect_expr("f2", result_type="Foo<double>")
+ self.expect_expr("b1", result_type="Bar<int>")
+ self.expect_expr("b2", result_type="Bar<double>")
+ self.expect_expr("bf1", result_type="Bar<int>")
+ self.expect_expr("bf2", result_type="Bar<double>")
+ self.expect_expr("bf1", result_type="Bar<int>")
+ self.expect_expr("bf2", result_type="Bar<double>")
+ self.expect_expr("cbf1", result_type="Container<int>")
+
+ @expectedFailureAll(
+ bugnumber="LLDB doesn't reconstruct template alias names from template parameters"
+ )
+ def test_tag_alias_simple(self):
+ self.do_test(
+ dict(CXXFLAGS_EXTRAS="-gdwarf-5 -gtemplate-alias -gsimple-template-names")
+ )
+
+ def test_tag_alias_no_simple(self):
+ self.do_test(
+ dict(
+ CXXFLAGS_EXTRAS="-gdwarf-5 -gtemplate-alias -gno-simple-template-names"
+ )
+ )
+
+ def test_no_tag_alias_simple(self):
+ self.do_test(
+ dict(
+ CXXFLAGS_EXTRAS="-gdwarf-5 -gno-template-alias -gsimple-template-names"
+ )
+ )
+
+ def test_no_tag_alias_no_simple(self):
+ self.do_test(
+ dict(
+ CXXFLAGS_EXTRAS="-gdwarf-5 -gno-template-alias -gno-simple-template-names"
+ )
+ )
diff --git a/lldb/test/API/lang/cpp/template-alias/main.cpp b/lldb/test/API/lang/cpp/template-alias/main.cpp
new file mode 100644
index 0000000..af6c979
--- /dev/null
+++ b/lldb/test/API/lang/cpp/template-alias/main.cpp
@@ -0,0 +1,16 @@
+template <typename T> using Foo = T;
+
+template <typename T> using Bar = Foo<T>;
+
+template <typename T> struct Container {};
+
+int main() {
+ Foo<int> f1;
+ Foo<double> f2;
+ Bar<int> b1;
+ Bar<double> b2;
+ Bar<Foo<int>> bf1;
+ Bar<Foo<double>> bf2;
+ Container<Bar<Foo<int>>> cbf1;
+ return 0;
+}
diff --git a/lldb/test/API/lang/objc/foundation/TestFoundationDisassembly.py b/lldb/test/API/lang/objc/foundation/TestFoundationDisassembly.py
index 245313d..75f6651a 100644
--- a/lldb/test/API/lang/objc/foundation/TestFoundationDisassembly.py
+++ b/lldb/test/API/lang/objc/foundation/TestFoundationDisassembly.py
@@ -13,52 +13,6 @@ class FoundationDisassembleTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@skipIfAsan
- def test_foundation_disasm(self):
- """Do 'disassemble -n func' on each and every 'Code' symbol entry from the Foundation.framework."""
- self.build()
-
- # Enable synchronous mode
- self.dbg.SetAsync(False)
-
- # Create a target by the debugger.
- target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
- self.assertTrue(target, VALID_TARGET)
-
- # Now launch the process, and do not stop at entry point.
- process = target.LaunchSimple(None, None, self.get_process_working_directory())
- self.assertTrue(process, PROCESS_IS_VALID)
-
- foundation_framework = None
- for module in target.modules:
- if module.file.basename == "Foundation":
- foundation_framework = module.file.fullpath
- break
-
- self.assertIsNotNone(foundation_framework, "Foundation.framework path located")
- self.runCmd("image dump symtab '%s'" % foundation_framework)
- raw_output = self.res.GetOutput()
- # Now, grab every 'Code' symbol and feed it into the command:
- # 'disassemble -n func'.
- #
- # The symbol name is on the last column and trails the flag column which
- # looks like '0xhhhhhhhh', i.e., 8 hexadecimal digits.
- codeRE = re.compile(
- r"""
- \ Code\ {9} # ' Code' followed by 9 SPCs,
- .* # the wildcard chars,
- 0x[0-9a-f]{8} # the flag column, and
- \ (.+)$ # finally the function symbol.
- """,
- re.VERBOSE,
- )
- for line in raw_output.split(os.linesep):
- match = codeRE.search(line)
- if match:
- func = match.group(1)
- self.runCmd('image lookup -s "%s"' % func)
- self.runCmd('disassemble --force -n "%s"' % func)
-
- @skipIfAsan
def test_simple_disasm(self):
"""Test the lldb 'disassemble' command"""
self.build()
diff --git a/lldb/test/API/lang/objc/modules-auto-import/TestModulesAutoImport.py b/lldb/test/API/lang/objc/modules-auto-import/TestModulesAutoImport.py
index 142d27d..f3558f6 100644
--- a/lldb/test/API/lang/objc/modules-auto-import/TestModulesAutoImport.py
+++ b/lldb/test/API/lang/objc/modules-auto-import/TestModulesAutoImport.py
@@ -16,6 +16,7 @@ class ObjCModulesAutoImportTestCase(TestBase):
self.line = line_number("main.m", "// Set breakpoint 0 here.")
@skipIf(macos_version=["<", "10.12"])
+ @skipIf(compiler="clang", compiler_version=["<", "19.0"])
def test_expr(self):
self.build()
exe = self.getBuildArtifact("a.out")
diff --git a/lldb/test/API/lang/objc/modules-compile-error/Makefile b/lldb/test/API/lang/objc/modules-compile-error/Makefile
deleted file mode 100644
index e031aa0..0000000
--- a/lldb/test/API/lang/objc/modules-compile-error/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-OBJC_SOURCES := main.m
-
-CFLAGS_EXTRAS = $(MANDATORY_MODULE_BUILD_CFLAGS) -I$(BUILDDIR) -DONLY_CLANG=1
-
-include Makefile.rules
diff --git a/lldb/test/API/lang/objc/modules-compile-error/TestModulesCompileError.py b/lldb/test/API/lang/objc/modules-compile-error/TestModulesCompileError.py
deleted file mode 100644
index 36e302be..0000000
--- a/lldb/test/API/lang/objc/modules-compile-error/TestModulesCompileError.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class TestCase(TestBase):
- @skipIf(compiler="clang", compiler_version=["<", "11.0"])
- def test(self):
- self.build()
- lldbutil.run_to_source_breakpoint(
- self, "// break here", lldb.SBFileSpec("main.m")
- )
-
- # Try importing our custom module. This will fail as LLDB won't define
- # the CLANG_ONLY define when it compiles the module for the expression
- # evaluator.
- # Check that the error message shows file/line/column, prints the relevant
- # line from the source code and mentions the module that failed to build.
- self.expect(
- "expr @import LLDBTestModule",
- error=True,
- substrs=[
- "module.h:4:1: error: use of undeclared identifier 'syntax_error_for_lldb_to_find'",
- "syntax_error_for_lldb_to_find // comment that tests source printing",
- "could not build module 'LLDBTestModule'",
- ],
- )
diff --git a/lldb/test/API/lang/objc/modules-compile-error/main.m b/lldb/test/API/lang/objc/modules-compile-error/main.m
deleted file mode 100644
index 35259dd..0000000
--- a/lldb/test/API/lang/objc/modules-compile-error/main.m
+++ /dev/null
@@ -1,5 +0,0 @@
-@import LLDBTestModule;
-
-int main() {
- return foo(); // break here
-}
diff --git a/lldb/test/API/lang/objc/modules-compile-error/module.h b/lldb/test/API/lang/objc/modules-compile-error/module.h
deleted file mode 100644
index 2edd13b..0000000
--- a/lldb/test/API/lang/objc/modules-compile-error/module.h
+++ /dev/null
@@ -1,5 +0,0 @@
-int foo() { return 123; }
-
-#ifndef ONLY_CLANG
-syntax_error_for_lldb_to_find // comment that tests source printing
-#endif
diff --git a/lldb/test/API/lang/objc/modules-compile-error/module.modulemap b/lldb/test/API/lang/objc/modules-compile-error/module.modulemap
deleted file mode 100644
index 3d44faf..0000000
--- a/lldb/test/API/lang/objc/modules-compile-error/module.modulemap
+++ /dev/null
@@ -1 +0,0 @@
-module LLDBTestModule { header "module.h" export * }
diff --git a/lldb/test/API/lang/objc/modules-objc-property/TestModulesObjCProperty.py b/lldb/test/API/lang/objc/modules-objc-property/TestModulesObjCProperty.py
index 3be064a..657a710 100644
--- a/lldb/test/API/lang/objc/modules-objc-property/TestModulesObjCProperty.py
+++ b/lldb/test/API/lang/objc/modules-objc-property/TestModulesObjCProperty.py
@@ -6,6 +6,7 @@ from lldbsuite.test import lldbutil
class TestCase(TestBase):
@no_debug_info_test
+ @skipIf(compiler="clang", compiler_version=["<", "19.0"])
def test_conflicting_properties(self):
"""Tests receiving two properties with the same name from modules."""
self.build()
diff --git a/lldb/test/API/lang/rust/enum-variant-same-name/RustEnumValue.py b/lldb/test/API/lang/rust/enum-variant-same-name/RustEnumValue.py
new file mode 100644
index 0000000..bc4fd7d
--- /dev/null
+++ b/lldb/test/API/lang/rust/enum-variant-same-name/RustEnumValue.py
@@ -0,0 +1,69 @@
+"""Helper library to traverse data emitted for Rust enums """
+from lldbsuite.test.lldbtest import *
+
+DISCRIMINANT_MEMBER_NAME = "$discr$"
+VALUE_MEMBER_NAME = "value"
+
+
+class RustEnumValue:
+ def __init__(self, value: lldb.SBValue):
+ self.value = value
+
+ def getAllVariantTypes(self):
+ result = []
+ for i in range(self._inner().GetNumChildren()):
+ result.append(self.getVariantByIndex(i).GetDisplayTypeName())
+ return result
+
+ def _inner(self) -> lldb.SBValue:
+ return self.value.GetChildAtIndex(0)
+
+ def getVariantByIndex(self, index):
+ return (
+ self._inner()
+ .GetChildAtIndex(index)
+ .GetChildMemberWithName(VALUE_MEMBER_NAME)
+ )
+
+ @staticmethod
+ def _getDiscriminantValueAsUnsigned(discr_sbvalue: lldb.SBValue):
+ byte_size = discr_sbvalue.GetType().GetByteSize()
+ error = lldb.SBError()
+
+ # when discriminant is u16 Clang emits 'unsigned char'
+ # and LLDB seems to treat it as character type disalowing to call GetValueAsUnsigned
+ if byte_size == 1:
+ return discr_sbvalue.GetData().GetUnsignedInt8(error, 0)
+ elif byte_size == 2:
+ return discr_sbvalue.GetData().GetUnsignedInt16(error, 0)
+ elif byte_size == 4:
+ return discr_sbvalue.GetData().GetUnsignedInt32(error, 0)
+ elif byte_size == 8:
+ return discr_sbvalue.GetData().GetUnsignedInt64(error, 0)
+ else:
+ return discr_sbvalue.GetValueAsUnsigned()
+
+ def getCurrentVariantIndex(self):
+ default_index = 0
+ for i in range(self._inner().GetNumChildren()):
+ variant: lldb.SBValue = self._inner().GetChildAtIndex(i)
+ discr = variant.GetChildMemberWithName(DISCRIMINANT_MEMBER_NAME)
+ if discr.IsValid():
+ discr_unsigned_value = RustEnumValue._getDiscriminantValueAsUnsigned(
+ discr
+ )
+ if variant.GetName() == f"$variant${discr_unsigned_value}":
+ return discr_unsigned_value
+ else:
+ default_index = i
+ return default_index
+
+ def getFields(self):
+ result = []
+ for i in range(self._inner().GetNumChildren()):
+ type: lldb.SBType = self._inner().GetType()
+ result.append(type.GetFieldAtIndex(i).GetName())
+ return result
+
+ def getCurrentValue(self) -> lldb.SBValue:
+ return self.getVariantByIndex(self.getCurrentVariantIndex())
diff --git a/lldb/test/API/lang/rust/enum-variant-same-name/TestRustEnumVariantSameName.py b/lldb/test/API/lang/rust/enum-variant-same-name/TestRustEnumVariantSameName.py
new file mode 100644
index 0000000..0a192dc
--- /dev/null
+++ b/lldb/test/API/lang/rust/enum-variant-same-name/TestRustEnumVariantSameName.py
@@ -0,0 +1,36 @@
+"""Test that lldb recognizes enum variant emitted by Rust compiler """
+import logging
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from RustEnumValue import RustEnumValue
+
+
+class TestRustEnumStructs(TestBase):
+ def setUp(self):
+ TestBase.setUp(self)
+ src_dir = self.getSourceDir()
+ yaml_path = os.path.join(src_dir, "main.yaml")
+ obj_path = self.getBuildArtifact("main.o")
+ self.yaml2obj(yaml_path, obj_path)
+ self.dbg.CreateTarget(obj_path)
+
+ def getFromGlobal(self, name):
+ values = self.target().FindGlobalVariables(name, 1)
+ self.assertEqual(values.GetSize(), 1)
+ return RustEnumValue(values[0])
+
+ def test_enum_instance(self):
+ # static ENUM_INSTANCE: A = A::A(B::B(10));
+ value = self.getFromGlobal("ENUM_INSTANCE").getCurrentValue()
+ self.assertEqual(value.GetType().GetDisplayTypeName(), "main::A::A")
+
+ value_b = RustEnumValue(value.GetChildAtIndex(0))
+ self.assertEqual(
+ value_b.getCurrentValue()
+ .GetChildAtIndex(0)
+ .GetData()
+ .GetUnsignedInt8(lldb.SBError(), 0),
+ 10,
+ )
diff --git a/lldb/test/API/lang/rust/enum-variant-same-name/main.rs b/lldb/test/API/lang/rust/enum-variant-same-name/main.rs
new file mode 100644
index 0000000..e76be3d
--- /dev/null
+++ b/lldb/test/API/lang/rust/enum-variant-same-name/main.rs
@@ -0,0 +1,15 @@
+/// Command:
+/// rustc -g --emit=obj --crate-type=bin -C panic=abort -C link-arg=-nostdlib main.rs && obj2yaml main.o -o main.yaml
+
+pub enum A {
+ A(B),
+}
+
+pub enum B {
+ B(u8),
+}
+
+static ENUM_INSTANCE: A = A::A(B::B(10));
+
+pub fn main() {
+}
diff --git a/lldb/test/API/lang/rust/enum-variant-same-name/main.yaml b/lldb/test/API/lang/rust/enum-variant-same-name/main.yaml
new file mode 100644
index 0000000..76e7cb6
--- /dev/null
+++ b/lldb/test/API/lang/rust/enum-variant-same-name/main.yaml
@@ -0,0 +1,1137 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+ SectionHeaderStringTable: .strtab
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x4
+ - Name: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: 4883EC2889C84889D14889F248897C2408488954241048894C24188844242748893C244889E7488D3500000000440FB6C0FF15000000004883C428C3
+ - Name: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: 4883EC1848897C2408488B3FE800000000E800000000884424170FB6C04883C418C3
+ - Name: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: 4883EC1848897C2408E8000000004883C418C3
+ - Name: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: 4883EC1848897C2410488B3FE8000000004883C418C3
+ - Name: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: 4883EC1848897C2408488D7C2408E8000000004883C418C3
+ - Name: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: 4883EC1848897C2410FFD74883C418C3
+ - Name: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: 48897C24F8C3
+ - Name: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: 31C0C3
+ - Name: .text._ZN4main4main17h5659c6c02e5cd445E
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: C3
+ - Name: .text.main
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Content: 504889F2488B05000000008A004863F7488D3D0000000031C9E80000000059C3
+ - Name: .data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x8
+ Content: '000000000000000008000000000000000800000000000000000000000000000000000000000000000000000000000000'
+ - Name: .rodata._ZN4main13ENUM_INSTANCE17hc6db515181ea378fE
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x1
+ Content: 0A
+ - Name: .debug_gdb_scripts
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x1
+ EntSize: 0x1
+ Content: 016764625F6C6F61645F727573745F7072657474795F7072696E746572732E707900
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x1
+ Content: 011101250E1305030E10171B0E110155170000023400030E4913021800000313011D13030E0B0B88010F0000040D00030E491388010F380B0000050F004913030E33060000062400030E3E0B0B0B0000073901030E0000081301030E0B0B88010F0000092E011101120640186E0E030E3A0B3B0B491300000A34000218030E88010F3A0B3B0B491300000B1D01311311011206580B590B570B00000C05000218311300000D1D00311311011206580B5905570B00000E2F004913030E00000F05000218030E3A0B3B0B49130000101301030E0B0B320B88010F0000110D00030E491388010F380B320B0000122E016E0E030E3A0B3B0549133C19000013050049130000142E011101120640186E0E030E3A0B3B0B0000150B01110112060000163400021831130000172E011101120640186E0E030E3A0B3B054913000018050002183A0B3B054913000019150000001A3400030E49133A0B3B0B88010F02186E0E00001B330100001C190100001D2E001101120640186E0E030E3A0B3B0B6A1900001E2E004713200B00001F2E014713200B0000200500030E3A0B3B0549130000212E016E0E030E3A0B3B05200B0000223400030E88010F3A0B3B054913000023050002183A0B3B0B49130000242E011101120640186E0E030E3A0B3B05000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x1
+ Content: F00400000400000000000801000000001C0000000000000000000000000000000000000000000000000002000000003D0000000903000000000000000003B500000000000000300804000000008B000000080004000000009F000000080804000000009F000000081004000000008B000000081804000000008B000000082004000000008B000000082800059800000000000000000000000600000000070006000000000708070000000007000000000700000000080000000008080400000000B1020000080000090000000000000000220000000157000000000000000002C7590300000A03910806000000000802C1B10200000B7303000000000000000000000300000002C7550C029117790300000D6D030000000000000000000003000000041D0810000E980000000000000000000900000000000000003C0000000157000000000000000002C0C50400000F0291080000000002C1B10200000F0291100000000002C2C50400000F0291180000000002C3CC0400000F0291270000000002C4520300000E9800000000000000000007000000000700000000070000000007000000001000000000010101110000000052030000010003120000000000000000037C0259030000136003000000000000000700000000140000000000000000130000000157000000000000000005940F029108000000000594B1020000150000000000000000000000000A02910700000000010598980000000B90030000000000000000000000000000059B0516029117A603000000000EB1020000000000000E9800000000000000000000070000000010000000000101011100000000A6010000010003120000000000000000041C0859030000135402000000000700000000170000000000000000030000000157000000000000000004A909540200001802917F04A909980000000000000005BE02000000000000000000001907000000001A00000000DE020000010C01090300000000000000000000000010000000000101011B1C0400000000F502000001000000100000000001010111000000000B030000010001000010000000000101011B1C04000000002203000001000000100000000001010111000000005203000001000100001D00000000000000000100000001570000000000000000010E00060000000007010600000000050405A601000000000000000000001EBA010000011F68020000012000000000041C0854020000000700000000070000000021000000000000000006DC01010E980000000000000022000000000106DC01980000000000070000000007000000000700000000090000000000000000160000000157000000000000000007FA590300002302911007FAE60400002302910F07FA980000000EB5000000000000000E980000000000000000090000000000000000180000000157000000000000000007FA590300002302910807FAB50000002302911707FA980000000EB5000000000000000E980000000000000000140000000000000000100000000157000000000000000007FA2302911007FAB10200002302910F07FA980000000EB1020000000000000E98000000000000000000000007000000002400000000000000000600000001570000000000000000080B0218029178080B02E60400000EB5000000000000000000000600000000050805D904000000000000000000000552030000000000000000000005B5000000000000000000000000
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x1
+ EntSize: 0x1
+ Content: 0072757374632076657273696F6E20312E38372E30202831373036376539616320323032352D30352D30392900
+ - Name: .note.GNU-stack
+ Type: SHT_PROGBITS
+ AddressAlign: 0x1
+ - Name: .eh_frame
+ Type: SHT_X86_64_UNWIND
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x8
+ Content: 1400000000000000017A5200017810011B0C070890010000140000001C000000000000003C00000000440E30770E08001400000034000000000000002200000000440E205D0E0800140000004C000000000000001300000000440E204E0E08001400000064000000000000001600000000440E20510E0800140000007C000000000000001800000000440E20530E08001400000094000000000000001000000000440E204B0E080010000000AC00000000000000060000000000000010000000C000000000000000030000000000000010000000D400000000000000010000000000000018000000E8000000000000002000000000410E105E0E080000000000
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x1
+ Content: 0D0400000400E9020000010101FB0E0D0001010101000000010000012F686F6D652F6B6976612F2E7275737475702F746F6F6C636861696E732F737461626C652D7838365F36342D756E6B6E6F776E2D6C696E75782D676E752F6C69622F727573746C69622F7372632F727573742F6C6962726172792F7374642F737263002F686F6D652F6B6976612F2E7275737475702F746F6F6C636861696E732F737461626C652D7838365F36342D756E6B6E6F776E2D6C696E75782D676E752F6C69622F727573746C69622F7372632F727573742F6C6962726172792F7374642F7372632F7379732F70726F636573732F756E6978002F686F6D652F6B6976612F2E7275737475702F746F6F6C636861696E732F737461626C652D7838365F36342D756E6B6E6F776E2D6C696E75782D676E752F6C69622F727573746C69622F7372632F727573742F6C6962726172792F7374642F7372632F737973002F686F6D652F6B6976612F2E7275737475702F746F6F6C636861696E732F737461626C652D7838365F36342D756E6B6E6F776E2D6C696E75782D676E752F6C69622F727573746C69622F7372632F727573742F6C6962726172792F636F72652F737263002F686F6D652F6B6976612F2E7275737475702F746F6F6C636861696E732F737461626C652D7838365F36342D756E6B6E6F776E2D6C696E75782D676E752F6C69622F727573746C69622F7372632F727573742F6C6962726172792F636F72652F7372632F6F7073002F686F6D652F6B6976612F2E7275737475702F746F6F6C636861696E732F737461626C652D7838365F36342D756E6B6E6F776E2D6C696E75782D676E752F6C69622F727573746C69622F7372632F727573742F6C6962726172792F636F72652F7372632F70747200006D61696E2E72730000000072742E727300010000636F6D6D6F6E2E72730002000070726F636573732E7273000100006261636B74726163652E72730003000068696E742E72730004000066756E6374696F6E2E7273000500006D6F642E727300060000000402000902000000000000000003BF0101050A0A08DD05054905020B084202050001010402000902000000000000000003C6010105460A900512063C040305090603B603D60402055D0B03CA7C3C0205000101040500090200000000000000000393010105120A940406050503C50258040505020B03C17D0102050001010407000902000000000000000003F9010105050A90060B8202050001010407000902000000000000000003F9010105050A90060B9E02050001010407000902000000000000000003F9010105050A90060B2E020500010104080009020000000000000000038A040105010A580201000101040405060A000902000000000000000003AA1301020300010105020A0009020000000000000000030E010201000101
+ - Name: .rela.text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Relocations:
+ - Offset: 0x29
+ Symbol: .data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ Type: R_X86_64_PC32
+ Addend: -4
+ - Offset: 0x33
+ Symbol: _ZN3std2rt19lang_start_internal17h418648f91f5be3a1E
+ Type: R_X86_64_GOTPCREL
+ Addend: -4
+ - Name: '.rela.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Relocations:
+ - Offset: 0xD
+ Symbol: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: R_X86_64_PLT32
+ Addend: -4
+ - Offset: 0x12
+ Symbol: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: R_X86_64_PLT32
+ Addend: -4
+ - Name: .rela.text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Relocations:
+ - Offset: 0xA
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: R_X86_64_PLT32
+ Addend: -4
+ - Name: '.rela.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Relocations:
+ - Offset: 0xD
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: R_X86_64_PLT32
+ Addend: -4
+ - Name: .rela.text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Relocations:
+ - Offset: 0xF
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_PLT32
+ Addend: -4
+ - Name: .rela.text.main
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .text.main
+ Relocations:
+ - Offset: 0x7
+ Symbol: __rustc_debug_gdb_scripts_section__
+ Type: R_X86_64_GOTPCREL
+ Addend: -4
+ - Offset: 0x13
+ Symbol: .text._ZN4main4main17h5659c6c02e5cd445E
+ Type: R_X86_64_PC32
+ Addend: -4
+ - Offset: 0x1A
+ Symbol: _ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: R_X86_64_PLT32
+ Addend: -4
+ - Name: .rela.data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ Relocations:
+ - Offset: 0x18
+ Symbol: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: R_X86_64_64
+ - Offset: 0x20
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_64
+ - Offset: 0x28
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_64
+ - Name: .rela.debug_info
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .debug_info
+ Relocations:
+ - Offset: 0x6
+ Symbol: .debug_abbrev
+ Type: R_X86_64_32
+ - Offset: 0xC
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ - Offset: 0x12
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 57
+ - Offset: 0x16
+ Symbol: .debug_line
+ Type: R_X86_64_32
+ - Offset: 0x1A
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 95
+ - Offset: 0x26
+ Symbol: .debug_ranges
+ Type: R_X86_64_32
+ - Offset: 0x2B
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 176
+ - Offset: 0x35
+ Symbol: .data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ Type: R_X86_64_64
+ - Offset: 0x42
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 382
+ - Offset: 0x49
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 260
+ - Offset: 0x54
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 287
+ - Offset: 0x5F
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 298
+ - Offset: 0x6A
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 304
+ - Offset: 0x75
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 314
+ - Offset: 0x80
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 324
+ - Offset: 0x90
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 277
+ - Offset: 0x99
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 274
+ - Offset: 0xA0
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 292
+ - Offset: 0xA7
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 334
+ - Offset: 0xAC
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 338
+ - Offset: 0xB1
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 341
+ - Offset: 0xB6
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 362
+ - Offset: 0xBD
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 352
+ - Offset: 0xC9
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_64
+ - Offset: 0xD7
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 943
+ - Offset: 0xDB
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1016
+ - Offset: 0xEA
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 352
+ - Offset: 0xFA
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_64
+ Addend: 26
+ - Offset: 0x116
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_64
+ Addend: 26
+ - Offset: 0x12C
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 769
+ - Offset: 0x133
+ Symbol: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: R_X86_64_64
+ - Offset: 0x141
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 879
+ - Offset: 0x145
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 922
+ - Offset: 0x153
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 352
+ - Offset: 0x161
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1744
+ - Offset: 0x16F
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1749
+ - Offset: 0x17D
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1781
+ - Offset: 0x18C
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 769
+ - Offset: 0x193
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 540
+ - Offset: 0x198
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 544
+ - Offset: 0x19D
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 552
+ - Offset: 0x1A2
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 557
+ - Offset: 0x1A7
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 564
+ - Offset: 0x1AF
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 487
+ - Offset: 0x1BB
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 573
+ - Offset: 0x1BF
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 641
+ - Offset: 0x1D5
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 835
+ - Offset: 0x1DA
+ Symbol: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: R_X86_64_64
+ - Offset: 0x1E8
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1034
+ - Offset: 0x1EC
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1106
+ - Offset: 0x1F6
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1796
+ - Offset: 0x201
+ Symbol: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: R_X86_64_64
+ Addend: 14
+ - Offset: 0x211
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1789
+ - Offset: 0x221
+ Symbol: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: R_X86_64_64
+ Addend: 14
+ - Offset: 0x23F
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1032
+ - Offset: 0x248
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 769
+ - Offset: 0x250
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 544
+ - Offset: 0x255
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 564
+ - Offset: 0x25D
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 487
+ - Offset: 0x269
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 695
+ - Offset: 0x26D
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 747
+ - Offset: 0x280
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 869
+ - Offset: 0x285
+ Symbol: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: R_X86_64_64
+ - Offset: 0x293
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1616
+ - Offset: 0x297
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1703
+ - Offset: 0x2B6
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 357
+ - Offset: 0x2C0
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 352
+ - Offset: 0x2C5
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 471
+ - Offset: 0x2D2
+ Symbol: .rodata._ZN4main13ENUM_INSTANCE17hc6db515181ea378fE
+ Type: R_X86_64_64
+ - Offset: 0x2DA
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 496
+ - Offset: 0x2DF
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 485
+ - Offset: 0x2E9
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 485
+ - Offset: 0x2F6
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 485
+ - Offset: 0x2FE
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 487
+ - Offset: 0x30C
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 491
+ - Offset: 0x316
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 491
+ - Offset: 0x323
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 491
+ - Offset: 0x32B
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 487
+ - Offset: 0x339
+ Symbol: .text._ZN4main4main17h5659c6c02e5cd445E
+ Type: R_X86_64_64
+ - Offset: 0x347
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1710
+ - Offset: 0x34B
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 352
+ - Offset: 0x353
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 493
+ - Offset: 0x35A
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 648
+ - Offset: 0x365
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 652
+ - Offset: 0x37A
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 754
+ - Offset: 0x387
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 759
+ - Offset: 0x38C
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 764
+ - Offset: 0x391
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 771
+ - Offset: 0x395
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 815
+ - Offset: 0x3A2
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 769
+ - Offset: 0x3A7
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 829
+ - Offset: 0x3B6
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 845
+ - Offset: 0x3BB
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 849
+ - Offset: 0x3C0
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 858
+ - Offset: 0x3C5
+ Symbol: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: R_X86_64_64
+ - Offset: 0x3D3
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1155
+ - Offset: 0x3D7
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1246
+ - Offset: 0x3FA
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1145
+ - Offset: 0x403
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1150
+ - Offset: 0x409
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: R_X86_64_64
+ - Offset: 0x417
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1302
+ - Offset: 0x41B
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1246
+ - Offset: 0x43E
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1145
+ - Offset: 0x447
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1150
+ - Offset: 0x44D
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: R_X86_64_64
+ - Offset: 0x45B
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1361
+ - Offset: 0x45F
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1420
+ - Offset: 0x47E
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1145
+ - Offset: 0x487
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1150
+ - Offset: 0x490
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 865
+ - Offset: 0x495
+ Symbol: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Type: R_X86_64_64
+ - Offset: 0x4A3
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1440
+ - Offset: 0x4A7
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1560
+ - Offset: 0x4BE
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 769
+ - Offset: 0x4C6
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 937
+ - Offset: 0x4D1
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1764
+ - Offset: 0x4DE
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1754
+ - Offset: 0x4EB
+ Symbol: .debug_str
+ Type: R_X86_64_32
+ Addend: 1798
+ - Name: .rela.debug_aranges
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .debug_aranges
+ Relocations:
+ - Offset: 0x6
+ Symbol: .debug_info
+ Type: R_X86_64_32
+ - Offset: 0x10
+ Symbol: .data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ Type: R_X86_64_64
+ - Offset: 0x20
+ Symbol: .rodata._ZN4main13ENUM_INSTANCE17hc6db515181ea378fE
+ Type: R_X86_64_64
+ - Offset: 0x30
+ Symbol: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: R_X86_64_64
+ - Offset: 0x40
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_64
+ - Offset: 0x50
+ Symbol: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: R_X86_64_64
+ - Offset: 0x60
+ Symbol: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: R_X86_64_64
+ - Offset: 0x70
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: R_X86_64_64
+ - Offset: 0x80
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: R_X86_64_64
+ - Offset: 0x90
+ Symbol: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Type: R_X86_64_64
+ - Offset: 0xA0
+ Symbol: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: R_X86_64_64
+ - Offset: 0xB0
+ Symbol: .text._ZN4main4main17h5659c6c02e5cd445E
+ Type: R_X86_64_64
+ - Name: .rela.debug_ranges
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .debug_ranges
+ Relocations:
+ - Symbol: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: R_X86_64_64
+ - Offset: 0x8
+ Symbol: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: R_X86_64_64
+ Addend: 60
+ - Offset: 0x10
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_64
+ - Offset: 0x18
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_64
+ Addend: 34
+ - Offset: 0x20
+ Symbol: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: R_X86_64_64
+ - Offset: 0x28
+ Symbol: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: R_X86_64_64
+ Addend: 19
+ - Offset: 0x30
+ Symbol: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: R_X86_64_64
+ - Offset: 0x38
+ Symbol: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: R_X86_64_64
+ Addend: 22
+ - Offset: 0x40
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: R_X86_64_64
+ - Offset: 0x48
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: R_X86_64_64
+ Addend: 24
+ - Offset: 0x50
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: R_X86_64_64
+ - Offset: 0x58
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: R_X86_64_64
+ Addend: 16
+ - Offset: 0x60
+ Symbol: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Type: R_X86_64_64
+ - Offset: 0x68
+ Symbol: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Type: R_X86_64_64
+ Addend: 6
+ - Offset: 0x70
+ Symbol: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: R_X86_64_64
+ - Offset: 0x78
+ Symbol: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: R_X86_64_64
+ Addend: 3
+ - Offset: 0x80
+ Symbol: .text._ZN4main4main17h5659c6c02e5cd445E
+ Type: R_X86_64_64
+ - Offset: 0x88
+ Symbol: .text._ZN4main4main17h5659c6c02e5cd445E
+ Type: R_X86_64_64
+ Addend: 1
+ - Name: .rela.eh_frame
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .eh_frame
+ Relocations:
+ - Offset: 0x20
+ Symbol: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: R_X86_64_PC32
+ - Offset: 0x38
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_PC32
+ - Offset: 0x50
+ Symbol: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: R_X86_64_PC32
+ - Offset: 0x68
+ Symbol: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: R_X86_64_PC32
+ - Offset: 0x80
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: R_X86_64_PC32
+ - Offset: 0x98
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: R_X86_64_PC32
+ - Offset: 0xB0
+ Symbol: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Type: R_X86_64_PC32
+ - Offset: 0xC4
+ Symbol: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: R_X86_64_PC32
+ - Offset: 0xD8
+ Symbol: .text._ZN4main4main17h5659c6c02e5cd445E
+ Type: R_X86_64_PC32
+ - Offset: 0xEC
+ Symbol: .text.main
+ Type: R_X86_64_PC32
+ - Name: .rela.debug_line
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .debug_line
+ Relocations:
+ - Offset: 0x2F8
+ Symbol: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: R_X86_64_64
+ - Offset: 0x31B
+ Symbol: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: R_X86_64_64
+ - Offset: 0x34B
+ Symbol: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: R_X86_64_64
+ - Offset: 0x376
+ Symbol: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: R_X86_64_64
+ - Offset: 0x393
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: R_X86_64_64
+ - Offset: 0x3B0
+ Symbol: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: R_X86_64_64
+ - Offset: 0x3CD
+ Symbol: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Type: R_X86_64_64
+ - Offset: 0x3EA
+ Symbol: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: R_X86_64_64
+ - Offset: 0x401
+ Symbol: .text._ZN4main4main17h5659c6c02e5cd445E
+ Type: R_X86_64_64
+ - Type: SectionHeaderTable
+ Sections:
+ - Name: .strtab
+ - Name: .text
+ - Name: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ - Name: .rela.text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ - Name: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ - Name: '.rela.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ - Name: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ - Name: .rela.text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ - Name: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ - Name: '.rela.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ - Name: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ - Name: .rela.text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ - Name: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ - Name: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ - Name: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ - Name: .text._ZN4main4main17h5659c6c02e5cd445E
+ - Name: .text.main
+ - Name: .rela.text.main
+ - Name: .data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ - Name: .rela.data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ - Name: .rodata._ZN4main13ENUM_INSTANCE17hc6db515181ea378fE
+ - Name: .debug_gdb_scripts
+ - Name: .debug_abbrev
+ - Name: .debug_info
+ - Name: .rela.debug_info
+ - Name: .debug_aranges
+ - Name: .rela.debug_aranges
+ - Name: .debug_ranges
+ - Name: .rela.debug_ranges
+ - Name: .debug_str
+ - Name: .comment
+ - Name: .note.GNU-stack
+ - Name: .eh_frame
+ - Name: .rela.eh_frame
+ - Name: .debug_line
+ - Name: .rela.debug_line
+ - Name: .symtab
+Symbols:
+ - Name: main.5f6bf0c8e9d0afce-cgu.0
+ Type: STT_FILE
+ Index: SHN_ABS
+ - Name: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: STT_SECTION
+ Section: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ - Name: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: STT_SECTION
+ Section: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ - Name: '_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Type: STT_FUNC
+ Section: '.text._ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ Size: 0x22
+ - Name: _ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: STT_FUNC
+ Section: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Size: 0x13
+ - Name: '_ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: STT_FUNC
+ Section: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Size: 0x3
+ - Name: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ Type: STT_SECTION
+ Section: .text._ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ - Name: _ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: STT_FUNC
+ Section: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Size: 0x10
+ - Name: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: STT_SECTION
+ Section: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ - Name: '_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Type: STT_FUNC
+ Section: '.text._ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ Size: 0x16
+ - Name: _ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: STT_FUNC
+ Section: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Size: 0x18
+ - Name: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ Type: STT_SECTION
+ Section: .text._ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ - Name: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ Type: STT_SECTION
+ Section: .text._ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ - Name: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Type: STT_SECTION
+ Section: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ - Name: '_ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Type: STT_FUNC
+ Section: '.text._ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ Size: 0x6
+ - Name: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ Type: STT_SECTION
+ Section: '.text._ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ - Name: .text._ZN4main4main17h5659c6c02e5cd445E
+ Type: STT_SECTION
+ Section: .text._ZN4main4main17h5659c6c02e5cd445E
+ - Name: _ZN4main4main17h5659c6c02e5cd445E
+ Type: STT_FUNC
+ Section: .text._ZN4main4main17h5659c6c02e5cd445E
+ Size: 0x1
+ - Name: .text.main
+ Type: STT_SECTION
+ Section: .text.main
+ - Name: .data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ Type: STT_SECTION
+ Section: .data.rel.ro..Lanon.4a406b9d9c1243847b49ddffb2385826.0
+ - Name: _ZN4main13ENUM_INSTANCE17hc6db515181ea378fE
+ Type: STT_OBJECT
+ Section: .rodata._ZN4main13ENUM_INSTANCE17hc6db515181ea378fE
+ Size: 0x1
+ - Name: .rodata._ZN4main13ENUM_INSTANCE17hc6db515181ea378fE
+ Type: STT_SECTION
+ Section: .rodata._ZN4main13ENUM_INSTANCE17hc6db515181ea378fE
+ - Name: .debug_abbrev
+ Type: STT_SECTION
+ Section: .debug_abbrev
+ - Name: .debug_info
+ Type: STT_SECTION
+ Section: .debug_info
+ - Name: .debug_ranges
+ Type: STT_SECTION
+ Section: .debug_ranges
+ - Name: .debug_str
+ Type: STT_SECTION
+ Section: .debug_str
+ - Name: .debug_line
+ Type: STT_SECTION
+ Section: .debug_line
+ - Name: _ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Type: STT_FUNC
+ Section: .text._ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ Binding: STB_GLOBAL
+ Size: 0x3C
+ Other: [ STV_HIDDEN ]
+ - Name: _ZN3std2rt19lang_start_internal17h418648f91f5be3a1E
+ Binding: STB_GLOBAL
+ - Name: main
+ Type: STT_FUNC
+ Section: .text.main
+ Binding: STB_GLOBAL
+ Size: 0x20
+ - Name: __rustc_debug_gdb_scripts_section__
+ Type: STT_OBJECT
+ Section: .debug_gdb_scripts
+ Binding: STB_WEAK
+ Size: 0x22
+DWARF:
+ debug_str:
+ - 'clang LLVM (rustc version 1.87.0 (17067e9ac 2025-05-09))'
+ - 'main.rs/@/main.5f6bf0c8e9d0afce-cgu.0'
+ - '/home/kiva/upstream/llvm-upstream/lldb/test/API/lang/rust/enum-variant-same-name'
+ - '<std::rt::lang_start::{closure_env#0}<()> as core::ops::function::Fn<()>>::{vtable}'
+ - drop_in_place
+ - '()'
+ - '*const ()'
+ - size
+ - usize
+ - align
+ - __method3
+ - __method4
+ - __method5
+ - std
+ - rt
+ - lang_start
+ - main
+ - 'fn()'
+ - '{closure_env#0}<()>'
+ - '<std::rt::lang_start::{closure_env#0}<()> as core::ops::function::Fn<()>>::{vtable_type}'
+ - ENUM_INSTANCE
+ - A
+ - __0
+ - B
+ - u8
+ - _ZN4main13ENUM_INSTANCE17hc6db515181ea378fE
+ - sys
+ - process
+ - unix
+ - common
+ - ExitCode
+ - _ZN3std3sys7process4unix6common8ExitCode6as_i3217h7893c1c2ab39ed8fE
+ - as_i32
+ - i32
+ - '&std::sys::process::unix::common::ExitCode'
+ - _ZN3std7process8ExitCode6to_i3217habce61080992bc43E
+ - to_i32
+ - self
+ - core
+ - hint
+ - T
+ - _ZN4core4hint9black_box17h29a7c52ab9efa45eE
+ - 'black_box<()>'
+ - dummy
+ - backtrace
+ - ops
+ - function
+ - FnOnce
+ - ptr
+ - '{impl#59}'
+ - _ZN3std2rt10lang_start17hcb2a6a78164896cfE
+ - 'lang_start<()>'
+ - isize
+ - '_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hda4568952b4f838eE'
+ - '{closure#0}<()>'
+ - F
+ - _ZN3std3sys9backtrace28__rust_begin_short_backtrace17h4c89f1d03cb386ebE
+ - '__rust_begin_short_backtrace<fn(), ()>'
+ - Self
+ - Args
+ - '_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h356d5dadf319082fE'
+ - 'call_once<std::rt::lang_start::{closure_env#0}<()>, ()>'
+ - _ZN4core3ops8function6FnOnce9call_once17h21112f971fb5dae8E
+ - _ZN4core3ops8function6FnOnce9call_once17hf55c273de81f71dfE
+ - 'call_once<fn(), ()>'
+ - '_ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h623f70e9f0cf3066E'
+ - 'drop_in_place<std::rt::lang_start::{closure_env#0}<()>>'
+ - '_ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17h10aa5c9c6135be01E'
+ - report
+ - _ZN4main4main17h5659c6c02e5cd445E
+ - argc
+ - argv
+ - '*const u8'
+ - '*const *const u8'
+ - sigpipe
+ - result
+ - f
+ - '*mut std::rt::lang_start::{closure_env#0}<()>'
+ debug_aranges:
+ - Length: 0xCC
+ Version: 2
+ CuOffset: 0x0
+ AddressSize: 0x8
+ Descriptors:
+ - Address: 0x0
+ Length: 0x30
+ - Address: 0x0
+ Length: 0x1
+ - Address: 0x0
+ Length: 0x3C
+ - Address: 0x0
+ Length: 0x22
+ - Address: 0x0
+ Length: 0x13
+ - Address: 0x0
+ Length: 0x16
+ - Address: 0x0
+ Length: 0x18
+ - Address: 0x0
+ Length: 0x10
+ - Address: 0x0
+ Length: 0x6
+ - Address: 0x0
+ Length: 0x3
+ - Address: 0x0
+ Length: 0x1
+ debug_ranges:
+ - Offset: 0x0
+ AddrSize: 0x8
+ Entries: []
+ - Offset: 0x10
+ AddrSize: 0x8
+ Entries: []
+ - Offset: 0x20
+ AddrSize: 0x8
+ Entries: []
+ - Offset: 0x30
+ AddrSize: 0x8
+ Entries: []
+ - Offset: 0x40
+ AddrSize: 0x8
+ Entries: []
+ - Offset: 0x50
+ AddrSize: 0x8
+ Entries: []
+ - Offset: 0x60
+ AddrSize: 0x8
+ Entries: []
+ - Offset: 0x70
+ AddrSize: 0x8
+ Entries: []
+ - Offset: 0x80
+ AddrSize: 0x8
+ Entries: []
+ - Offset: 0x90
+ AddrSize: 0x8
+ Entries: []
+...
diff --git a/lldb/test/API/macosx/find-dsym/bundle-with-dot-in-filename/Makefile b/lldb/test/API/macosx/find-dsym/bundle-with-dot-in-filename/Makefile
index 12781fd..f135840 100644
--- a/lldb/test/API/macosx/find-dsym/bundle-with-dot-in-filename/Makefile
+++ b/lldb/test/API/macosx/find-dsym/bundle-with-dot-in-filename/Makefile
@@ -5,7 +5,7 @@ all: clean $(EXE)
include Makefile.rules
$(EXE):
- $(CC) $(CFLAGS) -dynamiclib -o com.apple.sbd $(SRCDIR)/bundle.c
+ $(CC) $(ASAN_LDFLAGS) $(CFLAGS) -dynamiclib -o com.apple.sbd $(SRCDIR)/bundle.c
mkdir com.apple.sbd.xpc
mv com.apple.sbd com.apple.sbd.xpc/
mkdir -p com.apple.sbd.xpc.dSYM/Contents/Resources/DWARF
@@ -13,7 +13,7 @@ $(EXE):
rm -rf com.apple.sbd.dSYM
mkdir hide.app
tar cf - com.apple.sbd.xpc com.apple.sbd.xpc.dSYM | ( cd hide.app;tar xBpf -)
- $(CC) $(CFLAGS) -o find-bundle-with-dots-in-fn $(SRCDIR)/main.c
+ $(CC) $(ASAN_LDFLAGS) $(CFLAGS) -o find-bundle-with-dots-in-fn $(SRCDIR)/main.c
clean::
rm -rf a.out a.out.dSYM hide.app com.apple.sbd com.apple.sbd.dSYM com.apple.sbd.xpc com.apple.sbd.xpc.dSYM find-bundle-with-dots-in-fn find-bundle-with-dots-in-fn.dSYM
diff --git a/lldb/test/API/macosx/find-dsym/deep-bundle/Makefile b/lldb/test/API/macosx/find-dsym/deep-bundle/Makefile
index 806c840..c041d9e 100644
--- a/lldb/test/API/macosx/find-dsym/deep-bundle/Makefile
+++ b/lldb/test/API/macosx/find-dsym/deep-bundle/Makefile
@@ -4,7 +4,7 @@ all: clean $(EXE)
include Makefile.rules
$(EXE):
- $(CC) $(CFLAGS) -install_name $(shell pwd)/MyFramework.framework/Versions/A/MyFramework -dynamiclib -o MyFramework $(SRCDIR)/myframework.c
+ $(CC) $(ASAN_LDFLAGS) $(CFLAGS) -install_name $(shell pwd)/MyFramework.framework/Versions/A/MyFramework -dynamiclib -o MyFramework $(SRCDIR)/myframework.c
mkdir -p MyFramework.framework/Versions/A/Headers
mkdir -p MyFramework.framework/Versions/A/Resources
cp MyFramework MyFramework.framework/Versions/A
@@ -18,7 +18,7 @@ $(EXE):
mkdir hide.app
rm -f MyFramework
tar cf - MyFramework.framework MyFramework.framework.dSYM | ( cd hide.app;tar xBpf -)
- $(CC) $(CFLAGS) -o deep-bundle $(SRCDIR)/main.c -F. -framework MyFramework
+ $(CC) $(ASAN_LDFLAGS) $(CFLAGS) -o deep-bundle $(SRCDIR)/main.c -F. -framework MyFramework
clean::
rm -rf a.out a.out.dSYM deep-bundle deep-bundle.dSYM MyFramework.framework MyFramework.framework.dSYM MyFramework MyFramework.dSYM hide.app
diff --git a/lldb/test/API/macosx/posix_spawn/Makefile b/lldb/test/API/macosx/posix_spawn/Makefile
index 7ae46ca..cbdee91 100644
--- a/lldb/test/API/macosx/posix_spawn/Makefile
+++ b/lldb/test/API/macosx/posix_spawn/Makefile
@@ -6,13 +6,13 @@ include Makefile.rules
all: fat.out
x86_64.out: x86_64.c
- $(CC) -isysroot $(SDKROOT) -target x86_64-apple-macosx10.9 -o x86_64.out $<
+ $(CC) $(ASAN_LDFLAGS) -isysroot $(SDKROOT) -target x86_64-apple-macosx10.9 -o x86_64.out $<
x86_64h.out: x86_64h.c
- $(CC) -isysroot $(SDKROOT) -target x86_64h-apple-macosx10.9 -o x86_64h.out $<
+ $(CC) $(ASAN_LDFLAGS) -isysroot $(SDKROOT) -target x86_64h-apple-macosx10.9 -o x86_64h.out $<
arm64.out: arm64.c
- $(CC) -isysroot $(SDKROOT) -target arm64-apple-macosx10.9 -o arm64.out $<
+ $(CC) $(ASAN_LDFLAGS) -isysroot $(SDKROOT) -target arm64-apple-macosx10.9 -o arm64.out $<
fat.out: x86_64.out x86_64h.out arm64.out
$(LIPO) -o fat.out -create $^
diff --git a/lldb/test/API/python_api/command_script_output/TestCommandScriptOutput.py b/lldb/test/API/python_api/command_script_output/TestCommandScriptOutput.py
new file mode 100644
index 0000000..abe0eec
--- /dev/null
+++ b/lldb/test/API/python_api/command_script_output/TestCommandScriptOutput.py
@@ -0,0 +1,47 @@
+"""
+Test that HandleCommand captures stdout and stderr from script commands.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class CommandScriptOutputTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_script_command_stdout_stderr(self):
+ """Test that HandleCommand captures stdout and stderr from script commands."""
+ ci = self.dbg.GetCommandInterpreter()
+ self.assertTrue(ci, VALID_COMMAND_INTERPRETER)
+
+ res = lldb.SBCommandReturnObject()
+
+ # Execute a script command that writes to stdout.
+ ci.HandleCommand("script print('Hello stdout')", res)
+ self.assertTrue(res.Succeeded())
+ self.assertIn("Hello stdout", res.GetOutput())
+
+ # Execute a script command that writes to stderr.
+ ci.HandleCommand("script import sys; sys.stderr.write('Hello stderr\\n')", res)
+ self.assertTrue(res.Succeeded())
+ self.assertIn("Hello stderr", res.GetOutput())
+
+ # Execute a script command that writes to both stdout and stderr.
+ ci.HandleCommand(
+ "script import sys; print('Output line'); sys.stderr.write('Error line\\n')",
+ res,
+ )
+ self.assertTrue(res.Succeeded())
+ self.assertIn("Output line", res.GetOutput())
+ self.assertIn("Error line", res.GetOutput())
+
+ # Test that multiple print statements are captured.
+ ci.HandleCommand(
+ "script print('Line 1'); print('Line 2'); print('Line 3')", res
+ )
+ self.assertTrue(res.Succeeded())
+ output = res.GetOutput()
+ self.assertIn("Line 1", output)
+ self.assertIn("Line 2", output)
+ self.assertIn("Line 3", output)
diff --git a/lldb/test/API/python_api/exprpath_register/Makefile b/lldb/test/API/python_api/exprpath_register/Makefile
new file mode 100644
index 0000000..1049594
--- /dev/null
+++ b/lldb/test/API/python_api/exprpath_register/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/exprpath_register/TestExprPathRegisters.py b/lldb/test/API/python_api/exprpath_register/TestExprPathRegisters.py
new file mode 100644
index 0000000..4ffbc5e
--- /dev/null
+++ b/lldb/test/API/python_api/exprpath_register/TestExprPathRegisters.py
@@ -0,0 +1,64 @@
+"""
+Test Getting the expression path for registers works correctly
+"""
+
+import lldb
+from lldbsuite.test import lldbutil
+from lldbsuite.test.lldbtest import TestBase, VALID_BREAKPOINT, VALID_TARGET
+
+
+class TestExprPathRegisters(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def verify_register_path(self, reg_value: lldb.SBValue):
+ stream = lldb.SBStream()
+ reg_name = reg_value.name
+ self.assertTrue(
+ reg_value.GetExpressionPath(stream),
+ f"Expected an expression path for register {reg_name}.",
+ )
+ reg_expr_path = stream.GetData()
+ self.assertEqual(reg_expr_path, f"${reg_name}")
+
+ def test_float_registers(self):
+ """Verify the expression path of the registers is valid."""
+ self.build()
+ _, _, thread, _ = lldbutil.run_to_name_breakpoint(self, "my_foo")
+ frame = thread.GetSelectedFrame()
+ self.assertTrue(frame, "Expected a valid Frame.")
+
+ # possible floating point register on some cpus.
+ register_names = [
+ "xmm0",
+ "ymm0",
+ "v0",
+ "v1",
+ "f0",
+ "f1",
+ "d0",
+ "d1",
+ "vr0",
+ "vr1",
+ "st0",
+ "st1",
+ ]
+ for name in register_names:
+ reg_value = frame.FindRegister(name)
+ # some the register will not be available for the cpu
+ # only verify if it is valid.
+ if reg_value:
+ self.verify_register_path(reg_value)
+
+ def test_all_registers(self):
+ """Test all the registers that is avaiable on the machine"""
+ self.build()
+ _, _, thread, _ = lldbutil.run_to_name_breakpoint(self, "my_foo")
+ frame = thread.GetSelectedFrame()
+ self.assertTrue(frame, "Expected a valid Frame.")
+
+ register_sets = frame.GetRegisters()
+ self.assertTrue(register_sets.IsValid(), "Expected Frame Registers")
+
+ for register_set in register_sets:
+ for register in register_set.children:
+ self.verify_register_path(register)
diff --git a/lldb/test/API/python_api/exprpath_register/main.c b/lldb/test/API/python_api/exprpath_register/main.c
new file mode 100644
index 0000000..4809a87cd
--- /dev/null
+++ b/lldb/test/API/python_api/exprpath_register/main.c
@@ -0,0 +1,10 @@
+
+float my_foo() {
+ float result = 10.0 + 20.0;
+ return result;
+}
+
+int main(void) {
+ float result = my_foo();
+ return (int)result;
+}
diff --git a/lldb/test/API/python_api/frame_list/Makefile b/lldb/test/API/python_api/frame_list/Makefile
new file mode 100644
index 0000000..99998b2
--- /dev/null
+++ b/lldb/test/API/python_api/frame_list/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/frame_list/TestSBFrameList.py b/lldb/test/API/python_api/frame_list/TestSBFrameList.py
new file mode 100644
index 0000000..f348ce4
--- /dev/null
+++ b/lldb/test/API/python_api/frame_list/TestSBFrameList.py
@@ -0,0 +1,194 @@
+"""
+Test SBFrameList API.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class FrameListAPITestCase(TestBase):
+ def test_frame_list_api(self):
+ """Test SBThread.GetFrames() returns a valid SBFrameList."""
+ self.build()
+ self.frame_list_api()
+
+ def test_frame_list_iterator(self):
+ """Test SBFrameList iterator functionality."""
+ self.build()
+ self.frame_list_iterator()
+
+ def test_frame_list_indexing(self):
+ """Test SBFrameList indexing and length."""
+ self.build()
+ self.frame_list_indexing()
+
+ def test_frame_list_get_thread(self):
+ """Test SBFrameList.GetThread() returns correct thread."""
+ self.build()
+ self.frame_list_get_thread()
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.main_source = "main.cpp"
+
+ def frame_list_api(self):
+ """Test SBThread.GetFrames() returns a valid SBFrameList."""
+ exe = self.getBuildArtifact("a.out")
+
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Set break point at this line", lldb.SBFileSpec(self.main_source)
+ )
+
+ self.assertTrue(
+ thread.IsValid(), "There should be a thread stopped due to breakpoint"
+ )
+
+ # Test GetFrames() returns a valid SBFrameList
+ frame_list = thread.GetFrames()
+ self.assertTrue(frame_list.IsValid(), "Frame list should be valid")
+ self.assertGreater(
+ frame_list.GetSize(), 0, "Frame list should have at least one frame"
+ )
+
+ # Verify frame list size matches thread frame count
+ self.assertEqual(
+ frame_list.GetSize(),
+ thread.GetNumFrames(),
+ "Frame list size should match thread frame count",
+ )
+
+ # Verify frames are the same
+ for i in range(frame_list.GetSize()):
+ frame_from_list = frame_list.GetFrameAtIndex(i)
+ frame_from_thread = thread.GetFrameAtIndex(i)
+ self.assertTrue(
+ frame_from_list.IsValid(), f"Frame {i} from list should be valid"
+ )
+ self.assertEqual(
+ frame_from_list.GetPC(),
+ frame_from_thread.GetPC(),
+ f"Frame {i} PC should match",
+ )
+
+ def frame_list_iterator(self):
+ """Test SBFrameList iterator functionality."""
+ exe = self.getBuildArtifact("a.out")
+
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Set break point at this line", lldb.SBFileSpec(self.main_source)
+ )
+
+ self.assertTrue(
+ thread.IsValid(), "There should be a thread stopped due to breakpoint"
+ )
+
+ frame_list = thread.GetFrames()
+
+ # Test iteration
+ frame_count = 0
+ for frame in frame_list:
+ self.assertTrue(frame.IsValid(), "Each frame should be valid")
+ frame_count += 1
+
+ self.assertEqual(
+ frame_count,
+ frame_list.GetSize(),
+ "Iterator should visit all frames",
+ )
+
+ # Test that we can iterate multiple times
+ second_count = 0
+ for frame in frame_list:
+ second_count += 1
+
+ self.assertEqual(
+ frame_count, second_count, "Should be able to iterate multiple times"
+ )
+
+ def frame_list_indexing(self):
+ """Test SBFrameList indexing and length."""
+ exe = self.getBuildArtifact("a.out")
+
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Set break point at this line", lldb.SBFileSpec(self.main_source)
+ )
+
+ self.assertTrue(
+ thread.IsValid(), "There should be a thread stopped due to breakpoint"
+ )
+
+ frame_list = thread.GetFrames()
+
+ # Test len()
+ self.assertEqual(
+ len(frame_list), frame_list.GetSize(), "len() should return frame count"
+ )
+
+ # Test positive indexing
+ first_frame = frame_list[0]
+ self.assertTrue(first_frame.IsValid(), "First frame should be valid")
+ self.assertEqual(
+ first_frame.GetPC(),
+ thread.GetFrameAtIndex(0).GetPC(),
+ "Indexed frame should match",
+ )
+
+ # Test negative indexing
+ if len(frame_list) > 0:
+ last_frame = frame_list[-1]
+ self.assertTrue(last_frame.IsValid(), "Last frame should be valid")
+ self.assertEqual(
+ last_frame.GetPC(),
+ thread.GetFrameAtIndex(len(frame_list) - 1).GetPC(),
+ "Negative indexing should work",
+ )
+
+ # Test out of bounds returns None
+ out_of_bounds = frame_list[10000]
+ self.assertIsNone(out_of_bounds, "Out of bounds index should return None")
+
+ # Test bool conversion
+ self.assertTrue(bool(frame_list), "Non-empty frame list should be truthy")
+
+ # Test Clear()
+ frame_list.Clear()
+ # Note: Clear() clears the underlying StackFrameList cache,
+ # but the frame list object itself should still be valid
+ self.assertTrue(
+ frame_list.IsValid(), "Frame list should still be valid after Clear()"
+ )
+
+ def frame_list_get_thread(self):
+ """Test SBFrameList.GetThread() returns correct thread."""
+ exe = self.getBuildArtifact("a.out")
+
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Set break point at this line", lldb.SBFileSpec(self.main_source)
+ )
+
+ self.assertTrue(
+ thread.IsValid(), "There should be a thread stopped due to breakpoint"
+ )
+
+ frame_list = thread.GetFrames()
+ self.assertTrue(frame_list.IsValid(), "Frame list should be valid")
+
+ # Test GetThread() returns the correct thread
+ thread_from_list = frame_list.GetThread()
+ self.assertTrue(
+ thread_from_list.IsValid(), "Thread from frame list should be valid"
+ )
+ self.assertEqual(
+ thread_from_list.GetThreadID(),
+ thread.GetThreadID(),
+ "Frame list should return the correct thread",
+ )
+
+ # Verify it's the same thread object
+ self.assertEqual(
+ thread_from_list.GetProcess().GetProcessID(),
+ thread.GetProcess().GetProcessID(),
+ "Thread should belong to same process",
+ )
diff --git a/lldb/test/API/python_api/frame_list/main.cpp b/lldb/test/API/python_api/frame_list/main.cpp
new file mode 100644
index 0000000..e399446
--- /dev/null
+++ b/lldb/test/API/python_api/frame_list/main.cpp
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+int c(int val) {
+ // Set break point at this line
+ return val + 3;
+}
+
+int b(int val) {
+ int result = c(val);
+ return result;
+}
+
+int a(int val) {
+ int result = b(val);
+ return result;
+}
+
+int main() {
+ int result = a(1);
+ printf("Result: %d\n", result);
+ return 0;
+}
diff --git a/lldb/test/API/python_api/sblineentry/TestSBLineEntry.py b/lldb/test/API/python_api/sblineentry/TestSBLineEntry.py
new file mode 100644
index 0000000..ee8404c
--- /dev/null
+++ b/lldb/test/API/python_api/sblineentry/TestSBLineEntry.py
@@ -0,0 +1,144 @@
+"""
+Test SBLineEntry APIs, particularly synthetic line entries.
+"""
+
+import os
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class SBLineEntryTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_synthetic_line_entry(self):
+ """Test that synthetic LineEntry objects (created via SBAPI) can be
+ valid without a valid address range and can be set in SBSymbolContext."""
+
+ # Test creating a synthetic line entry via SBAPI.
+ line_entry = lldb.SBLineEntry()
+ self.assertFalse(
+ line_entry.IsValid(), "Default constructed line entry should be invalid"
+ )
+
+ # Set line number - this should mark the line entry as synthetic.
+ line_entry.SetLine(42)
+ self.assertTrue(
+ line_entry.IsValid(),
+ "Line entry should be valid after setting line, even without address",
+ )
+ self.assertEqual(line_entry.GetLine(), 42)
+
+ # Set file and column.
+ file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "test.cpp"), True)
+ line_entry.SetFileSpec(file_spec)
+ line_entry.SetColumn(10)
+
+ self.assertEqual(line_entry.GetColumn(), 10)
+ self.assertEqual(line_entry.GetFileSpec().GetFilename(), "test.cpp")
+
+ # Verify address range is still invalid (synthetic).
+ start_addr = line_entry.GetStartAddress()
+ self.assertFalse(
+ start_addr.IsValid(), "Synthetic line entry should not have valid address"
+ )
+
+ # Test setting synthetic line entry in symbol context.
+ sym_ctx = lldb.SBSymbolContext()
+ sym_ctx.SetLineEntry(line_entry)
+
+ retrieved_line_entry = sym_ctx.GetLineEntry()
+ self.assertTrue(
+ retrieved_line_entry.IsValid(), "Retrieved line entry should be valid"
+ )
+ self.assertEqual(retrieved_line_entry.GetLine(), 42)
+ self.assertEqual(retrieved_line_entry.GetColumn(), 10)
+ self.assertEqual(retrieved_line_entry.GetFileSpec().GetFilename(), "test.cpp")
+
+ def test_line_entry_validity_without_address(self):
+ """Test that line entries created via SBAPI are valid without addresses."""
+
+ line_entry = lldb.SBLineEntry()
+
+ # Initially invalid.
+ self.assertFalse(line_entry.IsValid())
+
+ # Still invalid with just a file spec.
+ file_spec = lldb.SBFileSpec("foo.cpp", True)
+ line_entry.SetFileSpec(file_spec)
+ self.assertFalse(
+ line_entry.IsValid(), "Line entry should be invalid without line number"
+ )
+
+ # Valid once line number is set (marks as synthetic).
+ line_entry.SetLine(100)
+ self.assertTrue(
+ line_entry.IsValid(), "Line entry should be valid with line number set"
+ )
+
+ # Verify no valid address range.
+ self.assertFalse(line_entry.GetStartAddress().IsValid())
+ self.assertFalse(line_entry.GetEndAddress().IsValid())
+
+ def test_line_entry_column(self):
+ """Test setting and getting column information on synthetic line entries."""
+
+ line_entry = lldb.SBLineEntry()
+ line_entry.SetLine(50)
+
+ # Default column should be 0.
+ self.assertEqual(line_entry.GetColumn(), 0)
+
+ # Set column.
+ line_entry.SetColumn(25)
+ self.assertEqual(line_entry.GetColumn(), 25)
+
+ # Verify line entry is still valid.
+ self.assertTrue(line_entry.IsValid())
+
+ def test_non_synthetic_line_entry_requires_line_number(self):
+ """Test that non-synthetic line entries with addresses still require a line number to be valid."""
+
+ # A line entry is always invalid without a line number, regardless of whether it has an address.
+ line_entry = lldb.SBLineEntry()
+ self.assertFalse(
+ line_entry.IsValid(), "Line entry should be invalid without line number"
+ )
+
+ # Even with a file spec, it's still invalid.
+ file_spec = lldb.SBFileSpec("test.cpp", True)
+ line_entry.SetFileSpec(file_spec)
+ self.assertFalse(
+ line_entry.IsValid(), "Line entry should be invalid without line number"
+ )
+
+ # Only after setting a line number does it become valid.
+ line_entry.SetLine(42)
+ self.assertTrue(
+ line_entry.IsValid(), "Line entry should be valid with line number"
+ )
+
+ def test_symbol_context_with_synthetic_line_entry(self):
+ """Test that SBSymbolContext correctly stores and retrieves synthetic line entries."""
+
+ # Create a synthetic line entry.
+ line_entry = lldb.SBLineEntry()
+ line_entry.SetLine(123)
+ line_entry.SetColumn(45)
+ file_spec = lldb.SBFileSpec("source.cpp", True)
+ line_entry.SetFileSpec(file_spec)
+
+ # Create symbol context and set line entry.
+ sym_ctx = lldb.SBSymbolContext()
+ sym_ctx.SetLineEntry(line_entry)
+
+ # Retrieve and verify.
+ retrieved = sym_ctx.GetLineEntry()
+ self.assertTrue(retrieved.IsValid())
+ self.assertEqual(retrieved.GetLine(), 123)
+ self.assertEqual(retrieved.GetColumn(), 45)
+ self.assertEqual(retrieved.GetFileSpec().GetFilename(), "source.cpp")
+
+ # Verify it's still synthetic (no valid address).
+ self.assertFalse(retrieved.GetStartAddress().IsValid())
diff --git a/lldb/test/API/python_api/target/TestTargetAPI.py b/lldb/test/API/python_api/target/TestTargetAPI.py
index d346563..d3c64d8 100644
--- a/lldb/test/API/python_api/target/TestTargetAPI.py
+++ b/lldb/test/API/python_api/target/TestTargetAPI.py
@@ -105,6 +105,24 @@ class TargetAPITestCase(TestBase):
self.assertIsNotNone(data_section2)
self.assertEqual(data_section.name, data_section2.name)
+ def test_get_arch_name(self):
+ d = {"EXE": "b.out"}
+ self.build(dictionary=d)
+ self.setTearDownCleanup(dictionary=d)
+ target = self.create_simple_target("b.out")
+
+ arch_name = target.arch_name
+ self.assertTrue(len(arch_name) > 0, "Got an arch name")
+
+ # Test consistency with triple.
+ triple = target.triple
+ self.assertTrue(len(triple) > 0, "Got a triple")
+ self.assertEqual(
+ triple.split("-")[0],
+ arch_name,
+ "Arch name is equal to the first item of the triple",
+ )
+
def test_get_ABIName(self):
d = {"EXE": "b.out"}
self.build(dictionary=d)
diff --git a/lldb/test/API/python_api/unified_section_list/Makefile b/lldb/test/API/python_api/unified_section_list/Makefile
new file mode 100644
index 0000000..431e716
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/Makefile
@@ -0,0 +1,5 @@
+CXX_SOURCES := main.cpp
+
+SPLIT_DEBUG_SYMBOLS := YES
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py b/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
new file mode 100644
index 0000000..93b23d0
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/TestModuleUnifiedSectionList.py
@@ -0,0 +1,285 @@
+"""
+Test Unified Section List merging.
+"""
+
+import os
+import shutil
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+from lldbsuite.test.lldbutil import symbol_type_to_str
+
+
+class ModuleUnifiedSectionList(TestBase):
+ @skipUnlessPlatform(["linux", "freebsd", "netbsd"])
+ def test_unified_section_list(self):
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ debug_info = self.getBuildArtifact("a.out.debug")
+ new_dir = os.path.join(os.path.dirname(debug_info), "new_dir")
+ os.mkdir(new_dir)
+ renamed_debug_info = os.path.join(new_dir, "renamed.debug")
+ os.rename(debug_info, renamed_debug_info)
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+ self.assertGreater(target.GetNumModules(), 0)
+
+ main_exe_module = target.GetModuleAtIndex(0)
+ eh_frame = main_exe_module.FindSection(".eh_frame")
+ self.assertTrue(eh_frame.IsValid())
+ self.assertGreater(eh_frame.size, 0)
+
+ # Should be stripped in main executable.
+ debug_info_section = main_exe_module.FindSection(".debug_info")
+ self.assertFalse(debug_info_section.IsValid())
+
+ ci = self.dbg.GetCommandInterpreter()
+ res = lldb.SBCommandReturnObject()
+ ci.HandleCommand(f"target symbols add {renamed_debug_info}", res)
+ self.assertTrue(res.Succeeded())
+
+ # Should be stripped in .debuginfo but be present in main executable.
+ main_exe_module = target.GetModuleAtIndex(0)
+ eh_frame = main_exe_module.FindSection(".eh_frame")
+ self.assertTrue(eh_frame.IsValid())
+ self.assertGreater(eh_frame.size, 0)
+
+ # Should be unified and both sections should have contents.
+ debug_info_section = main_exe_module.FindSection(".debug_info")
+ self.assertTrue(debug_info_section.IsValid())
+ self.assertGreater(debug_info_section.file_size, 0)
+
+ def test_unified_section_list_overwrite_larger_section(self):
+ """
+ Test the merging of an ELF file with another ELF File where all the new sections are bigger, validating we
+ overwrite .comment from SHT_NOBITS to the new SHT_PROGBITS section and the smaller .text with the larger
+ .text
+ """
+ exe = self.getBuildArtifact("a.out")
+ self.yaml2obj("main.yaml", exe)
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+ main_exe_module = target.GetModuleAtIndex(0)
+
+ # First we verify out .text section is the expected BEC0FFEE
+ text_before_merge = main_exe_module.FindSection(".text")
+ self.assertTrue(text_before_merge.IsValid())
+ error = lldb.SBError()
+ section_content = text_before_merge.data.ReadRawData(
+ error, 0, text_before_merge.data.size
+ )
+ self.assertTrue(error.Success())
+ self.assertEqual(section_content, bytes.fromhex("BEC0FFEE"))
+
+ # .comment in main.yaml should be SHT_NOBITS, and size 0
+ comment_before_merge = main_exe_module.FindSection(".comment")
+ self.assertTrue(comment_before_merge.IsValid())
+ self.assertEqual(comment_before_merge.data.size, 0)
+
+ # yamlize the main.largertext.yaml and force symbol loading
+ debug_info = self.getBuildArtifact("a.out.debug")
+ self.yaml2obj("main.largertext.yaml", debug_info)
+
+ ci = self.dbg.GetCommandInterpreter()
+ res = lldb.SBCommandReturnObject()
+ ci.HandleCommand(f"target symbols add {debug_info}", res)
+ self.assertTrue(res.Succeeded())
+
+ # verify we took the larger .text section
+ main_exe_module_after_merge = target.GetModuleAtIndex(0)
+ text_after_merge = main_exe_module_after_merge.FindSection(".text")
+ self.assertTrue(text_after_merge.IsValid())
+ self.assertGreater(text_after_merge.data.size, text_before_merge.data.size)
+ section_content_after_merge = text_after_merge.data.ReadRawData(
+ error, 0, text_after_merge.data.size
+ )
+ self.assertTrue(error.Success())
+ self.assertEqual(section_content_after_merge, bytes.fromhex("BEC0FFEEEEFF0CEB"))
+
+ # in main.largertext.yaml comment is not SHT_NOBITS, and so we should see
+ # the size > 0 and equal to BAADF00D
+ comment_after_merge = main_exe_module_after_merge.FindSection(".comment")
+ self.assertTrue(comment_after_merge.IsValid())
+ comment_content_after_merge = comment_after_merge.data.ReadRawData(
+ error, 0, comment_after_merge.data.size
+ )
+
+ self.assertTrue(error.Success())
+ self.assertEqual(comment_content_after_merge, bytes.fromhex("BAADF00D"))
+
+ def test_unified_section_list_overwrite_smaller_section(self):
+ """
+ Test the merging of an ELF file with another ELF File where all the existing sections are bigger, validating we don't
+ overwrite with the SHT_NOBITS for .comment or the smaller .text section.
+ """
+ exe = self.getBuildArtifact("a.out")
+ self.yaml2obj("main.largertext.yaml", exe)
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+ main_exe_module = target.GetModuleAtIndex(0)
+
+ # Same as above test but inverse, verify our larger .text section
+ # is the expected BEC0FFEE palindrome
+ text_before_merge = main_exe_module.FindSection(".text")
+ self.assertTrue(text_before_merge.IsValid())
+ error = lldb.SBError()
+ section_content = text_before_merge.data.ReadRawData(
+ error, 0, text_before_merge.data.size
+ )
+ self.assertTrue(error.Success())
+ self.assertEqual(section_content, bytes.fromhex("BEC0FFEEEEFF0CEB"))
+
+ # Comment is SHT_PROGBITS on the larger yaml and should remain
+ # the same after merge.
+ comment_before_merge = main_exe_module.FindSection(".comment")
+ self.assertTrue(comment_before_merge.IsValid())
+ comment_content = comment_before_merge.data.ReadRawData(
+ error, 0, comment_before_merge.data.size
+ )
+
+ self.assertTrue(error.Success())
+ self.assertEqual(comment_content, bytes.fromhex("BAADF00D"))
+
+ debug_info = self.getBuildArtifact("a.out.debug")
+ self.yaml2obj("main.yaml", debug_info)
+
+ ci = self.dbg.GetCommandInterpreter()
+ res = lldb.SBCommandReturnObject()
+ ci.HandleCommand(f"target symbols add {debug_info}", res)
+ self.assertTrue(res.Succeeded())
+
+ # Verify we didn't replace the sections after merge.s
+ main_exe_module_after_merge = target.GetModuleAtIndex(0)
+ text_after_merge = main_exe_module_after_merge.FindSection(".text")
+ self.assertTrue(text_after_merge.IsValid())
+ self.assertEqual(text_after_merge.data.size, text_before_merge.data.size)
+ section_content_after_merge = text_after_merge.data.ReadRawData(
+ error, 0, text_after_merge.data.size
+ )
+ self.assertTrue(error.Success())
+ self.assertEqual(section_content_after_merge, bytes.fromhex("BEC0FFEEEEFF0CEB"))
+
+ comment_after_merge = main_exe_module_after_merge.FindSection(".comment")
+ self.assertTrue(comment_after_merge.IsValid())
+ comment_content_after_merge = comment_after_merge.data.ReadRawData(
+ error, 0, comment_after_merge.data.size
+ )
+
+ self.assertTrue(error.Success())
+ self.assertEqual(comment_content_after_merge, bytes.fromhex("BAADF00D"))
+
+ def test_unified_section_list_overwrite_mixed_merge(self):
+ """
+ Test the merging of an ELF file with another ELF File where the lhs has a larger .comment section
+ and the RHS has a larger .text section.
+ """
+ exe = self.getBuildArtifact("a.out")
+ self.yaml2obj("main.largercomment.yaml", exe)
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+ main_exe_module = target.GetModuleAtIndex(0)
+
+ # Verify we have the expected smaller BEC0FFEE
+ text_before_merge = main_exe_module.FindSection(".text")
+ self.assertTrue(text_before_merge.IsValid())
+ error = lldb.SBError()
+ section_content = text_before_merge.data.ReadRawData(
+ error, 0, text_before_merge.data.size
+ )
+ self.assertTrue(error.Success())
+ self.assertEqual(section_content, bytes.fromhex("BEC0FFEE"))
+
+ # Verify we have the larger palindromic comment
+ comment_before_merge = main_exe_module.FindSection(".comment")
+ self.assertTrue(comment_before_merge.IsValid())
+ comment_content = comment_before_merge.data.ReadRawData(
+ error, 0, comment_before_merge.data.size
+ )
+
+ self.assertTrue(error.Success())
+ self.assertEqual(comment_content, bytes.fromhex("BAADF00DF00DBAAD"))
+
+ debug_info = self.getBuildArtifact("a.out.debug")
+ self.yaml2obj("main.largertext.yaml", debug_info)
+
+ ci = self.dbg.GetCommandInterpreter()
+ res = lldb.SBCommandReturnObject()
+ ci.HandleCommand(f"target symbols add {debug_info}", res)
+ self.assertTrue(res.Succeeded())
+
+ # Verify we replaced .text
+ main_exe_module_after_merge = target.GetModuleAtIndex(0)
+ text_after_merge = main_exe_module_after_merge.FindSection(".text")
+ self.assertTrue(text_after_merge.IsValid())
+ section_content_after_merge = text_after_merge.data.ReadRawData(
+ error, 0, text_after_merge.data.size
+ )
+ self.assertTrue(error.Success())
+ self.assertEqual(section_content_after_merge, bytes.fromhex("BEC0FFEEEEFF0CEB"))
+
+ # Verify .comment is still the same.
+ comment_after_merge = main_exe_module_after_merge.FindSection(".comment")
+ self.assertTrue(comment_after_merge.IsValid())
+ comment_content_after_merge = comment_after_merge.data.ReadRawData(
+ error, 0, comment_after_merge.data.size
+ )
+
+ self.assertTrue(error.Success())
+ self.assertEqual(comment_content_after_merge, bytes.fromhex("BAADF00DF00DBAAD"))
+
+ def test_unified_section_list_overwrite_equal_size(self):
+ """
+ Test the merging of an ELF file with an ELF file with sections of the same size with different values
+ .text
+ """
+ exe = self.getBuildArtifact("a.out")
+ self.yaml2obj("main.yaml", exe)
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+ main_exe_module = target.GetModuleAtIndex(0)
+
+ # First we verify out .text section is the expected BEC0FFEE
+ text_before_merge = main_exe_module.FindSection(".text")
+ self.assertTrue(text_before_merge.IsValid())
+ error = lldb.SBError()
+ section_content = text_before_merge.data.ReadRawData(
+ error, 0, text_before_merge.data.size
+ )
+ self.assertTrue(error.Success())
+ self.assertEqual(section_content, bytes.fromhex("BEC0FFEE"))
+
+ # .comment in main.yaml should be SHT_NOBITS, and size 0
+ comment_before_merge = main_exe_module.FindSection(".comment")
+ self.assertTrue(comment_before_merge.IsValid())
+ self.assertEqual(comment_before_merge.data.size, 0)
+
+ # yamlize the main with the .text reversed from BEC0FFEE
+ # to EEFF0CEB. We should still keep our .text with BEC0FFEE
+ debug_info = self.getBuildArtifact("a.out.debug")
+ self.yaml2obj("main.reversedtext.yaml", debug_info)
+
+ ci = self.dbg.GetCommandInterpreter()
+ res = lldb.SBCommandReturnObject()
+ ci.HandleCommand(f"target symbols add {debug_info}", res)
+ self.assertTrue(res.Succeeded())
+
+ # verify .text did not change
+ main_exe_module_after_merge = target.GetModuleAtIndex(0)
+ text_after_merge = main_exe_module_after_merge.FindSection(".text")
+ self.assertTrue(text_after_merge.IsValid())
+ section_content_after_merge = text_after_merge.data.ReadRawData(
+ error, 0, text_after_merge.data.size
+ )
+ self.assertTrue(error.Success())
+ self.assertEqual(section_content_after_merge, bytes.fromhex("BEC0FFEE"))
+
+ # verify comment did not change
+ comment_afer_merge = main_exe_module_after_merge.FindSection(".comment")
+ self.assertTrue(comment_afer_merge.IsValid())
+ self.assertEqual(comment_afer_merge.data.size, 0)
diff --git a/lldb/test/API/python_api/unified_section_list/main.cpp b/lldb/test/API/python_api/unified_section_list/main.cpp
new file mode 100644
index 0000000..45fd52e
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/main.cpp
@@ -0,0 +1,3 @@
+#include <stdio.h>
+
+int main() { printf("Hello World\n"); }
diff --git a/lldb/test/API/python_api/unified_section_list/main.largercomment.yaml b/lldb/test/API/python_api/unified_section_list/main.largercomment.yaml
new file mode 100644
index 0000000..f786006
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/main.largercomment.yaml
@@ -0,0 +1,46 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+ Entry: 0x1040
+ProgramHeaders:
+ - Type: PT_PHDR
+ Flags: [ PF_R ]
+ VAddr: 0x40
+ Align: 0x8
+ Offset: 0x40
+ - Type: PT_LOAD
+ Flags: [ PF_R ]
+ FirstSec: .text
+ LastSec: .fini
+ Align: 0x1000
+ Offset: 0x0
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1040
+ AddressAlign: 0x10
+ Content: BEC0FFEE
+ - Name: .fini
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1140
+ AddressAlign: 0x4
+ Content: DEADBEEF
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x3140
+ AddressAlign: 0x4
+ Content: BAADF00DF00DBAAD
+Symbols:
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1130
+ Size: 0xF
+...
diff --git a/lldb/test/API/python_api/unified_section_list/main.largertext.yaml b/lldb/test/API/python_api/unified_section_list/main.largertext.yaml
new file mode 100644
index 0000000..6450e67
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/main.largertext.yaml
@@ -0,0 +1,46 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+ Entry: 0x1040
+ProgramHeaders:
+ - Type: PT_PHDR
+ Flags: [ PF_R ]
+ VAddr: 0x40
+ Align: 0x8
+ Offset: 0x40
+ - Type: PT_LOAD
+ Flags: [ PF_R ]
+ FirstSec: .text
+ LastSec: .fini
+ Align: 0x1000
+ Offset: 0x0
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1040
+ AddressAlign: 0x10
+ Content: BEC0FFEEEEFF0CEB
+ - Name: .fini
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1140
+ AddressAlign: 0x4
+ Content: DEADBEEF
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x3140
+ AddressAlign: 0x4
+ Content: BAADF00D
+Symbols:
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1130
+ Size: 0xF
+...
diff --git a/lldb/test/API/python_api/unified_section_list/main.reversedtext.yaml b/lldb/test/API/python_api/unified_section_list/main.reversedtext.yaml
new file mode 100644
index 0000000..5720666
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/main.reversedtext.yaml
@@ -0,0 +1,45 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+ Entry: 0x1040
+ProgramHeaders:
+ - Type: PT_PHDR
+ Flags: [ PF_R ]
+ VAddr: 0x40
+ Align: 0x8
+ Offset: 0x40
+ - Type: PT_LOAD
+ Flags: [ PF_R ]
+ FirstSec: .text
+ LastSec: .fini
+ Align: 0x1000
+ Offset: 0x0
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1040
+ AddressAlign: 0x10
+ Content: BEC0FFEE
+ - Name: .fini
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1140
+ AddressAlign: 0x4
+ Content: DEADBEEF
+ - Name: .comment
+ Type: SHT_NOBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x3140
+ AddressAlign: 0x4
+Symbols:
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1130
+ Size: 0xF
+...
diff --git a/lldb/test/API/python_api/unified_section_list/main.yaml b/lldb/test/API/python_api/unified_section_list/main.yaml
new file mode 100644
index 0000000..5720666
--- /dev/null
+++ b/lldb/test/API/python_api/unified_section_list/main.yaml
@@ -0,0 +1,45 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+ Entry: 0x1040
+ProgramHeaders:
+ - Type: PT_PHDR
+ Flags: [ PF_R ]
+ VAddr: 0x40
+ Align: 0x8
+ Offset: 0x40
+ - Type: PT_LOAD
+ Flags: [ PF_R ]
+ FirstSec: .text
+ LastSec: .fini
+ Align: 0x1000
+ Offset: 0x0
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1040
+ AddressAlign: 0x10
+ Content: BEC0FFEE
+ - Name: .fini
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1140
+ AddressAlign: 0x4
+ Content: DEADBEEF
+ - Name: .comment
+ Type: SHT_NOBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x3140
+ AddressAlign: 0x4
+Symbols:
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1130
+ Size: 0xF
+...
diff --git a/lldb/test/API/symbol_ondemand/breakpoint_source_regex/TestSourceTextRegexBreakpoint.py b/lldb/test/API/symbol_ondemand/breakpoint_source_regex/TestSourceTextRegexBreakpoint.py
index 8bf294b..6904d8e 100644
--- a/lldb/test/API/symbol_ondemand/breakpoint_source_regex/TestSourceTextRegexBreakpoint.py
+++ b/lldb/test/API/symbol_ondemand/breakpoint_source_regex/TestSourceTextRegexBreakpoint.py
@@ -20,7 +20,9 @@ class TestSourceTextRegexBreakpoint(TestBase):
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
- lldbutil.run_break_set_by_source_regexp(self, "Set break point at this line.")
+ lldbutil.run_break_set_by_source_regexp(
+ self, "Set break point at this line.", extra_options="-f main.cpp"
+ )
self.runCmd("run", RUN_SUCCEEDED)
# The stop reason of the thread should be breakpoint.
diff --git a/lldb/test/API/terminal/TestEditline.py b/lldb/test/API/terminal/TestEditline.py
index 38f4f34..4696b1e 100644
--- a/lldb/test/API/terminal/TestEditline.py
+++ b/lldb/test/API/terminal/TestEditline.py
@@ -94,7 +94,7 @@ class EditlineTest(PExpectTest):
# after the prompt.
self.child.send("foo")
# Check that there are no escape codes.
- self.child.expect(re.escape("\n(lldb) foo"))
+ self.child.expect(re.escape("\n\r\x1b[K(lldb) foo"))
@skipIfAsan
@skipIfEditlineSupportMissing
diff --git a/lldb/test/API/test_utils/pdb/Makefile b/lldb/test/API/test_utils/pdb/Makefile
new file mode 100644
index 0000000..99998b2
--- /dev/null
+++ b/lldb/test/API/test_utils/pdb/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/test_utils/pdb/TestPdb.py b/lldb/test/API/test_utils/pdb/TestPdb.py
new file mode 100644
index 0000000..bd3a9d0
--- /dev/null
+++ b/lldb/test/API/test_utils/pdb/TestPdb.py
@@ -0,0 +1,18 @@
+"""
+Test PDB enabled tests
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class TestBuildMethod(TestBase):
+ TEST_WITH_PDB_DEBUG_INFO = True
+
+ def test(self):
+ self.build()
+ self.assertTrue(self.dbg.CreateTarget(self.getBuildArtifact()))
+ if self.getDebugInfo() == "pdb":
+ self.expect(
+ "target modules dump symfile", patterns=["SymbolFile (native-)?pdb"]
+ )
diff --git a/lldb/test/API/test_utils/pdb/main.cpp b/lldb/test/API/test_utils/pdb/main.cpp
new file mode 100644
index 0000000..76e8197
--- /dev/null
+++ b/lldb/test/API/test_utils/pdb/main.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
index 2db00a5..d628739 100644
--- a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
+++ b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
@@ -75,3 +75,38 @@ class TestDAP_attach(lldbdap_testcase.DAPTestCaseBase):
self.spawn_thread.start()
self.attach(program=program, waitFor=True)
self.continue_and_verify_pid()
+
+ def test_attach_with_missing_debuggerId_or_targetId(self):
+ """
+ Test that attaching with only one of debuggerId/targetId specified
+ fails with the expected error message.
+ """
+ self.build_and_create_debug_adapter()
+
+ # Test with only targetId specified (no debuggerId)
+ resp = self.attach(targetId=99999, expectFailure=True)
+ self.assertFalse(resp["success"])
+ self.assertIn(
+ "Both debuggerId and targetId must be specified together",
+ resp["body"]["error"]["format"],
+ )
+
+ def test_attach_with_invalid_debuggerId_and_targetId(self):
+ """
+ Test that attaching with both debuggerId and targetId specified but
+ invalid fails with an appropriate error message.
+ """
+ self.build_and_create_debug_adapter()
+
+ # Attach with both debuggerId=9999 and targetId=99999 (both invalid).
+ # Since debugger ID 9999 likely doesn't exist in the global registry,
+ # we expect a validation error.
+ resp = self.attach(debuggerId=9999, targetId=99999, expectFailure=True)
+ self.assertFalse(resp["success"])
+ error_msg = resp["body"]["error"]["format"]
+ # Either error is acceptable - both indicate the debugger reuse
+ # validation is working correctly
+ self.assertTrue(
+ "Unable to find existing debugger" in error_msg
+ or f"Expected debugger/target not found error, got: {error_msg}"
+ )
diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
index a542a31..df029ca 100644
--- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
@@ -39,18 +39,21 @@ class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase):
{"dataId": response_x["body"]["dataId"], "accessType": "write"},
]
set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
- self.assertEqual(
- set_response["body"]["breakpoints"],
- [{"verified": False}, {"verified": True}, {"verified": True}],
- )
+ breakpoints = set_response["body"]["breakpoints"]
+ self.assertEqual(len(breakpoints), 3)
+ self.assertFalse(breakpoints[0]["verified"])
+ self.assertTrue(breakpoints[1]["verified"])
+ self.assertTrue(breakpoints[2]["verified"])
- self.continue_to_next_stop()
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[2]["id"]])
x_val = self.dap_server.get_local_variable_value("x")
i_val = self.dap_server.get_local_variable_value("i")
self.assertEqual(x_val, "2")
self.assertEqual(i_val, "1")
- self.continue_to_next_stop()
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[1]["id"]])
arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
i_val = self.dap_server.get_local_variable_value("i")
self.assertEqual(arr_2["value"], "42")
@@ -79,18 +82,20 @@ class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase):
{"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
]
set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
- self.assertEqual(
- set_response["body"]["breakpoints"],
- [{"verified": True}, {"verified": True}],
- )
+ breakpoints = set_response["body"]["breakpoints"]
+ self.assertEqual(len(breakpoints), 2)
+ self.assertTrue(breakpoints[0]["verified"])
+ self.assertTrue(breakpoints[1]["verified"])
- self.continue_to_next_stop()
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[0]["id"]])
x_val = self.dap_server.get_local_variable_value("x")
i_val = self.dap_server.get_local_variable_value("i")
self.assertEqual(x_val, "2")
self.assertEqual(i_val, "1")
- self.continue_to_next_stop()
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[1]["id"]])
arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
i_val = self.dap_server.get_local_variable_value("i")
self.assertEqual(arr_2["value"], "42")
@@ -123,18 +128,20 @@ class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase):
{"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
]
set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
- self.assertEqual(
- set_response["body"]["breakpoints"],
- [{"verified": True}, {"verified": True}],
- )
+ breakpoints = set_response["body"]["breakpoints"]
+ self.assertEqual(len(breakpoints), 2)
+ self.assertTrue(breakpoints[0]["verified"])
+ self.assertTrue(breakpoints[1]["verified"])
- self.continue_to_next_stop()
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[0]["id"]])
x_val = self.dap_server.get_local_variable_value("x")
i_val = self.dap_server.get_local_variable_value("i")
self.assertEqual(x_val, "2")
self.assertEqual(i_val, "1")
- self.continue_to_next_stop()
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[1]["id"]])
arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
i_val = self.dap_server.get_local_variable_value("i")
self.assertEqual(arr_2["value"], "42")
@@ -153,8 +160,11 @@ class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase):
}
]
set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
- self.assertEqual(set_response["body"]["breakpoints"], [{"verified": True}])
- self.continue_to_next_stop()
+ breakpoints = set_response["body"]["breakpoints"]
+ self.assertEqual(len(breakpoints), 1)
+ self.assertTrue(breakpoints[0]["verified"])
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[0]["id"]])
x_val = self.dap_server.get_local_variable_value("x")
self.assertEqual(x_val, "3")
@@ -167,7 +177,64 @@ class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase):
}
]
set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
- self.assertEqual(set_response["body"]["breakpoints"], [{"verified": True}])
- self.continue_to_next_stop()
+ breakpoints = set_response["body"]["breakpoints"]
+ self.assertEqual(len(breakpoints), 1)
+ self.assertTrue(breakpoints[0]["verified"])
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[0]["id"]])
x_val = self.dap_server.get_local_variable_value("x")
self.assertEqual(x_val, "10")
+
+ @skipIfWindows
+ def test_bytes(self):
+ """Tests setting data breakpoints on memory range."""
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ source = "main.cpp"
+ first_loop_break_line = line_number(source, "// first loop breakpoint")
+ self.set_source_breakpoints(source, [first_loop_break_line])
+ self.continue_to_next_stop()
+ # Test write watchpoints on x, arr[2]
+ x = self.dap_server.get_local_variable("x")
+ response_x = self.dap_server.request_dataBreakpointInfo(
+ 0, x["memoryReference"], 4
+ )
+ arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
+ response_arr_2 = self.dap_server.request_dataBreakpointInfo(
+ 0, arr_2["memoryReference"], 4
+ )
+
+ # Test response from dataBreakpointInfo request.
+ self.assertEqual(
+ response_x["body"]["dataId"].split("/"), [x["memoryReference"][2:], "4"]
+ )
+ self.assertEqual(response_x["body"]["accessTypes"], self.accessTypes)
+ self.assertEqual(
+ response_arr_2["body"]["dataId"].split("/"),
+ [arr_2["memoryReference"][2:], "4"],
+ )
+ self.assertEqual(response_arr_2["body"]["accessTypes"], self.accessTypes)
+ dataBreakpoints = [
+ {"dataId": response_x["body"]["dataId"], "accessType": "write"},
+ {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
+ ]
+ set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
+ breakpoints = set_response["body"]["breakpoints"]
+ self.assertEqual(len(breakpoints), 2)
+ self.assertTrue(breakpoints[0]["verified"])
+ self.assertTrue(breakpoints[1]["verified"])
+
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[0]["id"]])
+ x_val = self.dap_server.get_local_variable_value("x")
+ i_val = self.dap_server.get_local_variable_value("i")
+ self.assertEqual(x_val, "2")
+ self.assertEqual(i_val, "1")
+
+ self.dap_server.request_continue()
+ self.verify_breakpoint_hit([breakpoints[1]["id"]])
+ arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
+ i_val = self.dap_server.get_local_variable_value("i")
+ self.assertEqual(arr_2["value"], "42")
+ self.assertEqual(i_val, "2")
+ self.dap_server.request_setDataBreakpoint([])
diff --git a/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py b/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py
index 09e3f62..19f88d8 100644
--- a/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py
+++ b/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py
@@ -3,17 +3,15 @@ Test lldb-dap disconnect request
"""
-import dap_server
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
import lldbdap_testcase
-import subprocess
import time
import os
-class TestDAP_launch(lldbdap_testcase.DAPTestCaseBase):
+class TestDAP_disconnect(lldbdap_testcase.DAPTestCaseBase):
source = "main.cpp"
def disconnect_and_assert_no_output_printed(self):
@@ -67,10 +65,11 @@ class TestDAP_launch(lldbdap_testcase.DAPTestCaseBase):
lambda: self.run_platform_command("rm %s" % (sync_file_path))
)
- self.process = subprocess.Popen([program, sync_file_path])
+ proc = self.spawnSubprocess(program, [sync_file_path])
lldbutil.wait_for_file_on_target(self, sync_file_path)
- self.attach(pid=self.process.pid, disconnectAutomatically=False)
+ self.attach(pid=proc.pid, disconnectAutomatically=False, stopOnEntry=True)
+ self.continue_to_next_stop()
response = self.dap_server.request_evaluate("wait_for_attach = false;")
self.assertTrue(response["success"])
diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
index 20a75f4..9557378 100644
--- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
+++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
@@ -1,5 +1,5 @@
"""
-Test lldb-dap completions request
+Test lldb-dap evaluate request
"""
import re
@@ -7,16 +7,70 @@ import re
import lldbdap_testcase
from lldbsuite.test.decorators import skipIfWindows
from lldbsuite.test.lldbtest import line_number
+from typing import TypedDict, Optional
+
+
+class EvaluateResponseBody(TypedDict, total=False):
+ result: str
+ variablesReference: int
+ type: Optional[str]
+ memoryReference: Optional[str]
+ valueLocationReference: Optional[int]
class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
- def assertEvaluate(self, expression, regex):
+ def assertEvaluate(
+ self,
+ expression,
+ result: str,
+ want_type="",
+ want_varref=False,
+ want_memref=True,
+ want_locref=False,
+ is_hex=None,
+ ):
+ resp = self.dap_server.request_evaluate(
+ expression, context=self.context, is_hex=is_hex
+ )
+ self.assertTrue(
+ resp["success"], f"Failed to evaluate expression {expression!r}"
+ )
+ body: EvaluateResponseBody = resp["body"]
self.assertRegex(
- self.dap_server.request_evaluate(expression, context=self.context)["body"][
- "result"
- ],
- regex,
+ body["result"],
+ result,
+ f"Unexpected 'result' for expression {expression!r} in response body {body}",
)
+ if want_varref:
+ self.assertNotEqual(
+ body["variablesReference"],
+ 0,
+ f"Unexpected 'variablesReference' for expression {expression!r} in response body {body}",
+ )
+ else:
+ self.assertEqual(
+ body["variablesReference"],
+ 0,
+ f"Unexpected 'variablesReference' for expression {expression!r} in response body {body}",
+ )
+ if want_type:
+ self.assertEqual(
+ body["type"],
+ want_type,
+ f"Unexpected 'type' for expression {expression!r} in response body {body}",
+ )
+ if want_memref:
+ self.assertIn(
+ "memoryReference",
+ body,
+ f"Unexpected 'memoryReference' for expression {expression!r} in response body {body}",
+ )
+ if want_locref:
+ self.assertIn(
+ "valueLocationReference",
+ body,
+ f"Unexpected 'valueLocationReference' for expression {expression!r} in response body {body}",
+ )
def assertEvaluateFailure(self, expression):
self.assertNotIn(
@@ -71,29 +125,45 @@ class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
self.continue_to_breakpoint(breakpoint_1)
# Expressions at breakpoint 1, which is in main
- self.assertEvaluate("var1", "20")
+ self.assertEvaluate("var1", "20", want_type="int")
# Empty expression should equate to the previous expression.
if context == "repl":
self.assertEvaluate("", "20")
else:
self.assertEvaluateFailure("")
- self.assertEvaluate("var2", "21")
+ self.assertEvaluate("var2", "21", want_type="int")
if context == "repl":
- self.assertEvaluate("", "21")
- self.assertEvaluate("", "21")
- self.assertEvaluate("static_int", "42")
- self.assertEvaluate("non_static_int", "43")
- self.assertEvaluate("struct1.foo", "15")
- self.assertEvaluate("struct2->foo", "16")
+ self.assertEvaluate("", "21", want_type="int")
+ self.assertEvaluate("", "21", want_type="int")
+ self.assertEvaluate("static_int", "0x0000002a", want_type="int", is_hex=True)
+ self.assertEvaluate(
+ "non_static_int", "0x0000002b", want_type="int", is_hex=True
+ )
+ self.assertEvaluate("struct1.foo", "0x0000000f", want_type="int", is_hex=True)
+ self.assertEvaluate("struct2->foo", "0x00000010", want_type="int", is_hex=True)
+ self.assertEvaluate("static_int", "42", want_type="int")
+ self.assertEvaluate("non_static_int", "43", want_type="int")
+ self.assertEvaluate("struct1.foo", "15", want_type="int")
+ self.assertEvaluate("struct2->foo", "16", want_type="int")
if self.isResultExpandedDescription():
self.assertEvaluate(
"struct1",
r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
+ want_type="my_struct",
+ want_varref=True,
+ )
+ self.assertEvaluate(
+ "struct2",
+ r"\(my_struct \*\) (struct2|\$\d+) = 0x.*",
+ want_type="my_struct *",
+ want_varref=True,
)
- self.assertEvaluate("struct2", r"\(my_struct \*\) (struct2|\$\d+) = 0x.*")
self.assertEvaluate(
- "struct3", r"\(my_struct \*\) (struct3|\$\d+) = nullptr"
+ "struct3",
+ r"\(my_struct \*\) (struct3|\$\d+) = nullptr",
+ want_type="my_struct *",
+ want_varref=True,
)
else:
self.assertEvaluate(
@@ -103,16 +173,22 @@ class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
if enableAutoVariableSummaries
else "my_struct @ 0x"
),
+ want_varref=True,
)
self.assertEvaluate(
- "struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*"
+ "struct2",
+ "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*",
+ want_varref=True,
+ want_type="my_struct *",
+ )
+ self.assertEvaluate(
+ "struct3", "0x.*0", want_varref=True, want_type="my_struct *"
)
- self.assertEvaluate("struct3", "0x.*0")
if context == "repl":
# In the repl context expressions may be interpreted as lldb
# commands since no variables have the same name as the command.
- self.assertEvaluate("list", r".*")
+ self.assertEvaluate("list", r".*", want_memref=False)
else:
self.assertEvaluateFailure("list") # local variable of a_function
@@ -121,10 +197,26 @@ class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
self.assertEvaluateFailure("foo") # member of my_struct
if self.isExpressionParsedExpected():
- self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
- self.assertEvaluate("a_function(1)", "1")
- self.assertEvaluate("var2 + struct1.foo", "36")
- self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
+ self.assertEvaluate(
+ "a_function",
+ "0x.*a.out`a_function.*",
+ want_type="int (*)(int)",
+ want_varref=True,
+ want_memref=False,
+ want_locref=True,
+ )
+ self.assertEvaluate(
+ "a_function(1)", "1", want_memref=False, want_type="int"
+ )
+ self.assertEvaluate("var2 + struct1.foo", "36", want_memref=False)
+ self.assertEvaluate(
+ "foo_func",
+ "0x.*a.out`foo_func.*",
+ want_type="int (*)()",
+ want_varref=True,
+ want_memref=False,
+ want_locref=True,
+ )
self.assertEvaluate("foo_var", "44")
else:
self.assertEvaluateFailure("a_function")
@@ -145,6 +237,8 @@ class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
self.assertEvaluate(
"struct1",
r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
+ want_type="my_struct",
+ want_varref=True,
)
else:
self.assertEvaluate(
@@ -154,15 +248,26 @@ class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
if enableAutoVariableSummaries
else "my_struct @ 0x"
),
+ want_type="my_struct",
+ want_varref=True,
)
self.assertEvaluate("struct1.foo", "15")
self.assertEvaluate("struct2->foo", "16")
if self.isExpressionParsedExpected():
- self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
- self.assertEvaluate("a_function(1)", "1")
- self.assertEvaluate("var2 + struct1.foo", "17")
- self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
+ self.assertEvaluate(
+ "a_function",
+ "0x.*a.out`a_function.*",
+ want_type="int (*)(int)",
+ want_varref=True,
+ want_memref=False,
+ want_locref=True,
+ )
+ self.assertEvaluate("a_function(1)", "1", want_memref=False)
+ self.assertEvaluate("var2 + struct1.foo", "17", want_memref=False)
+ self.assertEvaluate(
+ "foo_func", "0x.*a.out`foo_func.*", want_varref=True, want_memref=False
+ )
self.assertEvaluate("foo_var", "44")
else:
self.assertEvaluateFailure("a_function")
@@ -185,10 +290,18 @@ class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
self.assertEvaluateFailure("var2 + struct1.foo")
if self.isExpressionParsedExpected():
- self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
- self.assertEvaluate("a_function(1)", "1")
- self.assertEvaluate("list + 1", "43")
- self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
+ self.assertEvaluate(
+ "a_function",
+ "0x.*a.out`a_function.*",
+ want_varref=True,
+ want_memref=False,
+ want_locref=True,
+ )
+ self.assertEvaluate("a_function(1)", "1", want_memref=False)
+ self.assertEvaluate("list + 1", "43", want_memref=False)
+ self.assertEvaluate(
+ "foo_func", "0x.*a.out`foo_func.*", want_varref=True, want_memref=False
+ )
self.assertEvaluate("foo_var", "44")
else:
self.assertEvaluateFailure("a_function")
@@ -199,26 +312,28 @@ class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
# Now we check that values are updated after stepping
self.continue_to_breakpoint(breakpoint_4)
- self.assertEvaluate("my_vec", "size=2")
+ self.assertEvaluate("my_vec", "size=2", want_varref=True)
self.continue_to_breakpoint(breakpoint_5)
- self.assertEvaluate("my_vec", "size=3")
+ self.assertEvaluate("my_vec", "size=3", want_varref=True)
- self.assertEvaluate("my_map", "size=2")
+ self.assertEvaluate("my_map", "size=2", want_varref=True)
self.continue_to_breakpoint(breakpoint_6)
- self.assertEvaluate("my_map", "size=3")
+ self.assertEvaluate("my_map", "size=3", want_varref=True)
- self.assertEvaluate("my_bool_vec", "size=1")
+ self.assertEvaluate("my_bool_vec", "size=1", want_varref=True)
self.continue_to_breakpoint(breakpoint_7)
- self.assertEvaluate("my_bool_vec", "size=2")
+ self.assertEvaluate("my_bool_vec", "size=2", want_varref=True)
self.continue_to_breakpoint(breakpoint_8)
# Test memory read, especially with 'empty' repeat commands.
if context == "repl":
- self.assertEvaluate("memory read -c 1 &my_ints", ".* 05 .*\n")
- self.assertEvaluate("", ".* 0a .*\n")
- self.assertEvaluate("", ".* 0f .*\n")
- self.assertEvaluate("", ".* 14 .*\n")
- self.assertEvaluate("", ".* 19 .*\n")
+ self.assertEvaluate(
+ "memory read -c 1 &my_ints", ".* 05 .*\n", want_memref=False
+ )
+ self.assertEvaluate("", ".* 0a .*\n", want_memref=False)
+ self.assertEvaluate("", ".* 0f .*\n", want_memref=False)
+ self.assertEvaluate("", ".* 14 .*\n", want_memref=False)
+ self.assertEvaluate("", ".* 19 .*\n", want_memref=False)
self.continue_to_exit()
@@ -245,4 +360,6 @@ class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
@skipIfWindows
def test_variable_evaluate_expressions(self):
# Tests expression evaluations that are triggered in the variable explorer
- self.run_test_evaluate_expressions("variable", enableAutoVariableSummaries=True)
+ self.run_test_evaluate_expressions(
+ "variables", enableAutoVariableSummaries=True
+ )
diff --git a/lldb/test/API/tools/lldb-dap/server/TestDAP_server.py b/lldb/test/API/tools/lldb-dap/server/TestDAP_server.py
index 12b321c..3c53cf2 100644
--- a/lldb/test/API/tools/lldb-dap/server/TestDAP_server.py
+++ b/lldb/test/API/tools/lldb-dap/server/TestDAP_server.py
@@ -37,7 +37,7 @@ class TestDAP_server(lldbdap_testcase.DAPTestCaseBase):
def run_debug_session(self, connection, name, sleep_seconds_in_middle=None):
self.dap_server = dap_server.DebugAdapterServer(
- connection=connection,
+ connection=connection, spawn_helper=self.spawnSubprocess
)
program = self.getBuildArtifact("a.out")
source = "main.c"
@@ -94,6 +94,7 @@ class TestDAP_server(lldbdap_testcase.DAPTestCaseBase):
(process, connection) = self.start_server(connection="listen://localhost:0")
self.dap_server = dap_server.DebugAdapterServer(
connection=connection,
+ spawn_helper=self.spawnSubprocess,
)
program = self.getBuildArtifact("a.out")
source = "main.c"
diff --git a/lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/Makefile b/lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/Makefile
new file mode 100644
index 0000000..1049594
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/TestDAP_stackTraceCompilerGeneratedCode.py b/lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/TestDAP_stackTraceCompilerGeneratedCode.py
new file mode 100644
index 0000000..4ddf924
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/TestDAP_stackTraceCompilerGeneratedCode.py
@@ -0,0 +1,66 @@
+"""
+Test lldb-dap stackTrace request for compiler generated code
+"""
+
+import os
+
+import lldbdap_testcase
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class TestDAP_stackTraceCompilerGeneratedCode(lldbdap_testcase.DAPTestCaseBase):
+ def test_non_leaf_frame_compiler_generate_code(self):
+ """
+ Test that non-leaf frames with compiler-generated code are properly resolved.
+
+ This test verifies that LLDB correctly handles stack frames containing
+ compiler-generated code (code without valid source location information).
+ When a non-leaf frame contains compiler-generated code immediately after a
+ call instruction, LLDB should resolve the frame's source location to the
+ call instruction's line, rather than to the compiler-generated code that
+ follows, which lacks proper symbolication information.
+ """
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ source = "main.c"
+
+ # Set breakpoint inside bar() function
+ lines = [line_number(source, "// breakpoint here")]
+ breakpoint_ids = self.set_source_breakpoints(source, lines)
+ self.assertEqual(
+ len(breakpoint_ids), len(lines), "expect correct number of breakpoints"
+ )
+
+ self.continue_to_breakpoints(breakpoint_ids)
+
+ # Get the stack frames: [0] = bar(), [1] = foo(), [2] = main()
+ stack_frames = self.get_stackFrames()
+ self.assertGreater(len(stack_frames), 2, "Expected more than 2 stack frames")
+
+ # Examine the foo() frame (stack_frames[1])
+ # This is the critical frame containing compiler-generated code
+ foo_frame = stack_frames[1]
+
+ # Verify that the frame's line number points to the bar() call,
+ # not to the compiler-generated code after it
+ foo_call_bar_source_line = foo_frame.get("line")
+ self.assertEqual(
+ foo_call_bar_source_line,
+ line_number(source, "foo call bar"),
+ "Expected foo call bar to be the source line of the frame",
+ )
+
+ # Verify the source file name is correctly resolved
+ foo_source_name = foo_frame.get("source", {}).get("name")
+ self.assertEqual(
+ foo_source_name, "main.c", "Expected foo source name to be main.c"
+ )
+
+ # When lldb fails to symbolicate a frame it will emit a fake assembly
+ # source with path of format <module>`<symbol> or <module>`<address> with
+ # sourceReference to retrieve disassembly source file.
+ # Verify that this didn't happen - the path should be a real file path.
+ foo_path = foo_frame.get("source", {}).get("path")
+ self.assertNotIn("`", foo_path, "Expected foo source path to not contain `")
+ self.continue_to_exit()
diff --git a/lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/main.c b/lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/main.c
new file mode 100644
index 0000000..dd3fcc2
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/main.c
@@ -0,0 +1,19 @@
+void bar() {
+ int val = 32; // breakpoint here
+}
+
+void at_line_zero() {}
+
+int foo();
+
+int main(int argc, char const *argv[]) {
+ foo();
+ return 0;
+}
+
+int foo() {
+ bar(); // foo call bar
+#line 0 "test.cpp"
+ at_line_zero();
+ return 0;
+}
diff --git a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py b/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py
index b487257..7e60dd2 100644
--- a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py
+++ b/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py
@@ -36,3 +36,54 @@ class TestDAP_startDebugging(lldbdap_testcase.DAPTestCaseBase):
request = self.dap_server.reverse_requests[0]
self.assertEqual(request["arguments"]["configuration"]["pid"], 321)
self.assertEqual(request["arguments"]["request"], "attach")
+
+ def test_startDebugging_debugger_reuse(self):
+ """
+ Tests that debugger and target IDs can be passed through startDebugging
+ for debugger reuse. This verifies the infrastructure for child DAP
+ sessions to reuse the parent's debugger and attach to an existing target.
+ """
+ program = self.getBuildArtifact("a.out")
+ source = "main.c"
+ self.build_and_launch(program)
+
+ breakpoint_line = line_number(source, "// breakpoint")
+ self.set_source_breakpoints(source, [breakpoint_line])
+ self.continue_to_next_stop()
+
+ # Use mock IDs to test the infrastructure
+ # In a real scenario, these would come from the parent session
+ test_debugger_id = 1
+ test_target_id = 100
+
+ # Send a startDebugging request with debuggerId and targetId
+ # This simulates creating a child DAP session that reuses the debugger
+ self.dap_server.request_evaluate(
+ f'`lldb-dap start-debugging attach \'{{"debuggerId":{test_debugger_id},"targetId":{test_target_id}}}\'',
+ context="repl",
+ )
+
+ self.continue_to_exit()
+
+ # Verify the reverse request was sent with the correct IDs
+ self.assertEqual(
+ len(self.dap_server.reverse_requests),
+ 1,
+ "Should have received one startDebugging reverse request",
+ )
+
+ request = self.dap_server.reverse_requests[0]
+ self.assertEqual(request["command"], "startDebugging")
+ self.assertEqual(request["arguments"]["request"], "attach")
+
+ config = request["arguments"]["configuration"]
+ self.assertEqual(
+ config["debuggerId"],
+ test_debugger_id,
+ "Reverse request should include debugger ID",
+ )
+ self.assertEqual(
+ config["targetId"],
+ test_target_id,
+ "Reverse request should include target ID",
+ )