diff options
| author | Oliver Hunt <oliver@apple.com> | 2025-10-20 01:38:07 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-20 01:38:07 -0700 |
| commit | 7de01aa5d0418bd4e8db2917f831e7383c6863bb (patch) | |
| tree | 1db866f57c2236573cd4b4c2d141d6d420f87a92 /lldb/test | |
| parent | 6bc540043d4c3fed8f44c8f6de86be0d1740582e (diff) | |
| parent | 46a866ab7735aaa0f89fde209d516271c4825c49 (diff) | |
Merge branch 'main' into users/ojhunt/ptrauth-additionsusers/ojhunt/ptrauth-additions
Diffstat (limited to 'lldb/test')
97 files changed, 2254 insertions, 330 deletions
diff --git a/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py b/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py index 0cc505aedc4b..759b620105c4 100644 --- a/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py +++ b/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py @@ -215,8 +215,20 @@ note: candidate function not viable: requires single argument 'x', but 2 argumen details = diags.GetValueForKey("details") - # Detail 1/2: undeclared 'a' + # Detail 1/3: note: requested expression language diag = details.GetItemAtIndex(0) + self.assertEqual(str(diag.GetValueForKey("severity")), "note") + self.assertIn("Ran expression as 'C++", str(diag.GetValueForKey("message"))) + self.assertIn( + "Ran expression as 'C++", str(diag.GetValueForKey("rendered")) + ) + self.assertEqual(str(diag.GetValueForKey("source_location")), "") + self.assertEqual(str(diag.GetValueForKey("file")), "") + self.assertFalse(diag.GetValueForKey("hidden").GetBooleanValue()) + self.assertFalse(diag.GetValueForKey("in_user_input").GetBooleanValue()) + + # Detail 2/3: undeclared 'a' + diag = details.GetItemAtIndex(1) severity = diag.GetValueForKey("severity") message = diag.GetValueForKey("message") @@ -234,8 +246,8 @@ note: candidate function not viable: requires single argument 'x', but 2 argumen self.assertFalse(hidden.GetBooleanValue()) self.assertTrue(in_user_input.GetBooleanValue()) - # Detail 1/2: undeclared 'b' - diag = details.GetItemAtIndex(1) + # Detail 3/3: undeclared 'b' + diag = details.GetItemAtIndex(2) message = diag.GetValueForKey("message") self.assertIn("undeclared identifier 'b'", str(message)) diff --git a/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py index ed028a1a4ea3..4aea8009058b 100644 --- a/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py @@ -11,6 +11,9 @@ class TestCase(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(macos_version=["<", "15.0"]) + @skipIf( + bugnumber="ASTImport of lambdas not supported: https://github.com/llvm/llvm-project/issues/149477" + ) def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/deque-basic/TestDequeFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/deque-basic/TestDequeFromStdModule.py index 0fb6e883597d..5e819b7f6e16 100644 --- a/lldb/test/API/commands/expression/import-std-module/deque-basic/TestDequeFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/deque-basic/TestDequeFromStdModule.py @@ -11,6 +11,9 @@ class TestBasicDeque(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(macos_version=["<", "15.0"]) + @skipIf( + bugnumber="ASTImport of lambdas not supported: https://github.com/llvm/llvm-project/issues/149477" + ) def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDequeFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDequeFromStdModule.py index e631a8737637..e8676b21bced 100644 --- a/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDequeFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDequeFromStdModule.py @@ -12,6 +12,9 @@ class TestDbgInfoContentDeque(TestBase): @skipIf(compiler=no_match("clang")) @skipIf(compiler="clang", compiler_version=["<", "18.0"]) @skipIf(macos_version=["<", "15.0"]) + @skipIf( + bugnumber="ASTImport of lambdas not supported: https://github.com/llvm/llvm-project/issues/149477" + ) def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/forward_list/TestForwardListFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/forward_list/TestForwardListFromStdModule.py index a6ba0810e68e..9581155be204 100644 --- a/lldb/test/API/commands/expression/import-std-module/forward_list/TestForwardListFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/forward_list/TestForwardListFromStdModule.py @@ -11,6 +11,9 @@ class TestBasicForwardList(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(macos_version=["<", "15.0"]) + @skipIf( + bugnumber="ASTImport of lambdas not supported: https://github.com/llvm/llvm-project/issues/149477" + ) def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentListFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentListFromStdModule.py index b26bd7dedda8..923551ca64c3 100644 --- a/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentListFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentListFromStdModule.py @@ -13,6 +13,9 @@ class TestDbgInfoContentList(TestBase): @skipIf(compiler=no_match("clang")) @skipIf(compiler="clang", compiler_version=["<", "12.0"]) @skipIf(macos_version=["<", "15.0"]) + @skipIf( + bugnumber="ASTImport of lambdas not supported: https://github.com/llvm/llvm-project/issues/149477" + ) def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/list/TestListFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/list/TestListFromStdModule.py index 6253a35e926d..d6c88926e3e4 100644 --- a/lldb/test/API/commands/expression/import-std-module/list/TestListFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/list/TestListFromStdModule.py @@ -11,6 +11,9 @@ class TestBasicList(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(macos_version=["<", "15.0"]) + @skipIf( + bugnumber="ASTImport of lambdas not supported: https://github.com/llvm/llvm-project/issues/149477" + ) def test(self): self.build() diff --git a/lldb/test/API/commands/protocol/TestMCPUnixSocket.py b/lldb/test/API/commands/protocol/TestMCPUnixSocket.py index ea9255cc60ef..9edb97eb791b 100644 --- a/lldb/test/API/commands/protocol/TestMCPUnixSocket.py +++ b/lldb/test/API/commands/protocol/TestMCPUnixSocket.py @@ -32,3 +32,16 @@ class MCPUnixSocketCommandTestCase(TestBase): startstr="MCP server started with connection listeners:", substrs=[f"unix-connect://{socket_file}"], ) + + self.expect( + "protocol-server get MCP", + startstr="MCP server connection listeners:", + substrs=[f"unix-connect://{socket_file}"], + ) + + self.runCmd("protocol-server stop MCP", check=False) + self.expect( + "protocol-server get MCP", + error=True, + substrs=["MCP server is not running"], + ) diff --git a/lldb/test/API/driver/quit_speed/TestQuitWithProcess.py b/lldb/test/API/driver/quit_speed/TestQuitWithProcess.py index 2412b295bfb5..305e3cc397cf 100644 --- a/lldb/test/API/driver/quit_speed/TestQuitWithProcess.py +++ b/lldb/test/API/driver/quit_speed/TestQuitWithProcess.py @@ -33,3 +33,28 @@ class DriverQuitSpeedTest(PExpectTest): child.sendline("quit") print("sent quit") child.expect(pexpect.EOF, timeout=15) + + @skipIfAsan + def test_run_quit_with_prompt(self): + """Test that the lldb driver's batch mode works correctly with trailing space in confimation.""" + import pexpect + + self.build() + + exe = self.getBuildArtifact("a.out") + + self.launch(executable=exe) + child = self.child + + # Launch the process without a TTY so we don't have to interrupt: + child.sendline("process launch -n") + print("launched process") + child.expect(r"Process ([\d]*) launched:") + print("Got launch message") + child.sendline("quit") + print("sent quit") + + child.expect(r".*LLDB will kill one or more processes.*") + # add trailing space to the confirmation. + child.sendline("yEs ") + child.expect(pexpect.EOF, timeout=15) diff --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py index 85c734012761..95868486b8cb 100644 --- a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py +++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py @@ -51,7 +51,6 @@ class Resolver: def get_short_help(self): return "I am a python breakpoint resolver" - class ResolverModuleDepth(Resolver): def __get_depth__(self): return lldb.eSearchDepthModule diff --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/Makefile b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/Makefile new file mode 100644 index 000000000000..695335e068c0 --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -std=c99 + +include Makefile.rules diff --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/TestWasHit.py b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/TestWasHit.py new file mode 100644 index 000000000000..2e176239facf --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/TestWasHit.py @@ -0,0 +1,102 @@ +""" +Test the WasHit feature of scripted breakpoints +""" + +import os +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class TestWasHit(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_was_hit_resolver(self): + """Use facade breakpoints to emulate hitting some locations""" + self.build() + self.do_test() + + def make_target_and_import(self): + target = lldbutil.run_to_breakpoint_make_target(self) + self.import_resolver_script() + return target + + def import_resolver_script(self): + interp = self.dbg.GetCommandInterpreter() + error = lldb.SBError() + + script_name = os.path.join(self.getSourceDir(), "bkpt_resolver.py") + + command = "command script import " + script_name + self.runCmd(command) + + def make_extra_args(self, sym_name, num_locs, loc_to_miss): + return f" -k symbol -v {sym_name} -k num_locs -v {num_locs} -k loc_to_miss -v {loc_to_miss} " + + def do_test(self): + """This reads in a python file and sets a breakpoint using it.""" + + target = self.make_target_and_import() + extra_args = self.make_extra_args("stop_symbol", 4, 2) + + bkpt_no = lldbutil.run_break_set_by_script( + self, "bkpt_resolver.FacadeExample", extra_args, 4 + ) + + # Make sure the help text shows up in the "break list" output: + self.expect( + "break list", + substrs=["I am a facade resolver - sym: stop_symbol - num_locs: 4"], + msg="Help is listed in break list", + ) + + bkpt = target.FindBreakpointByID(bkpt_no) + self.assertTrue(bkpt.IsValid(), "Found the right breakpoint") + + # Now continue. We should hit locations 1, 3 and 4: + (target, process, thread, bkpt) = lldbutil.run_to_breakpoint_do_run( + self, target, bkpt + ) + # This location should be bkpt_no.1: + self.assertEqual( + thread.stop_reason_data[0], bkpt_no, "Hit the right breakpoint" + ) + self.assertEqual(thread.stop_reason_data[1], 1, "First location hit is 1") + + for loc in [3, 4]: + process.Continue() + self.assertEqual( + thread.stop_reason, lldb.eStopReasonBreakpoint, "Hit breakpoint" + ) + self.assertEqual( + thread.stop_reason_data[0], bkpt_no, "Hit the right breakpoint" + ) + self.assertEqual( + thread.stop_reason_data[1], loc, f"Hit the right location: {loc}" + ) + + # At this point we should have hit three of the four locations, and not location 1.2. + # Check that that is true, and that the descriptions for the location are the ones + # the resolver provided. + self.assertEqual(bkpt.hit_count, 3, "Hit three locations") + for loc_id in range(1, 4): + bkpt_loc = bkpt.FindLocationByID(loc_id) + self.assertTrue(bkpt_loc.IsValid(), f"{loc_id} was invalid.") + if loc_id != 2: + self.assertEqual( + bkpt_loc.hit_count, 1, f"Loc {loc_id} hit count was wrong" + ) + else: + self.assertEqual(bkpt_loc.hit_count, 0, "We didn't skip loc 2") + stream = lldb.SBStream() + self.assertTrue( + bkpt_loc.GetDescription(stream, lldb.eDescriptionLevelFull), + f"Didn't get description for {loc_id}", + ) + self.assertIn( + f"Location index: {loc_id}", + stream.GetData(), + f"Wrong desciption for {loc_id}", + ) diff --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/bkpt_resolver.py b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/bkpt_resolver.py new file mode 100644 index 000000000000..acc8513e3e3e --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/bkpt_resolver.py @@ -0,0 +1,49 @@ +import lldb + + +class FacadeExample: + def __init__(self, bkpt, extra_args, dict): + self.bkpt = bkpt + self.extra_args = extra_args + self.base_sym = None + self.facade_locs = [] + self.facade_locs_desc = [] + self.cur_facade_loc = 1 + + self.sym_name = extra_args.GetValueForKey("symbol").GetStringValue(100) + self.num_locs = extra_args.GetValueForKey("num_locs").GetIntegerValue(5) + self.loc_to_miss = extra_args.GetValueForKey("loc_to_miss").GetIntegerValue( + 10000 + ) + + def __callback__(self, sym_ctx): + self.base_sym = sym_ctx.module.FindSymbol(self.sym_name, lldb.eSymbolTypeCode) + if self.base_sym.IsValid(): + self.bkpt.AddLocation(self.base_sym.GetStartAddress()) + # Locations are 1 based, so to keep things simple, I'm making + # the array holding locations 1 based as well: + self.facade_locs_desc.append( + "This is the zero index, you shouldn't see this" + ) + self.facade_locs.append(None) + for i in range(1, self.num_locs + 1): + self.facade_locs_desc.append(f"Location index: {i}") + self.facade_locs.append(self.bkpt.AddFacadeLocation()) + + def get_short_help(self): + return f"I am a facade resolver - sym: {self.sym_name} - num_locs: {self.num_locs} - locs_to_miss: {self.loc_to_miss}" + + def was_hit(self, frame, bp_loc): + tmp_loc = self.cur_facade_loc + + self.cur_facade_loc = self.cur_facade_loc + 1 + if self.cur_facade_loc == self.num_locs + 1: + self.cur_facade_loc = 1 + + if tmp_loc == self.loc_to_miss: + return None + + return self.facade_locs[tmp_loc] + + def get_location_description(self, bp_loc, desc_level): + return self.facade_locs_desc[bp_loc.id] diff --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/main.c b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/main.c new file mode 100644 index 000000000000..b8f977e49351 --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/main.c @@ -0,0 +1,14 @@ +#include <stdio.h> + +int stop_symbol() { + static int s_cnt = 0; + printf("I am in the stop symbol: %d\n", s_cnt++); + return s_cnt; +} + +int main() { + for (int i = 0; i < 100; i++) { + stop_symbol(); + } + return 0; +} diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic-simulators/invalid-atomic/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic-simulators/invalid-atomic/Makefile new file mode 100644 index 000000000000..99998b20bcb0 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic-simulators/invalid-atomic/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic-simulators/invalid-atomic/TestDataFormatterInvalidAtomic.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic-simulators/invalid-atomic/TestDataFormatterInvalidAtomic.py new file mode 100644 index 000000000000..76b8e7b40f44 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic-simulators/invalid-atomic/TestDataFormatterInvalidAtomic.py @@ -0,0 +1,45 @@ +""" +Test formatting of `std::atomic`s not from any STL +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class InvalidAtomicDataFormatterTestCase(TestBase): + def test(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "Set break point at this line.", lldb.SBFileSpec("main.cpp") + ) + + self.expect_expr( + "a", + result_children=[ + ValueCheck(name="foo", value="1"), + ValueCheck(name="bar", value="2"), + ], + ) + self.expect_expr( + "b", + result_children=[ + ValueCheck(name="foo", value="3"), + ValueCheck(name="bar", value="4"), + ], + ) + + self.expect_expr( + "c", + result_children=[ + ValueCheck(name="foo", value="5"), + ValueCheck(name="bar", value="6"), + ], + ) + self.expect_expr( + "d", + result_children=[ + ValueCheck(name="foo", value="7"), + ValueCheck(name="bar", value="8"), + ], + ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic-simulators/invalid-atomic/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic-simulators/invalid-atomic/main.cpp new file mode 100644 index 000000000000..7b4c51c921a9 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic-simulators/invalid-atomic/main.cpp @@ -0,0 +1,23 @@ +namespace std { +template <typename T> struct atomic { + int foo; + int bar; +}; + +namespace __1 { +template <typename T> struct atomic { + int foo; + int bar; +}; +} // namespace __1 +} // namespace std + +int main() { + std::atomic<int> a{1, 2}; + std::atomic<void> b{3, 4}; + + std::__1::atomic<int> c{5, 6}; + std::__1::atomic<void> d{7, 8}; + + return 0; // Set break point at this line. +} diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered_map-iterator/TestDataFormatterStdUnorderedMap.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered_map-iterator/TestDataFormatterStdUnorderedMap.py index 1e920faab639..45f7b5be465c 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered_map-iterator/TestDataFormatterStdUnorderedMap.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered_map-iterator/TestDataFormatterStdUnorderedMap.py @@ -124,11 +124,6 @@ class StdUnorderedMapDataFormatterTestCase(TestBase): self.check_ptr_ptr("ptr5") self.check_ptr_ptr("ptr6") - @expectedFailureAll( - bugnumber="https://github.com/llvm/llvm-project/issues/146040", - compiler="clang", - compiler_version=["<", "21"], - ) @add_test_categories(["libc++"]) def test_ptr_libcxx(self): self.build(dictionary={"USE_LIBCPP": 1}) diff --git a/lldb/test/API/functionalities/json/symbol-file/Makefile b/lldb/test/API/functionalities/json/symbol-file/Makefile index 13bc164582ee..5d05d95fc842 100644 --- a/lldb/test/API/functionalities/json/symbol-file/Makefile +++ b/lldb/test/API/functionalities/json/symbol-file/Makefile @@ -1,4 +1,5 @@ C_SOURCES := main.c +CFLAGS_EXTRAS := -no-pie all: stripped.out diff --git a/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py b/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py index f06c9ae14bb7..d7249df350fc 100644 --- a/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py +++ b/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py @@ -1,6 +1,7 @@ # Test the SBAPI for GetStatistics() import json + import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -54,6 +55,11 @@ class TestStatsAPI(TestBase): stats_json, 'Make sure the "frameVariable" key in in target.GetStatistics()["targets"][0]', ) + self.assertNotIn( + "loadCoreTime", + stats_json, + "LoadCoreTime should not be present in a live, non-coredump target", + ) expressionEvaluation = stats_json["expressionEvaluation"] self.assertIn( "successes", @@ -157,3 +163,25 @@ class TestStatsAPI(TestBase): stats_force.GetAsJSON(stream_force) debug_stats_force = json.loads(stream_force.GetData()) self.assertEqual(debug_stats_force["totalDebugInfoByteSize"], 445) + + def test_core_load_time(self): + """ + Test to see if the coredump path is included in statistics dump. + """ + yaml_file = "arm64-minidump-build-ids.yaml" + src_dir = self.getSourceDir() + minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp") + self.yaml2obj(os.path.join(src_dir, yaml_file), minidump_path) + target = self.dbg.CreateTarget(None) + process = target.LoadCore(minidump_path) + self.assertTrue(process.IsValid()) + + stats_options = lldb.SBStatisticsOptions() + stats = target.GetStatistics(stats_options) + stream = lldb.SBStream() + stats.GetAsJSON(stream) + debug_stats = json.loads(stream.GetData()) + self.assertTrue("targets" in debug_stats) + target_info = debug_stats["targets"][0] + self.assertTrue("loadCoreTime" in target_info) + self.assertTrue(float(target_info["loadCoreTime"]) > 0.0) diff --git a/lldb/test/API/functionalities/stats_api/arm64-minidump-build-ids.yaml b/lldb/test/API/functionalities/stats_api/arm64-minidump-build-ids.yaml new file mode 100644 index 000000000000..4acbc409d808 --- /dev/null +++ b/lldb/test/API/functionalities/stats_api/arm64-minidump-build-ids.yaml @@ -0,0 +1,19 @@ +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM + Platform ID: Linux + CSD Version: '15E216' + CPU: + CPUID: 0x00000000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/a' + CodeView Record: 4C4570420102030405060708090A0B0C0D0E0F1011121314 + - Base of Image: 0x0000000000001000 + Size of Image: 0x00001000 + Module Name: '/tmp/b' + CodeView Record: 4C4570420A141E28323C46505A646E78828C96A0AAB4BEC8 +... diff --git a/lldb/test/API/functionalities/thread/step_out_line0/Makefile b/lldb/test/API/functionalities/thread/step_out_line0/Makefile new file mode 100644 index 000000000000..10495940055b --- /dev/null +++ b/lldb/test/API/functionalities/thread/step_out_line0/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/functionalities/thread/step_out_line0/TestThreadStepOutLine0.py b/lldb/test/API/functionalities/thread/step_out_line0/TestThreadStepOutLine0.py new file mode 100644 index 000000000000..2707ca852f66 --- /dev/null +++ b/lldb/test/API/functionalities/thread/step_out_line0/TestThreadStepOutLine0.py @@ -0,0 +1,35 @@ +""" +Test stepping out of a function when the return location is an unsuitable +stopping point. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ThreadStepOutLine0TestCase(TestBase): + def test(self): + self.build() + target, process, thread, _ = lldbutil.run_to_source_breakpoint( + self, "// Set breakpoint here", lldb.SBFileSpec("main.c") + ) + correct_stepped_out_line = line_number("main.c", "// Should stop here") + return_statement_line = line_number("main.c", "// Ran too far") + safety_bp = target.BreakpointCreateByLocation( + lldb.SBFileSpec("main.c"), return_statement_line + ) + self.assertTrue(safety_bp.IsValid()) + + error = lldb.SBError() + thread.StepOut(error) + self.assertTrue(error.Success()) + + frame = thread.GetSelectedFrame() + self.assertEqual( + frame.line_entry.GetLine(), + correct_stepped_out_line, + "Step-out lost control of execution, ran too far", + ) diff --git a/lldb/test/API/functionalities/thread/step_out_line0/main.c b/lldb/test/API/functionalities/thread/step_out_line0/main.c new file mode 100644 index 000000000000..ad0c1c05d695 --- /dev/null +++ b/lldb/test/API/functionalities/thread/step_out_line0/main.c @@ -0,0 +1,11 @@ +int step_out_of_here(int a) { + return a + 5; // Set breakpoint here +} + +int main() { +#line 0 + int v = step_out_of_here(3) + 7; +#line 9 + v += 11; // Should stop here + return v; // Ran too far +} diff --git a/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py b/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py index 768dd6fe6867..50ea17370524 100644 --- a/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py +++ b/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py @@ -12,21 +12,7 @@ from lldbsuite.test import lldbutil class TestCortexMExceptionUnwind(TestBase): NO_DEBUG_INFO_TESTCASE = True - # on the lldb-remote-linux-ubuntu CI, the binary.json's triple of - # armv7m-apple is not being set in the Target triple, and we're - # picking the wrong ABI plugin, ABISysV_arm. - # ABISysV_arm::CreateDefaultUnwindPlan() doesn't have a way to detect - # arm/thumb for a stack frame, or even the Target's triple for a - # Cortex-M part that is always thumb. It hardcodes r11 as the frame - # pointer register, which is correct for arm code but not thumb. - # It is never correct # on a Cortex-M target. - # The Darwin ABIMacOSX_arm diverges from AAPCS and always uses r7 for - # the frame pointer -- the thumb convention -- whether executing arm or - # thumb. So its CreateDefaultUnwindPlan picks the correct register for - # the frame pointer, and we can walk the stack. - # ABISysV_arm::CreateDefaultUnwindPlan will only get one frame and - # not be able to continue. - @skipIfRemote + @skipIfLLVMTargetMissing("ARM") def test_no_fpu(self): """Test that we can backtrace correctly through an ARM Cortex-M Exception return stack""" @@ -42,6 +28,9 @@ class TestCortexMExceptionUnwind(TestBase): core = self.getBuildArtifact("core") self.yaml2macho_core("armv7m-nofpu-exception.yaml", core, exe_uuid) + if self.TraceOn(): + self.runCmd("log enable lldb unwind") + process = target.LoadCore(core) self.assertTrue(process.IsValid()) @@ -55,14 +44,9 @@ class TestCortexMExceptionUnwind(TestBase): thread = process.GetThreadAtIndex(0) self.assertTrue(thread.IsValid()) - # We have 4 named stack frames and two unnamed - # frames above that. The topmost two stack frames - # were not interesting for this test, so I didn't - # create symbols for them. - self.assertEqual(thread.GetNumFrames(), 6) + self.assertEqual(thread.GetNumFrames(), 3) stackframe_names = [ "exception_catcher", - "exception_catcher", "exception_thrower", "main", ] diff --git a/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml b/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml index 9ce5ff49d9b6..0b4e1f8fac3e 100644 --- a/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml +++ b/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml @@ -2,8 +2,8 @@ cpu: armv7m threads: - regsets: - flavor: gpr - registers: [{name: sp, value: 0x2000fe70}, {name: r7, value: 0x2000fe80}, - {name: pc, value: 0x0020392c}, {name: lr, value: 0x0020392d}] + registers: [{name: sp, value: 0x2000fe88}, {name: r7, value: 0x2000fe88}, + {name: pc, value: 0x00203916}, {name: lr, value: 0x0020392d}] memory-regions: # stack memory fetched via # (lldb) p/x $sp @@ -14,7 +14,7 @@ memory-regions: 0x0000002a, 0x20010e58, 0x00203923, 0x00000001, 0x2000fe88, 0x00203911, 0x2000ffdc, 0xfffffff9, 0x00000102, 0x00000002, 0x000003f0, 0x0000002a, - 0x20012620, 0x00203215, 0x00203366, 0x81000200, + 0x20012620, 0x00203215, 0x00202a92, 0x81000200, 0x00203215, 0x200128b0, 0x0024928d, 0x2000fecc, 0x002491ed, 0x20010e58, 0x20010e4c, 0x2000ffa0, 0x200107a0, 0x0000003c, 0x200116e8, 0x200108b0, @@ -62,3 +62,26 @@ memory-regions: 0x98, 0xae, 0x28, 0x00 ] + # exception_thrower + # (lldb) disass -b -c 12 -n exception_thrower + # 0x202a88 <+0>: 0xb5f0 push {r4, r5, r6, r7, lr} + # 0x202a8a <+2>: 0xaf03 add r7, sp, #0xc + # 0x202a8c <+4>: 0xe92d0f00 push.w {r8, r9, r10, r11} + # 0x202a90 <+8>: 0xb0c3 sub sp, #0x10c + # 0x202a92 <+10>: 0xf7ffffd9 bl 0x202a48 + - addr: 0x202a88 + UInt8: [ + 0xf0, 0xb5, 0x03, 0xaf, 0x2d, 0xe9, 0x00, 0x0f, + 0xc3, 0xb0, 0xff, 0xf7, 0xd9, 0xff, 0xff, 0xf7 + ] + + # main: + # 0x202a7e <+0>: push {r7, lr} + # 0x202a80 <+2>: mov r7, sp + # 0x202a82 <+4>: bl 0x202a88 ; exception_thrower + # 0x202a86 <+8>: nop + - addr: 0x202a7e + UInt8: [ + 0x80, 0xb5, 0x6f, 0x46, 0x00, 0xf0, 0x01, 0xf8, + 0x00, 0xbf + ] diff --git a/lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json b/lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json index 8fcd5307ff82..0de0169f7adb 100644 --- a/lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json +++ b/lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json @@ -1,5 +1,5 @@ { - "triple": "armv7m-apple", + "triple": "armv7m--", "uuid": "2D157DBA-53C9-3AC7-B5A1-9D336EC831CB", "type": "executable", "sections": [ @@ -28,13 +28,13 @@ { "name": "exception_catcher", "type": "code", - "size": 44, + "size": 32, "address": 2111760 }, { "name": "exception_thrower", "type": "code", - "size": 2652, + "size": 16, "address": 2108040 } ] diff --git a/lldb/test/API/lang/cpp/abi_tag_structors/TestAbiTagStructors.py b/lldb/test/API/lang/cpp/abi_tag_structors/TestAbiTagStructors.py index 87d8adb42b82..2d3e4f7cdd47 100644 --- a/lldb/test/API/lang/cpp/abi_tag_structors/TestAbiTagStructors.py +++ b/lldb/test/API/lang/cpp/abi_tag_structors/TestAbiTagStructors.py @@ -10,6 +10,11 @@ from lldbsuite.test import lldbutil class AbiTagStructorsTestCase(TestBase): + @skipIf( + compiler="clang", + compiler_version=["<", "22"], + bugnumber="Required Clang flag not supported", + ) @expectedFailureAll(oslist=["windows"]) def test_with_structor_linkage_names(self): self.build(dictionary={"CXXFLAGS_EXTRAS": "-gstructor-decl-linkage-names"}) @@ -73,7 +78,16 @@ class AbiTagStructorsTestCase(TestBase): Test that without linkage names on structor declarations we can't call ABI-tagged structors. """ - self.build(dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"}) + # In older versions of Clang the -gno-structor-decl-linkage-names + # behaviour was the default. + if self.expectedCompiler(["clang"]) and self.expectedCompilerVersion( + [">=", "22.0"] + ): + self.build( + dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"} + ) + else: + self.build() lldbutil.run_to_source_breakpoint( self, "Break here", lldb.SBFileSpec("main.cpp", False) @@ -105,12 +119,23 @@ class AbiTagStructorsTestCase(TestBase): "expression TaggedLocal()", error=True, substrs=["Couldn't look up symbols"] ) + @skipIf(compiler="clang", compiler_version=["<", "22"]) @expectedFailureAll(oslist=["windows"]) - def test_nested_no_structor_linkage_names(self): + def test_nested_with_structor_linkage_names(self): self.build(dictionary={"CXXFLAGS_EXTRAS": "-gstructor-decl-linkage-names"}) self.do_nested_structor_test() @expectedFailureAll(oslist=["windows"]) - def test_nested_with_structor_linkage_names(self): - self.build(dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"}) + def test_nested_no_structor_linkage_names(self): + # In older versions of Clang the -gno-structor-decl-linkage-names + # behaviour was the default. + if self.expectedCompiler(["clang"]) and self.expectedCompilerVersion( + [">=", "22.0"] + ): + self.build( + dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"} + ) + else: + self.build() + self.do_nested_structor_test() diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py index c0545c70c84e..b3bed43c7587 100644 --- a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py @@ -6,6 +6,11 @@ from lldbsuite.test import lldbutil class ExprDefinitionInDylibTestCase(TestBase): + @skipIf( + compiler="clang", + compiler_version=["<", "22"], + bugnumber="Required Clang flag not supported", + ) @skipIfWindows def test_with_structor_linkage_names(self): """ @@ -74,7 +79,16 @@ class ExprDefinitionInDylibTestCase(TestBase): Tests that if structor declarations don't have linkage names, we can't call ABI-tagged constructors. But non-tagged ones are fine. """ - self.build(dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"}) + # In older versions of Clang the -gno-structor-decl-linkage-names + # behaviour was the default. + if self.expectedCompiler(["clang"]) and self.expectedCompilerVersion( + [">=", "22.0"] + ): + self.build( + dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"} + ) + else: + self.build() target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) self.assertTrue(target, VALID_TARGET) @@ -95,6 +109,6 @@ class ExprDefinitionInDylibTestCase(TestBase): self.expect_expr("Foo(10)", result_type="Foo") - self.expect("Base()", error=True) + self.expect("expr Base()", error=True) - self.expect("Bar()", error=True) + self.expect("expr Bar()", error=True) diff --git a/lldb/test/API/lang/cpp/floating-types-specialization/Makefile b/lldb/test/API/lang/cpp/floating-types-specialization/Makefile new file mode 100644 index 000000000000..99998b20bcb0 --- /dev/null +++ b/lldb/test/API/lang/cpp/floating-types-specialization/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/floating-types-specialization/TestCppFloatingTypesSpecialization.py b/lldb/test/API/lang/cpp/floating-types-specialization/TestCppFloatingTypesSpecialization.py new file mode 100644 index 000000000000..979391f3681f --- /dev/null +++ b/lldb/test/API/lang/cpp/floating-types-specialization/TestCppFloatingTypesSpecialization.py @@ -0,0 +1,37 @@ +import lldb +import lldbsuite.test.lldbplatformutil as lldbplatformutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCase(TestBase): + @skipIf(compiler="clang", compiler_version=["<", "17.0"]) + def test(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "// break here", lldb.SBFileSpec("main.cpp", False) + ) + + # On 32-bit Arm, you have to have the bfloat16 extension, or an FPU while + # not using the soft float mode. The target we assume has none of that + # so instead of __bf16 we get __fp16. + is_arm_32_bit = lldbplatformutil.getArchitecture() == "arm" + + self.expect_expr( + "f0", result_type=("Foo<__fp16>" if is_arm_32_bit else "Foo<__bf16>") + ) + + # When __bf16 is actually __fp16, f1 looks like it inherits from itself. + # Which clang allows but LLDB fails to evaluate. + if not is_arm_32_bit: + self.expect_expr("f1", result_type="Foo<__fp16>") + + # Test sizeof to ensure while computing layout we don't do + # infinite recursion. + v = self.frame().EvaluateExpression("sizeof(f0)") + self.assertEqual(v.GetValueAsUnsigned() > 0, True) + + if not is_arm_32_bit: + v = self.frame().EvaluateExpression("sizeof(f1)") + self.assertEqual(v.GetValueAsUnsigned() > 0, True) diff --git a/lldb/test/API/lang/cpp/floating-types-specialization/main.cpp b/lldb/test/API/lang/cpp/floating-types-specialization/main.cpp new file mode 100644 index 000000000000..e3e8a3767fef --- /dev/null +++ b/lldb/test/API/lang/cpp/floating-types-specialization/main.cpp @@ -0,0 +1,11 @@ +template <typename T> struct Foo; + +template <> struct Foo<__bf16> {}; + +template <> struct Foo<_Float16> : Foo<__bf16> {}; + +int main() { + Foo<__bf16> f0; + Foo<_Float16> f1; + return 0; // break here +} diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/Makefile b/lldb/test/API/lang/cpp/function-call-from-object-file/Makefile new file mode 100644 index 000000000000..285bbfbbca4f --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp lib1.cpp lib2.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/TestFunctionCallFromObjectFile.py b/lldb/test/API/lang/cpp/function-call-from-object-file/TestFunctionCallFromObjectFile.py new file mode 100644 index 000000000000..f0a7aef182a6 --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/TestFunctionCallFromObjectFile.py @@ -0,0 +1,29 @@ +""" +Tests that we can call functions that have definitions in multiple +CUs in the debug-info (which is the case for functions defined in headers). +The linker will most likely de-duplicate the functiond definitions when linking +the final executable. On Darwin, this will create a debug-map that LLDB will use +to fix up object file addresses to addresses in the linked executable. However, +if we parsed the DIE from the object file whose functiond definition got stripped +by the linker, LLDB needs to ensure it can still resolve the function symbol it +got for it. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestFunctionCallFromObjectFile(TestBase): + def test_lib1(self): + self.build() + lldbutil.run_to_name_breakpoint(self, "lib1_func") + + self.expect_expr("Foo{}.foo()", result_type="int", result_value="15") + + def test_lib2(self): + self.build() + lldbutil.run_to_name_breakpoint(self, "lib2_func") + + self.expect_expr("Foo{}.foo()", result_type="int", result_value="15") diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/common.h b/lldb/test/API/lang/cpp/function-call-from-object-file/common.h new file mode 100644 index 000000000000..76e23be6b97a --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/common.h @@ -0,0 +1,8 @@ +#ifndef COMMON_H_IN +#define COMMON_H_IN + +struct Foo { + int foo() { return 15; } +}; + +#endif // COMMON_H_IN diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/lib1.cpp b/lldb/test/API/lang/cpp/function-call-from-object-file/lib1.cpp new file mode 100644 index 000000000000..b97bcc1b712b --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/lib1.cpp @@ -0,0 +1,8 @@ +#include "common.h" + +// Parameter "Foo*" forces LLDB to parse "Foo" from the object +// file that it is stopped in. +void lib1_func(Foo *) { + // Force definition into lib1.o debug-info. + Foo{}.foo(); +} diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/lib2.cpp b/lldb/test/API/lang/cpp/function-call-from-object-file/lib2.cpp new file mode 100644 index 000000000000..2f9d81a8bdf4 --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/lib2.cpp @@ -0,0 +1,6 @@ +#include "common.h" + +void lib2_func(Foo *) { + // Force definition into lib2.o debug-info. + Foo{}.foo(); +} diff --git a/lldb/test/API/lang/cpp/function-call-from-object-file/main.cpp b/lldb/test/API/lang/cpp/function-call-from-object-file/main.cpp new file mode 100644 index 000000000000..61ca798daf1d --- /dev/null +++ b/lldb/test/API/lang/cpp/function-call-from-object-file/main.cpp @@ -0,0 +1,10 @@ +struct Foo; + +extern void lib1_func(Foo *); +extern void lib2_func(Foo *); + +int main() { + lib1_func(nullptr); + lib2_func(nullptr); + return 0; +} diff --git a/lldb/test/API/lang/cpp/structured-binding/TestStructuredBinding.py b/lldb/test/API/lang/cpp/structured-binding/TestStructuredBinding.py index 5f939ecfbef2..882c91d1ce8c 100644 --- a/lldb/test/API/lang/cpp/structured-binding/TestStructuredBinding.py +++ b/lldb/test/API/lang/cpp/structured-binding/TestStructuredBinding.py @@ -99,16 +99,21 @@ class TestStructuredBinding(TestBase): self.expect_expr("ty2", result_value="'z'") self.expect_expr("tz2", result_value="10") - self.expect( - "frame variable", - substrs=[ - "tx1 =", - "ty1 =", - "tz1 =", - "tx2 =", - "ty2 =", - "tz2 =", - "mp1 =", - "mp2 =", - ], - ) + # Older versions of Clang marked structured binding variables + # as artificial, and thus LLDB wouldn't display them. + if self.expectedCompiler(["clang"]) and self.expectedCompilerVersion( + [">=", "22.0"] + ): + self.expect( + "frame variable", + substrs=[ + "tx1 =", + "ty1 =", + "tz1 =", + "tx2 =", + "ty2 =", + "tz2 =", + "mp1 =", + "mp2 =", + ], + ) diff --git a/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py b/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py index eac7b5ef1099..83c057220410 100644 --- a/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py +++ b/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py @@ -1,4 +1,5 @@ import lldb +import lldbsuite.test.lldbplatformutil as lldbplatformutil from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil @@ -82,8 +83,12 @@ class TestCase(TestBase): value = self.expect_expr("temp7", result_type="Foo<__fp16, __fp16>") self.assertFalse(value.GetType().GetTemplateArgumentValue(target, 1)) - value = self.expect_expr("temp8", result_type="Foo<__fp16, __fp16>") - self.assertFalse(value.GetType().GetTemplateArgumentValue(target, 1)) + # The target we use when evaluating these expressions for Arm leads to there + # not being a __bf16 type in the AST so we fall back to __fp16 and evaluating + # this fails. + if lldbplatformutil.getArchitecture() != "arm": + value = self.expect_expr("temp8", result_type="Foo<__bf16, __bf16>") + self.assertFalse(value.GetType().GetTemplateArgumentValue(target, 1)) value = self.expect_expr("temp9", result_type="Bar<double, 1.200000e+00>") template_param_value = value.GetType().GetTemplateArgumentValue(target, 1) diff --git a/lldb/test/API/lang/objc/ivar-in-framework-base/Makefile b/lldb/test/API/lang/objc/ivar-in-framework-base/Makefile new file mode 100644 index 000000000000..c7947fc138c1 --- /dev/null +++ b/lldb/test/API/lang/objc/ivar-in-framework-base/Makefile @@ -0,0 +1,6 @@ +OBJC_SOURCES := main.m lib.m +LD_EXTRAS = -framework Foundation + +include Makefile.rules + +lib.o: CFLAGS = $(CFLAGS_NO_DEBUG) diff --git a/lldb/test/API/lang/objc/ivar-in-framework-base/TestIvarInFrameworkBase.py b/lldb/test/API/lang/objc/ivar-in-framework-base/TestIvarInFrameworkBase.py new file mode 100644 index 000000000000..40fc6b7a6899 --- /dev/null +++ b/lldb/test/API/lang/objc/ivar-in-framework-base/TestIvarInFrameworkBase.py @@ -0,0 +1,39 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestIvarInFrameworkBase(TestBase): + """ + Tests whether LLDB's data inspection commands can correctly retrieve + information about ivars from the Objective-C runtime. + In this test-case we have a base class type for which we don't have access + to the debug-info of the implementation (mimicking the scenario of subclassing + a type from a system framework). LLDB won't be able to see the backing ivar for + 'fooProp' from just debug-info, but it will fall back on the runtime to get the + necessary information. + """ + + def test_frame_var(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.m")) + self.expect("frame variable *bar", substrs=["_fooProp = 10", "_barProp = 15"]) + + def test_expr(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.m")) + self.expect_expr( + "*bar", + result_type="Bar", + result_children=[ + ValueCheck( + name="Foo", + children=[ + ValueCheck(name="NSObject"), + ValueCheck(name="_fooProp", value="10"), + ], + ), + ValueCheck(name="_barProp", value="15"), + ], + ) diff --git a/lldb/test/API/lang/objc/ivar-in-framework-base/lib.h b/lldb/test/API/lang/objc/ivar-in-framework-base/lib.h new file mode 100644 index 000000000000..31ceb53dc688 --- /dev/null +++ b/lldb/test/API/lang/objc/ivar-in-framework-base/lib.h @@ -0,0 +1,6 @@ +#import <Foundation/Foundation.h> + +@interface Foo : NSObject +@property int fooProp; +- (id)init; +@end diff --git a/lldb/test/API/lang/objc/ivar-in-framework-base/lib.m b/lldb/test/API/lang/objc/ivar-in-framework-base/lib.m new file mode 100644 index 000000000000..e1bf80ac4bd4 --- /dev/null +++ b/lldb/test/API/lang/objc/ivar-in-framework-base/lib.m @@ -0,0 +1,8 @@ +#import "lib.h" + +@implementation Foo +- (id)init { + self.fooProp = 10; + return self; +} +@end diff --git a/lldb/test/API/lang/objc/ivar-in-framework-base/main.m b/lldb/test/API/lang/objc/ivar-in-framework-base/main.m new file mode 100644 index 000000000000..1fd352ec92c5 --- /dev/null +++ b/lldb/test/API/lang/objc/ivar-in-framework-base/main.m @@ -0,0 +1,22 @@ +#import "lib.h" +#include <stdio.h> + +@interface Bar : Foo +@property int barProp; +- (id)init; +@end + +@implementation Bar + +- (id)init { + self = [super init]; + self.barProp = 15; + return self; +} +@end + +int main() { + Bar *bar = [Bar new]; + puts("break here"); + return 0; +} diff --git a/lldb/test/API/macosx/debugserver-multimemread/Makefile b/lldb/test/API/macosx/debugserver-multimemread/Makefile new file mode 100644 index 000000000000..10495940055b --- /dev/null +++ b/lldb/test/API/macosx/debugserver-multimemread/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/macosx/debugserver-multimemread/TestDebugserverMultiMemRead.py b/lldb/test/API/macosx/debugserver-multimemread/TestDebugserverMultiMemRead.py new file mode 100644 index 000000000000..6caa5f85c284 --- /dev/null +++ b/lldb/test/API/macosx/debugserver-multimemread/TestDebugserverMultiMemRead.py @@ -0,0 +1,102 @@ +""" +Tests debugserver support for MultiMemRead. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +@skipUnlessDarwin +@skipIfOutOfTreeDebugserver +class TestCase(TestBase): + def send_process_packet(self, packet_str): + self.runCmd(f"proc plugin packet send {packet_str}", check=False) + # The output is of the form: + # packet: <packet_str> + # response: <response> + reply = self.res.GetOutput().split("\n") + packet = reply[0].strip() + response = reply[1].strip() + + self.assertTrue(packet.startswith("packet: ")) + self.assertTrue(response.startswith("response: ")) + return response[len("response: ") :] + + def check_invalid_packet(self, packet_str): + reply = self.send_process_packet("packet_str") + self.assertEqual(reply, "E03") + + def test_packets(self): + self.build() + source_file = lldb.SBFileSpec("main.c") + target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, "break here", source_file + ) + + reply = self.send_process_packet("qSupported") + self.assertIn("MultiMemRead+", reply) + + mem_address_var = thread.frames[0].FindVariable("memory") + self.assertTrue(mem_address_var) + mem_address = mem_address_var.GetValueAsUnsigned() + 42 + + # no ":" + self.check_invalid_packet("MultiMemRead") + # missing ranges + self.check_invalid_packet("MultiMemRead:") + # needs at least one range + self.check_invalid_packet("MultiMemRead:ranges:") + # needs at least one range + self.check_invalid_packet("MultiMemRead:ranges:,") + # a range is a pair of numbers + self.check_invalid_packet("MultiMemRead:ranges:10") + # a range is a pair of numbers + self.check_invalid_packet("MultiMemRead:ranges:10,") + # range list must end with ; + self.check_invalid_packet("MultiMemRead:ranges:10,2") + self.check_invalid_packet("MultiMemRead:ranges:10,2,") + self.check_invalid_packet("MultiMemRead:ranges:10,2,3") + # ranges are pairs of numbers. + self.check_invalid_packet("MultiMemRead:ranges:10,2,3;") + # unrecognized field + self.check_invalid_packet("MultiMemRead:ranges:10,2;blah:;") + # unrecognized field + self.check_invalid_packet("MultiMemRead:blah:;ranges:10,2;") + + # Zero-length reads are ok. + reply = self.send_process_packet("MultiMemRead:ranges:0,0;") + self.assertEqual(reply, "0;") + + # Debugserver is permissive with trailing commas. + reply = self.send_process_packet("MultiMemRead:ranges:10,2,;") + self.assertEqual(reply, "0;") + reply = self.send_process_packet(f"MultiMemRead:ranges:{mem_address:x},2,;") + self.assertEqual(reply, "2;ab") + + reply = self.send_process_packet("MultiMemRead:ranges:10,2;") + self.assertEqual(reply, "0;") + reply = self.send_process_packet(f"MultiMemRead:ranges:{mem_address:x},0;") + self.assertEqual(reply, "0;") + reply = self.send_process_packet(f"MultiMemRead:ranges:{mem_address:x},2;") + self.assertEqual(reply, "2;ab") + reply = self.send_process_packet( + f"MultiMemRead:ranges:{mem_address:x},2,{mem_address+2:x},4;" + ) + self.assertEqual(reply, "2,4;abcdef") + reply = self.send_process_packet( + f"MultiMemRead:ranges:{mem_address:x},2,{mem_address+2:x},4,{mem_address+6:x},8;" + ) + self.assertEqual(reply, "2,4,8;abcdefghijklmn") + + # Test zero length in the middle. + reply = self.send_process_packet( + f"MultiMemRead:ranges:{mem_address:x},2,{mem_address+2:x},0,{mem_address+6:x},8;" + ) + self.assertEqual(reply, "2,0,8;abghijklmn") + # Test zero length in the end. + reply = self.send_process_packet( + f"MultiMemRead:ranges:{mem_address:x},2,{mem_address+2:x},4,{mem_address+6:x},0;" + ) + self.assertEqual(reply, "2,4,0;abcdef") diff --git a/lldb/test/API/macosx/debugserver-multimemread/main.c b/lldb/test/API/macosx/debugserver-multimemread/main.c new file mode 100644 index 000000000000..44cdd475b550 --- /dev/null +++ b/lldb/test/API/macosx/debugserver-multimemread/main.c @@ -0,0 +1,14 @@ +#include <stdlib.h> +#include <string.h> + +int main(int argc, char **argv) { + char *memory = malloc(1024); + memset(memory, '-', 1024); + // Write "interesting" characters at an offset from the memory filled with + // `-`. This way, if we read outside the range in either direction, we should + // find `-`s`. + int offset = 42; + for (int i = offset; i < offset + 14; i++) + memory[i] = 'a' + (i - offset); + return 0; // break here +} diff --git a/lldb/test/API/macosx/mte/Makefile b/lldb/test/API/macosx/mte/Makefile new file mode 100644 index 000000000000..d614e0f0a3bc --- /dev/null +++ b/lldb/test/API/macosx/mte/Makefile @@ -0,0 +1,15 @@ +C_SOURCES := main.c + +EXE := uaf + +binary-plain: uaf +binary-entitled: uaf sign + +all: binary-entitled + +include Makefile.rules + +sign: mte-entitlements.plist uaf +ifeq ($(OS),Darwin) + codesign -s - -f --entitlements $^ +endif diff --git a/lldb/test/API/macosx/mte/TestDarwinMTE.py b/lldb/test/API/macosx/mte/TestDarwinMTE.py new file mode 100644 index 000000000000..a70b4b4aed26 --- /dev/null +++ b/lldb/test/API/macosx/mte/TestDarwinMTE.py @@ -0,0 +1,122 @@ +"""Test MTE Memory Tagging on Apple platforms""" + +import lldb +import re +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbsuite.test.cpu_feature as cpu_feature + +exe_name = "uaf" # Must match Makefile + + +class TestDarwinMTE(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + @skipUnlessFeature(cpu_feature.AArch64.MTE) + def test_process_launch_memory_tagging(self): + self.build(make_targets=["binary-plain"]) + self.createTestTarget(self.getBuildArtifact(exe_name)) + + self.expect("process launch", substrs=["exited with status = 0"]) + + self.expect( + "process launch --memory-tagging", + substrs=["stopped", "stop reason = EXC_ARM_MTE_TAG_FAULT"], + ) + + @skipUnlessFeature(cpu_feature.AArch64.MTE) + def test_tag_fault(self): + self.build() + exe = self.getBuildArtifact(exe_name) + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + process = target.LaunchSimple(None, None, None) + self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) + + self.expect( + "thread info", + substrs=[ + "stop reason = EXC_ARM_MTE_TAG_FAULT", + "MTE tag mismatch detected", + ], + ) + + @skipUnlessFeature(cpu_feature.AArch64.MTE) + def test_memory_region(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "// before free", lldb.SBFileSpec("main.c"), exe_name=exe_name + ) + + # (lldb) memory region ptr + # [0x00000001005ec000-0x00000001009ec000) rw- + # memory tagging: enabled + # Modified memory (dirty) page list provided, 2 entries. + # Dirty pages: 0x1005ec000, 0x1005fc000. + self.expect("memory region ptr", substrs=["memory tagging: enabled"]) + + @skipUnlessFeature(cpu_feature.AArch64.MTE) + def test_memory_read_show_tags(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "// before free", lldb.SBFileSpec("main.c"), exe_name=exe_name + ) + + # (lldb) memory read ptr-16 ptr+48 --show-tags + # 0x7d2c00930: 00 00 00 00 00 00 00 00 d0 e3 a5 0a 02 00 00 00 ................ (tag: 0x3) + # 0x7d2c00940: 48 65 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 Hello........... (tag: 0xb) + # 0x7d2c00950: 57 6f 72 6c 64 00 00 00 00 00 00 00 00 00 00 00 World........... (tag: 0xb) + # 0x7d2c00960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ (tag: 0x9) + self.expect( + "memory read ptr-16 ptr+48 --show-tags", + substrs=[" Hello...........", " World..........."], + patterns=[r"(.*\(tag: 0x[0-9a-f]\)\n){4}"], + ) + + def _parse_pointer_tag(self, output): + return re.search(r"Logical tag: (0x[0-9a-f])", output).group(1) + + def _parse_memory_tags(self, output, expected_tag_count): + tags = re.findall(r"\): (0x[0-9a-f])", output) + self.assertEqual(len(tags), expected_tag_count) + return tags + + @skipUnlessFeature(cpu_feature.AArch64.MTE) + def test_memory_tag_read(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "// before free", lldb.SBFileSpec("main.c"), exe_name=exe_name + ) + + # (lldb) memory tag read ptr-1 ptr+33 + # Logical tag: 0x5 + # Allocation tags: + # [0x100a65a40, 0x100a65a50): 0xf (mismatch) + # [0x100a65a50, 0x100a65a60): 0x5 + # [0x100a65a60, 0x100a65a70): 0x5 + # [0x100a65a70, 0x100a65a80): 0x2 (mismatch) + self.expect( + "memory tag read ptr-1 ptr+33", + substrs=["Logical tag: 0x", "Allocation tags:", "(mismatch)"], + patterns=[r"(\[.*\): 0x[0-9a-f].*\n){4}"], + ) + output = self.res.GetOutput() + self.assertEqual(output.count("(mismatch)"), 2) + ptr_tag = self._parse_pointer_tag(output) + tags = self._parse_memory_tags(output, 4) + self.assertEqual(tags[1], ptr_tag) + self.assertEqual(tags[2], ptr_tag) + self.assertNotEqual(tags[0], ptr_tag) # Memory that comes before/after + self.assertNotEqual(tags[3], ptr_tag) # allocation has different tag. + + # Continue running until MTE fault + self.expect("process continue", substrs=["stop reason = EXC_ARM_MTE_TAG_FAULT"]) + + self.runCmd("memory tag read ptr-1 ptr+33") + output = self.res.GetOutput() + self.assertEqual(output.count("(mismatch)"), 4) + tags = self._parse_memory_tags(output, 4) + self.assertTrue(all(t != ptr_tag for t in tags)) diff --git a/lldb/test/API/macosx/mte/main.c b/lldb/test/API/macosx/mte/main.c new file mode 100644 index 000000000000..f9f6b1594ef4 --- /dev/null +++ b/lldb/test/API/macosx/mte/main.c @@ -0,0 +1,28 @@ +#include <malloc/malloc.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// Produce some names on the trace +const size_t tag_granule = 16; +static uint8_t *my_malloc(void) { return malloc(2 * tag_granule); } +static uint8_t *allocate(void) { return my_malloc(); } + +static void my_free(void *ptr) { free(ptr); } +static void deallocate(void *ptr) { my_free(ptr); } + +static void touch_memory(uint8_t *ptr) { ptr[7] = 1; } // invalid access +static void modify(uint8_t *ptr) { touch_memory(ptr); } + +int main() { + uint8_t *ptr = allocate(); + + strncpy((char *)ptr, "Hello", 16); + strncpy((char *)ptr + 16, "World", 16); + + deallocate(ptr); // before free + + modify(ptr); // use-after-free + + return 0; +} diff --git a/lldb/test/API/macosx/mte/mte-entitlements.plist b/lldb/test/API/macosx/mte/mte-entitlements.plist new file mode 100644 index 000000000000..6de5d5634d87 --- /dev/null +++ b/lldb/test/API/macosx/mte/mte-entitlements.plist @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>com.apple.security.hardened-process</key> + <true/> + <key>com.apple.security.hardened-process.checked-allocations</key> + <true/> +</dict> +</plist> diff --git a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py index 43f45f330ee2..44b118328801 100644 --- a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py +++ b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py @@ -294,3 +294,150 @@ class DebuggerAPITestCase(TestBase): self.assertEqual(instance_str, class_str) self.assertEqual(class_str, property_str) + + def test_find_target_with_unique_id(self): + """Test SBDebugger.FindTargetByGloballyUniqueID() functionality.""" + + # Test with invalid ID - should return invalid target + invalid_target = self.dbg.FindTargetByGloballyUniqueID(999999) + self.assertFalse(invalid_target.IsValid()) + + # Test with ID 0 - should return invalid target + zero_target = self.dbg.FindTargetByGloballyUniqueID(0) + self.assertFalse(zero_target.IsValid()) + + # Build a real executable and create target with it + self.build() + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target.IsValid()) + + # Find the target using its unique ID + unique_id = target.GetGloballyUniqueID() + self.assertNotEqual(unique_id, lldb.LLDB_INVALID_GLOBALLY_UNIQUE_TARGET_ID) + found_target = self.dbg.FindTargetByGloballyUniqueID(unique_id) + self.assertTrue(found_target.IsValid()) + self.assertEqual( + self.dbg.GetIndexOfTarget(target), self.dbg.GetIndexOfTarget(found_target) + ) + self.assertEqual(found_target.GetGloballyUniqueID(), unique_id) + + def test_target_unique_id_uniqueness(self): + """Test that Target.GetGloballyUniqueID() returns unique values across multiple targets.""" + + # Create multiple targets and verify they all have unique IDs + self.build() + exe = self.getBuildArtifact("a.out") + targets = [] + unique_ids = set() + + for i in range(10): + target = self.dbg.CreateTarget(exe) + self.assertTrue(target.IsValid()) + + unique_id = target.GetGloballyUniqueID() + self.assertNotEqual(unique_id, 0) + + # Verify this ID hasn't been used before + self.assertNotIn( + unique_id, unique_ids, f"Duplicate unique ID found: {unique_id}" + ) + + unique_ids.add(unique_id) + targets.append(target) + + # Verify all targets can still be found by their IDs + for target in targets: + unique_id = target.GetGloballyUniqueID() + found = self.dbg.FindTargetByGloballyUniqueID(unique_id) + self.assertTrue(found.IsValid()) + self.assertEqual(found.GetGloballyUniqueID(), unique_id) + + def test_target_unique_id_uniqueness_after_deletion(self): + """Test finding targets have unique ID after target deletion.""" + # Create two targets + self.build() + exe = self.getBuildArtifact("a.out") + target1 = self.dbg.CreateTarget(exe) + target2 = self.dbg.CreateTarget(exe) + self.assertTrue(target1.IsValid()) + self.assertTrue(target2.IsValid()) + + unique_id1 = target1.GetGloballyUniqueID() + unique_id2 = target2.GetGloballyUniqueID() + self.assertNotEqual(unique_id1, 0) + self.assertNotEqual(unique_id2, 0) + self.assertNotEqual(unique_id1, unique_id2) + + # Verify we can find them initially + found_target1 = self.dbg.FindTargetByGloballyUniqueID(unique_id1) + found_target2 = self.dbg.FindTargetByGloballyUniqueID(unique_id2) + self.assertTrue(found_target1.IsValid()) + self.assertTrue(found_target2.IsValid()) + target2_index = self.dbg.GetIndexOfTarget(target2) + + # Delete target 2 + deleted = self.dbg.DeleteTarget(target2) + self.assertTrue(deleted) + + # Try to find the deleted target - should not be found + not_found_target = self.dbg.FindTargetByGloballyUniqueID(unique_id2) + self.assertFalse(not_found_target.IsValid()) + + # Create a new target + target3 = self.dbg.CreateTarget(exe) + self.assertTrue(target3.IsValid()) + # Target list index of target3 should be the same as target2's + # since it was deleted, but it should have a distinct unique ID + target3_index = self.dbg.GetIndexOfTarget(target3) + unique_id3 = target3.GetGloballyUniqueID() + self.assertEqual(target3_index, target2_index) + self.assertNotEqual(unique_id3, unique_id2) + self.assertNotEqual(unique_id3, unique_id1) + # Make sure we can find the new target + found_target3 = self.dbg.FindTargetByGloballyUniqueID( + target3.GetGloballyUniqueID() + ) + self.assertTrue(found_target3.IsValid()) + + def test_target_globally_unique_id_across_debuggers(self): + """Test that target IDs are globally unique across multiple debuggers.""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Create two debuggers with targets each + debugger1 = lldb.SBDebugger.Create() + debugger2 = lldb.SBDebugger.Create() + self.addTearDownHook(lambda: lldb.SBDebugger.Destroy(debugger1)) + self.addTearDownHook(lambda: lldb.SBDebugger.Destroy(debugger2)) + + # Create 2 targets per debugger + targets_d1 = [debugger1.CreateTarget(exe), debugger1.CreateTarget(exe)] + targets_d2 = [debugger2.CreateTarget(exe), debugger2.CreateTarget(exe)] + targets = targets_d1 + targets_d2 + + # Get all IDs and verify they're unique + ids = [target.GetGloballyUniqueID() for target in targets] + self.assertEqual( + len(set(ids)), len(ids), f"IDs should be globally unique: {ids}" + ) + self.assertTrue( + all(uid != lldb.LLDB_INVALID_GLOBALLY_UNIQUE_TARGET_ID for uid in ids), + "All IDs should be valid", + ) + + # Verify targets can be found by their IDs in respective debuggers + for debugger, target_pair in [ + (debugger1, targets[:2]), + (debugger2, targets[2:]), + ]: + for target in target_pair: + found = debugger.FindTargetByGloballyUniqueID( + target.GetGloballyUniqueID() + ) + self.assertTrue( + found.IsValid(), "Target should be found by its unique ID" + ) + self.assertEqual( + found.GetGloballyUniqueID(), target.GetGloballyUniqueID() + ) diff --git a/lldb/test/API/python_api/default-constructor/sb_filespec.py b/lldb/test/API/python_api/default-constructor/sb_filespec.py index 4ab5c49c37eb..5dd78b1ace98 100644 --- a/lldb/test/API/python_api/default-constructor/sb_filespec.py +++ b/lldb/test/API/python_api/default-constructor/sb_filespec.py @@ -10,5 +10,5 @@ def fuzz_obj(obj): obj.ResolveExecutableLocation() obj.GetFilename() obj.GetDirectory() - obj.GetPath(None, 0) + obj.GetPath(1) obj.GetDescription(lldb.SBStream()) diff --git a/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py b/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py index 1029bdc3096d..01ed11a5a112 100644 --- a/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py +++ b/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py @@ -1,4 +1,4 @@ -"""Test the SBCommandInterpreter APIs.""" +"""tESt the SBCommandInterpreter APIs.""" import json import lldb @@ -156,13 +156,15 @@ class CommandInterpreterAPICase(TestBase): self.assertEqual(transcript[0]["error"], "") # (lldb) an-unknown-command - self.assertEqual(transcript[1], + self.assertEqual( + transcript[1], { "command": "an-unknown-command", # Unresolved commands don't have "commandName"/"commandArguments" "output": "", "error": "error: 'an-unknown-command' is not a valid command.\n", - }) + }, + ) # (lldb) br s -f main.c -l <line> self.assertEqual(transcript[2]["command"], "br s -f main.c -l %d" % self.line) @@ -175,14 +177,17 @@ class CommandInterpreterAPICase(TestBase): self.assertEqual(transcript[2]["error"], "") # (lldb) p a - self.assertEqual(transcript[3], + self.assertEqual( + transcript[3], { "command": "p a", "commandName": "dwim-print", "commandArguments": "-- a", "output": "", - "error": "error: <user expression 0>:1:1: use of undeclared identifier 'a'\n 1 | a\n | ^\n", - }) + "error": "note: Falling back to default language. Ran expression as 'Objective C++'.\n" + "error: <user expression 0>:1:1: use of undeclared identifier 'a'\n 1 | a\n | ^\n", + }, + ) # (lldb) statistics dump self.assertEqual(transcript[4]["command"], "statistics dump") @@ -203,7 +208,10 @@ class CommandInterpreterAPICase(TestBase): self.assertTrue(ci, VALID_COMMAND_INTERPRETER) # The setting's default value should be "false" - self.runCmd("settings show interpreter.save-transcript", "interpreter.save-transcript (boolean) = false\n") + self.runCmd( + "settings show interpreter.save-transcript", + "interpreter.save-transcript (boolean) = false\n", + ) def test_save_transcript_setting_off(self): ci = self.dbg.GetCommandInterpreter() @@ -250,17 +258,37 @@ class CommandInterpreterAPICase(TestBase): structured_data_1 = ci.GetTranscript() self.assertTrue(structured_data_1.IsValid()) self.assertEqual(structured_data_1.GetSize(), 1) - self.assertEqual(structured_data_1.GetItemAtIndex(0).GetValueForKey("command").GetStringValue(100), "version") + self.assertEqual( + structured_data_1.GetItemAtIndex(0) + .GetValueForKey("command") + .GetStringValue(100), + "version", + ) # Run some more commands and get the transcript as structured data again self.runCmd("help") structured_data_2 = ci.GetTranscript() self.assertTrue(structured_data_2.IsValid()) self.assertEqual(structured_data_2.GetSize(), 2) - self.assertEqual(structured_data_2.GetItemAtIndex(0).GetValueForKey("command").GetStringValue(100), "version") - self.assertEqual(structured_data_2.GetItemAtIndex(1).GetValueForKey("command").GetStringValue(100), "help") + self.assertEqual( + structured_data_2.GetItemAtIndex(0) + .GetValueForKey("command") + .GetStringValue(100), + "version", + ) + self.assertEqual( + structured_data_2.GetItemAtIndex(1) + .GetValueForKey("command") + .GetStringValue(100), + "help", + ) # Now, the first structured data should remain unchanged self.assertTrue(structured_data_1.IsValid()) self.assertEqual(structured_data_1.GetSize(), 1) - self.assertEqual(structured_data_1.GetItemAtIndex(0).GetValueForKey("command").GetStringValue(100), "version") + self.assertEqual( + structured_data_1.GetItemAtIndex(0) + .GetValueForKey("command") + .GetStringValue(100), + "version", + ) diff --git a/lldb/test/API/python_api/sbtype_basic_type/TestSBTypeBasicType.py b/lldb/test/API/python_api/sbtype_basic_type/TestSBTypeBasicType.py index 535d8b900673..f8594dfc6b78 100644 --- a/lldb/test/API/python_api/sbtype_basic_type/TestSBTypeBasicType.py +++ b/lldb/test/API/python_api/sbtype_basic_type/TestSBTypeBasicType.py @@ -28,3 +28,11 @@ class TestCase(TestBase): self.assertEqual(b.GetType().GetBasicType(), int_basic_type) self.assertEqual(c.GetType().GetBasicType(), int_basic_type) self.assertEqual(d.GetType().GetBasicType(), int_basic_type) + + # Check the size of the chosen basic types. + self.assertEqual(self.target().FindFirstType("__int128").size, 16) + self.assertEqual(self.target().FindFirstType("unsigned __int128").size, 16) + + # Check the size of the chosen aliases of basic types. + self.assertEqual(self.target().FindFirstType("__int128_t").size, 16) + self.assertEqual(self.target().FindFirstType("__uint128_t").size, 16) diff --git a/lldb/test/API/tools/lldb-dap/attach-commands/Makefile b/lldb/test/API/tools/lldb-dap/attach-commands/Makefile new file mode 100644 index 000000000000..10495940055b --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/attach-commands/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py b/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py new file mode 100644 index 000000000000..9e29f07db80f --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py @@ -0,0 +1,145 @@ +""" +Test lldb-dap attach commands +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbdap_testcase +import time + + +class TestDAP_attachCommands(lldbdap_testcase.DAPTestCaseBase): + @skipIfNetBSD # Hangs on NetBSD as well + def test_commands(self): + """ + Tests the "initCommands", "preRunCommands", "stopCommands", + "exitCommands", "terminateCommands" and "attachCommands" + that can be passed during attach. + + "initCommands" are a list of LLDB commands that get executed + before the target is created. + "preRunCommands" are a list of LLDB commands that get executed + after the target has been created and before the launch. + "stopCommands" are a list of LLDB commands that get executed each + time the program stops. + "exitCommands" are a list of LLDB commands that get executed when + the process exits + "attachCommands" are a list of LLDB commands that get executed and + must have a valid process in the selected target in LLDB after + they are done executing. This allows custom commands to create any + kind of debug session. + "terminateCommands" are a list of LLDB commands that get executed when + the debugger session terminates. + """ + program = self.build_and_create_debug_adapter_for_attach() + + # Here we just create a target and launch the process as a way to test + # if we are able to use attach commands to create any kind of a target + # and use it for debugging + attachCommands = [ + 'target create -d "%s"' % (program), + "process launch --stop-at-entry", + ] + initCommands = ["target list", "platform list"] + preRunCommands = ["image list a.out", "image dump sections a.out"] + postRunCommands = ["help trace", "help process trace"] + stopCommands = ["frame variable", "thread backtrace"] + exitCommands = ["expr 2+3", "expr 3+4"] + terminateCommands = ["expr 4+2"] + self.attach( + program=program, + attachCommands=attachCommands, + initCommands=initCommands, + preRunCommands=preRunCommands, + stopCommands=stopCommands, + exitCommands=exitCommands, + terminateCommands=terminateCommands, + postRunCommands=postRunCommands, + ) + # Get output from the console. This should contain both the + # "initCommands" and the "preRunCommands". + output = self.get_console() + # Verify all "initCommands" were found in console output + self.verify_commands("initCommands", output, initCommands) + # Verify all "preRunCommands" were found in console output + self.verify_commands("preRunCommands", output, preRunCommands) + # Verify all "postRunCommands" were found in console output + self.verify_commands("postRunCommands", output, postRunCommands) + + functions = ["main"] + breakpoint_ids = self.set_function_breakpoints(functions) + self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint") + self.continue_to_breakpoints(breakpoint_ids) + output = self.collect_console(pattern=stopCommands[-1]) + self.verify_commands("stopCommands", output, stopCommands) + + # Continue after launch and hit the "pause()" call and stop the target. + # Get output from the console. This should contain both the + # "stopCommands" that were run after we stop. + self.do_continue() + time.sleep(0.5) + self.dap_server.request_pause() + self.dap_server.wait_for_stopped() + output = self.collect_console(pattern=stopCommands[-1]) + self.verify_commands("stopCommands", output, stopCommands) + + # Continue until the program exits + self.continue_to_exit() + # Get output from the console. This should contain both the + # "exitCommands" that were run after the second breakpoint was hit + # and the "terminateCommands" due to the debugging session ending + output = self.collect_console( + pattern=terminateCommands[0], + ) + self.verify_commands("exitCommands", output, exitCommands) + self.verify_commands("terminateCommands", output, terminateCommands) + + def test_attach_command_process_failures(self): + """ + Tests that a 'attachCommands' is expected to leave the debugger's + selected target with a valid process. + """ + program = self.build_and_create_debug_adapter_for_attach() + attachCommands = ['script print("oops, forgot to attach to a process...")'] + resp = self.attach( + program=program, + attachCommands=attachCommands, + expectFailure=True, + ) + self.assertFalse(resp["success"]) + self.assertIn( + "attachCommands failed to attach to a process", + resp["body"]["error"]["format"], + ) + + @skipIfNetBSD # Hangs on NetBSD as well + def test_terminate_commands(self): + """ + Tests that the "terminateCommands", that can be passed during + attach, are run when the debugger is disconnected. + """ + program = self.build_and_create_debug_adapter_for_attach() + + # Here we just create a target and launch the process as a way to test + # if we are able to use attach commands to create any kind of a target + # and use it for debugging + attachCommands = [ + 'target create -d "%s"' % (program), + "process launch --stop-at-entry", + ] + terminateCommands = ["expr 4+2"] + self.attach( + program=program, + attachCommands=attachCommands, + terminateCommands=terminateCommands, + disconnectAutomatically=False, + ) + self.get_console() + # Once it's disconnected the console should contain the + # "terminateCommands" + self.dap_server.request_disconnect(terminateDebuggee=True) + output = self.collect_console( + pattern=terminateCommands[0], + ) + self.verify_commands("terminateCommands", output, terminateCommands) diff --git a/lldb/test/API/tools/lldb-dap/attach-commands/main.c b/lldb/test/API/tools/lldb-dap/attach-commands/main.c new file mode 100644 index 000000000000..f56d5d53afa0 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/attach-commands/main.c @@ -0,0 +1,30 @@ +#include "attach.h" +#include <stdio.h> +#ifdef _WIN32 +#include <process.h> +#include <windows.h> +#else +#include <unistd.h> +#endif + +int main(int argc, char const *argv[]) { + lldb_enable_attach(); + + if (argc >= 2) { + // Create the synchronization token. + FILE *f = fopen(argv[1], "wx"); + if (!f) + return 1; + fputs("\n", f); + fflush(f); + fclose(f); + } + + printf("pid = %i\n", getpid()); +#ifdef _WIN32 + Sleep(10 * 1000); +#else + sleep(10); +#endif + return 0; // breakpoint 1 +} 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 c54e21c1b973..5331a9f94ef1 100644 --- a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py +++ b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py @@ -11,50 +11,35 @@ import threading import time -def spawn_and_wait(program, delay): - if delay: - time.sleep(delay) - process = subprocess.Popen( - [program], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) - process.wait() - - class TestDAP_attach(lldbdap_testcase.DAPTestCaseBase): - def set_and_hit_breakpoint(self, continueToExit=True): - source = "main.c" - breakpoint1_line = line_number(source, "// breakpoint 1") - lines = [breakpoint1_line] - # Set breakpoint in the thread function so we can step the threads - breakpoint_ids = self.set_source_breakpoints(source, lines) - self.assertEqual( - len(breakpoint_ids), len(lines), "expect correct number of breakpoints" - ) - # Test binary will sleep for 10s, offset the breakpoint timeout - # accordingly. - timeout_offset = 10 - self.continue_to_breakpoints( - breakpoint_ids, timeout=timeout_offset + self.DEFAULT_TIMEOUT + def spawn(self, args): + self.process = subprocess.Popen( + args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, ) - if continueToExit: - self.continue_to_exit() - @skipIfNetBSD # Hangs on NetBSD as well + def spawn_and_wait(self, program, delay): + time.sleep(delay) + self.spawn([program]) + self.process.wait() + + def continue_and_verify_pid(self): + self.do_continue() + out, _ = self.process.communicate("foo") + self.assertIn(f"pid = {self.process.pid}", out) + def test_by_pid(self): """ Tests attaching to a process by process ID. """ program = self.build_and_create_debug_adapter_for_attach() - self.process = subprocess.Popen( - [program], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) + self.spawn([program]) self.attach(pid=self.process.pid) - self.set_and_hit_breakpoint(continueToExit=True) + self.continue_and_verify_pid() - @skipIfNetBSD # Hangs on NetBSD as well def test_by_name(self): """ Tests attaching to a process by process name. @@ -65,24 +50,20 @@ class TestDAP_attach(lldbdap_testcase.DAPTestCaseBase): pid_file_path = lldbutil.append_to_process_working_directory( self, "pid_file_%d" % (int(time.time())) ) - - popen = self.spawnSubprocess(program, [pid_file_path]) + self.spawn([program, pid_file_path]) lldbutil.wait_for_file_on_target(self, pid_file_path) self.attach(program=program) - self.set_and_hit_breakpoint(continueToExit=True) + self.continue_and_verify_pid() - @skipUnlessDarwin - @skipIfNetBSD # Hangs on NetBSD as well def test_by_name_waitFor(self): """ - Tests attaching to a process by process name and waiting for the - next instance of a process to be launched, ignoring all current - ones. + Tests waiting for, and attaching to a process by process name that + doesn't exist yet. """ program = self.build_and_create_debug_adapter_for_attach() self.spawn_thread = threading.Thread( - target=spawn_and_wait, + target=self.spawn_and_wait, args=( program, 1.0, @@ -90,140 +71,4 @@ class TestDAP_attach(lldbdap_testcase.DAPTestCaseBase): ) self.spawn_thread.start() self.attach(program=program, waitFor=True) - self.set_and_hit_breakpoint(continueToExit=True) - - @skipIfNetBSD # Hangs on NetBSD as well - def test_commands(self): - """ - Tests the "initCommands", "preRunCommands", "stopCommands", - "exitCommands", "terminateCommands" and "attachCommands" - that can be passed during attach. - - "initCommands" are a list of LLDB commands that get executed - before the target is created. - "preRunCommands" are a list of LLDB commands that get executed - after the target has been created and before the launch. - "stopCommands" are a list of LLDB commands that get executed each - time the program stops. - "exitCommands" are a list of LLDB commands that get executed when - the process exits - "attachCommands" are a list of LLDB commands that get executed and - must have a valid process in the selected target in LLDB after - they are done executing. This allows custom commands to create any - kind of debug session. - "terminateCommands" are a list of LLDB commands that get executed when - the debugger session terminates. - """ - program = self.build_and_create_debug_adapter_for_attach() - - # Here we just create a target and launch the process as a way to test - # if we are able to use attach commands to create any kind of a target - # and use it for debugging - attachCommands = [ - 'target create -d "%s"' % (program), - "process launch --stop-at-entry", - ] - initCommands = ["target list", "platform list"] - preRunCommands = ["image list a.out", "image dump sections a.out"] - postRunCommands = ["help trace", "help process trace"] - stopCommands = ["frame variable", "thread backtrace"] - exitCommands = ["expr 2+3", "expr 3+4"] - terminateCommands = ["expr 4+2"] - self.attach( - program=program, - attachCommands=attachCommands, - initCommands=initCommands, - preRunCommands=preRunCommands, - stopCommands=stopCommands, - exitCommands=exitCommands, - terminateCommands=terminateCommands, - postRunCommands=postRunCommands, - ) - # Get output from the console. This should contain both the - # "initCommands" and the "preRunCommands". - output = self.get_console() - # Verify all "initCommands" were found in console output - self.verify_commands("initCommands", output, initCommands) - # Verify all "preRunCommands" were found in console output - self.verify_commands("preRunCommands", output, preRunCommands) - # Verify all "postRunCommands" were found in console output - self.verify_commands("postRunCommands", output, postRunCommands) - - functions = ["main"] - breakpoint_ids = self.set_function_breakpoints(functions) - self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint") - self.continue_to_breakpoints(breakpoint_ids) - output = self.collect_console(timeout=10, pattern=stopCommands[-1]) - self.verify_commands("stopCommands", output, stopCommands) - - # Continue after launch and hit the "pause()" call and stop the target. - # Get output from the console. This should contain both the - # "stopCommands" that were run after we stop. - self.do_continue() - time.sleep(0.5) - self.dap_server.request_pause() - self.dap_server.wait_for_stopped() - output = self.collect_console(timeout=10, pattern=stopCommands[-1]) - self.verify_commands("stopCommands", output, stopCommands) - - # Continue until the program exits - self.continue_to_exit() - # Get output from the console. This should contain both the - # "exitCommands" that were run after the second breakpoint was hit - # and the "terminateCommands" due to the debugging session ending - output = self.collect_console( - timeout=10.0, - pattern=terminateCommands[0], - ) - self.verify_commands("exitCommands", output, exitCommands) - self.verify_commands("terminateCommands", output, terminateCommands) - - def test_attach_command_process_failures(self): - """ - Tests that a 'attachCommands' is expected to leave the debugger's - selected target with a valid process. - """ - program = self.build_and_create_debug_adapter_for_attach() - attachCommands = ['script print("oops, forgot to attach to a process...")'] - resp = self.attach( - program=program, - attachCommands=attachCommands, - expectFailure=True, - ) - self.assertFalse(resp["success"]) - self.assertIn( - "attachCommands failed to attach to a process", - resp["body"]["error"]["format"], - ) - - @skipIfNetBSD # Hangs on NetBSD as well - def test_terminate_commands(self): - """ - Tests that the "terminateCommands", that can be passed during - attach, are run when the debugger is disconnected. - """ - program = self.build_and_create_debug_adapter_for_attach() - - # Here we just create a target and launch the process as a way to test - # if we are able to use attach commands to create any kind of a target - # and use it for debugging - attachCommands = [ - 'target create -d "%s"' % (program), - "process launch --stop-at-entry", - ] - terminateCommands = ["expr 4+2"] - self.attach( - program=program, - attachCommands=attachCommands, - terminateCommands=terminateCommands, - disconnectAutomatically=False, - ) - self.get_console() - # Once it's disconnected the console should contain the - # "terminateCommands" - self.dap_server.request_disconnect(terminateDebuggee=True) - output = self.collect_console( - timeout=1.0, - pattern=terminateCommands[0], - ) - self.verify_commands("terminateCommands", output, terminateCommands) + self.continue_and_verify_pid() diff --git a/lldb/test/API/tools/lldb-dap/attach/main.c b/lldb/test/API/tools/lldb-dap/attach/main.c index f56d5d53afa0..e14cf71a7044 100644 --- a/lldb/test/API/tools/lldb-dap/attach/main.c +++ b/lldb/test/API/tools/lldb-dap/attach/main.c @@ -2,7 +2,6 @@ #include <stdio.h> #ifdef _WIN32 #include <process.h> -#include <windows.h> #else #include <unistd.h> #endif @@ -20,11 +19,9 @@ int main(int argc, char const *argv[]) { fclose(f); } + // Wait on input from stdin. + getchar(); + printf("pid = %i\n", getpid()); -#ifdef _WIN32 - Sleep(10 * 1000); -#else - sleep(10); -#endif - return 0; // breakpoint 1 + return 0; } diff --git a/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py b/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py index 151ad761a504..beab4d6c1f5a 100644 --- a/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py +++ b/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py @@ -82,14 +82,14 @@ class TestDAP_breakpointEvents(lldbdap_testcase.DAPTestCaseBase): ) # Flush the breakpoint events. - self.dap_server.wait_for_breakpoint_events(timeout=5) + self.dap_server.wait_for_breakpoint_events() # Continue to the breakpoint self.continue_to_breakpoints(dap_breakpoint_ids) verified_breakpoint_ids = [] unverified_breakpoint_ids = [] - for breakpoint_event in self.dap_server.wait_for_breakpoint_events(timeout=5): + for breakpoint_event in self.dap_server.wait_for_breakpoint_events(): breakpoint = breakpoint_event["body"]["breakpoint"] id = breakpoint["id"] if breakpoint["verified"]: diff --git a/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py b/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py index e722fcea9283..14789a669468 100644 --- a/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py +++ b/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py @@ -46,7 +46,7 @@ class TestDAP_cancel(lldbdap_testcase.DAPTestCaseBase): # Use a relatively short timeout since this is only to ensure the # following request is queued. - blocking_seq = self.async_blocking_request(duration=1.0) + blocking_seq = self.async_blocking_request(duration=self.DEFAULT_TIMEOUT / 10) # Use a longer timeout to ensure we catch if the request was interrupted # properly. pending_seq = self.async_blocking_request(duration=self.DEFAULT_TIMEOUT / 2) diff --git a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py index e61d2480ea4b..f53813a8a48f 100644 --- a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py +++ b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py @@ -23,7 +23,6 @@ class TestDAP_commands(lldbdap_testcase.DAPTestCaseBase): exitCommands=["?" + command_quiet, command_not_quiet], ) full_output = self.collect_console( - timeout=1.0, pattern=command_not_quiet, ) self.assertNotIn(command_quiet, full_output) @@ -51,7 +50,6 @@ class TestDAP_commands(lldbdap_testcase.DAPTestCaseBase): expectFailure=True, ) full_output = self.collect_console( - timeout=1.0, pattern=command_abort_on_error, ) self.assertNotIn(command_quiet, full_output) diff --git a/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py b/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py index af5c62a8c4eb..9fbe9aaee8c6 100644 --- a/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py +++ b/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py @@ -44,7 +44,7 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): """ process = self.launch() process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_SUCCESS) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_SUCCESS) def test_invalid_header(self): """ @@ -54,7 +54,7 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): process = self.launch() process.stdin.write(b"not the correct message header") process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_FAILURE) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_FAILURE) def test_partial_header(self): """ @@ -64,7 +64,7 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): process = self.launch() process.stdin.write(b"Content-Length: ") process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_FAILURE) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_FAILURE) def test_incorrect_content_length(self): """ @@ -74,7 +74,7 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): process = self.launch() process.stdin.write(b"Content-Length: abc") process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_FAILURE) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_FAILURE) def test_partial_content_length(self): """ @@ -84,4 +84,4 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): process = self.launch() process.stdin.write(b"Content-Length: 10\r\n\r\n{") process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_FAILURE) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_FAILURE) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py index ceef95dfcd0d..8db2316e73fc 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py @@ -632,7 +632,27 @@ class TestDAP_launch(lldbdap_testcase.DAPTestCaseBase): program = self.getBuildArtifact("a.out") with tempfile.NamedTemporaryFile("rt") as f: - self.launch(program, stdio=[None, f.name, None]) + self.launch(program, stdio=[None, f.name]) + self.continue_to_exit() + lines = f.readlines() + self.assertIn( + program, lines[0], "make sure program path is in first argument" + ) + + @skipIfAsan + @skipIfWindows + @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) + def test_stdio_redirection_and_console(self): + """ + Test stdio redirection and console. + """ + self.build_and_create_debug_adapter() + program = self.getBuildArtifact("a.out") + + with tempfile.NamedTemporaryFile("rt") as f: + self.launch( + program, console="integratedTerminal", stdio=[None, f.name, None] + ) self.continue_to_exit() lines = f.readlines() self.assertIn( diff --git a/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py b/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py index bb835af12f5e..1f4afabbd161 100644 --- a/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py +++ b/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py @@ -23,15 +23,15 @@ class TestDAP_module_event(lldbdap_testcase.DAPTestCaseBase): self.continue_to_breakpoints(breakpoint_ids) # We're now stopped at breakpoint 1 before the dlopen. Flush all the module events. - event = self.dap_server.wait_for_event(["module"], 0.25) + event = self.dap_server.wait_for_event(["module"]) while event is not None: - event = self.dap_server.wait_for_event(["module"], 0.25) + event = self.dap_server.wait_for_event(["module"]) # Continue to the second breakpoint, before the dlclose. self.continue_to_breakpoints(breakpoint_ids) # Make sure we got a module event for libother. - event = self.dap_server.wait_for_event(["module"], 5) + event = self.dap_server.wait_for_event(["module"]) self.assertIsNotNone(event, "didn't get a module event") module_name = event["body"]["module"]["name"] module_id = event["body"]["module"]["id"] @@ -42,7 +42,7 @@ class TestDAP_module_event(lldbdap_testcase.DAPTestCaseBase): self.continue_to_breakpoints(breakpoint_ids) # Make sure we got a module event for libother. - event = self.dap_server.wait_for_event(["module"], 5) + event = self.dap_server.wait_for_event(["module"]) self.assertIsNotNone(event, "didn't get a module event") reason = event["body"]["reason"] self.assertEqual(reason, "removed") @@ -55,8 +55,4 @@ class TestDAP_module_event(lldbdap_testcase.DAPTestCaseBase): self.assertListEqual(list(module_data.keys()), required_keys) self.assertEqual(module_data["name"], "", "expects empty name.") - # Make sure we do not send another event - event = self.dap_server.wait_for_event(["module"], 3) - self.assertIsNone(event, "expects no events.") - self.continue_to_exit() diff --git a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py index c5a68372d822..0ed53dac5d86 100644 --- a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py +++ b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py @@ -67,7 +67,7 @@ class TestDAP_module(lldbdap_testcase.DAPTestCaseBase): # Collect all the module names we saw as events. module_new_names = [] module_changed_names = [] - module_event = self.dap_server.wait_for_event(["module"], 1) + module_event = self.dap_server.wait_for_event(["module"]) while module_event is not None: reason = module_event["body"]["reason"] if reason == "new": @@ -75,7 +75,7 @@ class TestDAP_module(lldbdap_testcase.DAPTestCaseBase): elif reason == "changed": module_changed_names.append(module_event["body"]["module"]["name"]) - module_event = self.dap_server.wait_for_event(["module"], 1) + module_event = self.dap_server.wait_for_event(["module"]) # Make sure we got an event for every active module. self.assertNotEqual(len(module_new_names), 0) diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py index fe978a9a7335..0065258920ec 100644 --- a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -29,7 +29,7 @@ class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): self.continue_to_breakpoints(breakpoint_ids) # Ensure partial messages are still sent. - output = self.collect_stdout(timeout=1.0, pattern="abcdef") + output = self.collect_stdout(pattern="abcdef") self.assertTrue(output and len(output) > 0, "expect program stdout") self.continue_to_exit() diff --git a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py index 67483798f226..e1ad1425a993 100644 --- a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py +++ b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py @@ -105,7 +105,7 @@ class TestDAP_restart_console(lldbdap_testcase.DAPTestCaseBase): # Restart and check that we still get a stopped event before reaching # main. self.dap_server.request_restart() - stopped_events = self.dap_server.wait_for_stopped(timeout=20) + stopped_events = self.dap_server.wait_for_stopped() self.verify_stopped_on_entry(stopped_events) # continue to main diff --git a/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py index 08c225b3cada..6008a0cb0237 100644 --- a/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py +++ b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py @@ -29,7 +29,7 @@ class TestDAP_stackTraceMissingSourcePath(lldbdap_testcase.DAPTestCaseBase): """ Build the program and run until the breakpoint is hit, and return the stack frames. """ - other_source_file = "other.c" + other_source_file = self.getBuildArtifact("other.c") with delete_file_on_exit(other_source_file): with open(other_source_file, "w") as f: f.write(OTHER_C_SOURCE_CODE) @@ -169,3 +169,4 @@ class TestDAP_stackTraceMissingSourcePath(lldbdap_testcase.DAPTestCaseBase): self.verify_frames_source( frames, main_frame_assembly=False, other_frame_assembly=False ) + self.continue_to_exit() diff --git a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py index 13a694602f23..977d6ce9dac8 100644 --- a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py +++ b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py @@ -65,6 +65,11 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): self.assertNotIn( key, actual, 'key "%s" is not expected in %s' % (key, actual) ) + isReadOnly = verify_dict.get("readOnly", False) + attributes = actual.get("presentationHint", {}).get("attributes", []) + self.assertEqual( + isReadOnly, "readOnly" in attributes, "%s %s" % (verify_dict, actual) + ) hasVariablesReference = "variablesReference" in actual varRef = None if hasVariablesReference: @@ -179,8 +184,9 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): "children": { "x": {"equals": {"type": "int", "value": "11"}}, "y": {"equals": {"type": "int", "value": "22"}}, - "buffer": {"children": buffer_children}, + "buffer": {"children": buffer_children, "readOnly": True}, }, + "readOnly": True, }, "x": {"equals": {"type": "int"}}, } @@ -444,8 +450,10 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): "buffer": { "children": buffer_children, "equals": {"indexedVariables": 16}, + "readOnly": True, }, }, + "readOnly": True, }, "x": { "equals": {"type": "int"}, @@ -528,7 +536,7 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): "children": { "x": {"equals": {"type": "int", "value": "11"}}, "y": {"equals": {"type": "int", "value": "22"}}, - "buffer": {"children": buffer_children}, + "buffer": {"children": buffer_children, "readOnly": True}, }, } @@ -622,11 +630,17 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): # "[raw]" child. raw_child_count = 1 if enableSyntheticChildDebugging else 0 verify_locals = { - "small_array": {"equals": {"indexedVariables": 5}}, - "large_array": {"equals": {"indexedVariables": 200}}, - "small_vector": {"equals": {"indexedVariables": 5 + raw_child_count}}, - "large_vector": {"equals": {"indexedVariables": 200 + raw_child_count}}, - "pt": {"missing": ["indexedVariables"]}, + "small_array": {"equals": {"indexedVariables": 5}, "readOnly": True}, + "large_array": {"equals": {"indexedVariables": 200}, "readOnly": True}, + "small_vector": { + "equals": {"indexedVariables": 5 + raw_child_count}, + "readOnly": True, + }, + "large_vector": { + "equals": {"indexedVariables": 200 + raw_child_count}, + "readOnly": True, + }, + "pt": {"missing": ["indexedVariables"], "readOnly": True}, } self.verify_variables(verify_locals, locals) @@ -640,7 +654,10 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): "[4]": {"equals": {"type": "int", "value": "0"}}, } if enableSyntheticChildDebugging: - verify_children["[raw]"] = ({"contains": {"type": ["vector"]}},) + verify_children["[raw]"] = { + "contains": {"type": ["vector"]}, + "readOnly": True, + } children = self.dap_server.request_variables(locals[2]["variablesReference"])[ "body" @@ -660,7 +677,7 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): return_name: {"equals": {"type": "int", "value": "300"}}, "argc": {}, "argv": {}, - "pt": {}, + "pt": {"readOnly": True}, "x": {}, "return_result": {"equals": {"type": "int"}}, } diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py index 13c4a85f51f7..ef1d546cf171 100644 --- a/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py +++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py @@ -2,6 +2,7 @@ import random from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.support import seven from fork_testbase import GdbRemoteForkTestBase diff --git a/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py b/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py index c01f6d83fafe..f1c0519ae56d 100644 --- a/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py +++ b/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py @@ -22,7 +22,9 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test.lldbdwarf import * from lldbsuite.test import lldbutil, lldbplatformutil - +# On Linux systems with Yama ptrace_scope = 1 there is a race condition when the +# debugee enables tracing. See https://github.com/llvm/llvm-project/issues/161510. +@skipIfLinux class LldbGdbServerTestCase( gdbremote_testcase.GdbRemoteTestCaseBase, DwarfOpcodeParser ): diff --git a/lldb/test/API/tools/lldb-server/main.cpp b/lldb/test/API/tools/lldb-server/main.cpp index 0e9323cce88c..7e84552b0f25 100644 --- a/lldb/test/API/tools/lldb-server/main.cpp +++ b/lldb/test/API/tools/lldb-server/main.cpp @@ -5,6 +5,7 @@ #include <cstdlib> #include <cstring> #include <errno.h> +#include <fstream> #include <future> #include <inttypes.h> #include <memory> @@ -265,7 +266,11 @@ int main(int argc, char **argv) { // Process command line args. for (int i = 1; i < argc; ++i) { std::string arg = argv[i]; - if (consume_front(arg, "stderr:")) { + if (consume_front(arg, "syncfile:")) { + // Write to this file to tell test framework that attaching is now + // possible. + std::ofstream(arg).close(); + } else if (consume_front(arg, "stderr:")) { // Treat remainder as text to go to stderr. fprintf(stderr, "%s\n", arg.c_str()); } else if (consume_front(arg, "retval:")) { diff --git a/lldb/test/Shell/Driver/LocalLLDBInit.test b/lldb/test/Shell/Driver/LocalLLDBInit.test index 5db545e7ec56..2aa8c527929f 100644 --- a/lldb/test/Shell/Driver/LocalLLDBInit.test +++ b/lldb/test/Shell/Driver/LocalLLDBInit.test @@ -9,7 +9,7 @@ # RUN: env HOME=%t.home %lldb-init -local-lldbinit -o 'settings show frame-format' 2>&1 | FileCheck %s --check-prefix=ALLOWINIT --check-prefix=NOINIT # RUN: %lldb -o 'settings show frame-format' 2>&1 | FileCheck %s --check-prefix=NOINIT --check-prefix=CHECK -# WARNINIT: There is a .lldbinit file in the current directory which is not being read. +# WARNINIT: warning: There is a .lldbinit file in the current directory which is not being read. # NOINIT-NOT: There is a .lldbinit file in the current directory which is not being read. # CHECK-NOT: bogus # ALLOWINIT: name 'prlnt' is not defined diff --git a/lldb/test/Shell/Expr/TestExprLanguageNote.test b/lldb/test/Shell/Expr/TestExprLanguageNote.test new file mode 100644 index 000000000000..e8e4e1399e45 --- /dev/null +++ b/lldb/test/Shell/Expr/TestExprLanguageNote.test @@ -0,0 +1,88 @@ +# RUN: split-file %s %t +# RUN: %clang_host -g %t/main.cpp -o %t.out +# +# RUN: %lldb -x -b -o "settings set interpreter.stop-command-source-on-error false" \ +# RUN: -s %t/no-target.input 2>&1 | FileCheck %s --check-prefix=CHECK-NO-TARGET +# +# RUN: %lldb %t.out -x -b -o "settings set interpreter.stop-command-source-on-error false" \ +# RUN: -s %t/with-target.input 2>&1 | FileCheck %s --check-prefix=CHECK-TARGET + +#--- main.cpp + +int main() { + int x = 10; + return x; +} + +#--- with-target.input + +expr blah + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET: note: Falling back to default language. Ran expression as 'Objective C++'. + +b 4 +run + +expr blah + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET: note: Ran expression as '{{(ISO )?}}C++{{.*}}' + +expr -l objc -- blah + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET: note: Expression evaluation in pure Objective-C not supported. Ran expression as 'Objective C++'. + +expr -l c -- blah + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET: note: Expression evaluation in pure C not supported. Ran expression as 'ISO C++'. + +expr -l c++14 -- blah + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET: note: Ran expression as 'C++14' + +expr -l c++20 -- blah + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET: note: Ran expression as 'C++20' + +expr -l objective-c++ -- blah + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET: note: Ran expression as 'Objective C++' + +# D uses TypeSystemClang but running expressions in it isn't supported. Test that we warn about this. +expr -l D -- blah + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET: note: Expression evaluation in D not supported. Falling back to default language. Ran expression as 'Objective C++'. + +expr -l c++17 -- x = 5 + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET-NOT: note: + +expr x = 5 + +# CHECK-TARGET: (lldb) expr +# CHECK-TARGET-NOT: note: + +#--- no-target.input + +expr blah + +# CHECK-NO-TARGET: (lldb) expr +# CHECK-NO-TARGET: note: Falling back to default language. Ran expression as 'Objective C++'. + +expr -l c++ -- 1 + 1 + +# CHECK-NO-TARGET: (lldb) expr +# CHECK-NO-TARGET-NOT: note: + +expr 1 + 1 + +# CHECK-NO-TARGET: (lldb) expr +# CHECK-NO-TARGET-NOT: note: diff --git a/lldb/test/Shell/Expr/TestGlobalSymbolObjCConflict.c b/lldb/test/Shell/Expr/TestGlobalSymbolObjCConflict.c new file mode 100644 index 000000000000..8f1bb62874a1 --- /dev/null +++ b/lldb/test/Shell/Expr/TestGlobalSymbolObjCConflict.c @@ -0,0 +1,35 @@ +// XFAIL: target-windows + +// Tests that LLDB correctly parses global symbols +// starting with 'O'. On some platforms (e.g., Darwin) +// C-symbols are prefixed with a '_'. The LLDB Macho-O +// parses handles Objective-C metadata symbols starting +// with '_OBJC' specially. This test ensures that we don't +// lose track of regular global symbols with a '_O' prefix +// in this. + +// RUN: %clang_host -c -g -fno-common %s -o %t.o +// RUN: %clang_host %t.o -o %t.out +// RUN: %lldb -b -x %t.out \ +// RUN: -o "b 29" \ +// RUN: -o "run" \ +// RUN: -o "p OglobalVar" \ +// RUN: -o "p Oabc" | FileCheck %s + +typedef struct { + int a; +} Oabc_t; + +Oabc_t Oabc; +int OglobalVar; + +int main(int argc, const char *argv[]) { + Oabc.a = 15; + OglobalVar = 10; + return OglobalVar + Oabc.a; +} + +// CHECK: (lldb) p OglobalVar +// CHECK: (int) 10 +// CHECK: (lldb) p Oabc +// CHECK: (Oabc_t) (a = 15) diff --git a/lldb/test/Shell/SymbolFile/DWARF/incomplete-member-beyond-parent-bounds.yaml b/lldb/test/Shell/SymbolFile/DWARF/incomplete-member-beyond-parent-bounds.yaml new file mode 100644 index 000000000000..4e659d02b3cd --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/incomplete-member-beyond-parent-bounds.yaml @@ -0,0 +1,104 @@ +# This is DWARF where we placed an incomplete type +# at an offset that is the parent DW_AT_byte_size. Check +# that we don't report an error in such cases. +# +# DW_TAG_compile_unit +# DW_AT_name ("main.cpp") +# DW_AT_language (DW_LANG_C) +# +# DW_TAG_structure_type +# DW_AT_name ("Incomplete") +# DW_AT_external (true) +# +# DW_TAG_structure_type +# DW_AT_name ("Foo") +# DW_AT_byte_size (0x04) +# +# DW_TAG_member +# DW_AT_name ("mem") +# DW_AT_data_member_location ("0x04") +# DW_AT_type (0x00000011 "Incomplete") +# +# NULL +# +# NULL + +# RUN: yaml2obj %s > %t +# RUN: lldb-test symbols --name=Foo --find=type %t 2>&1 | FileCheck %s + +# CHECK: Found 1 types: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_str: + - main.cpp + - Incomplete + - Foo + - mem + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Code: 0x2 + Tag: DW_TAG_structure_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + - Code: 0x3 + Tag: DW_TAG_structure_type + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x4 + Tag: DW_TAG_member + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Attribute: DW_AT_data_member_location + Form: DW_FORM_data1 + debug_info: + - Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x0 + - Value: 0x2 + - AbbrCode: 0x2 + Values: + - Value: 0x9 + - AbbrCode: 0x3 + Values: + - Value: 0x14 + - Value: 0x04 + - AbbrCode: 0x4 + Values: + - Value: 0x18 + - Value: 0x11 + - Value: 0x04 + - AbbrCode: 0x0 + - AbbrCode: 0x0 +... diff --git a/lldb/test/Shell/SymbolFile/DWARF/member-beyond-parent-bounds.yaml b/lldb/test/Shell/SymbolFile/DWARF/member-beyond-parent-bounds.yaml new file mode 100644 index 000000000000..2ac538ed1a85 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/member-beyond-parent-bounds.yaml @@ -0,0 +1,109 @@ +# This is malformed DWARF where we placed a non-zero sized type +# at an offset that is larger the parent DW_AT_byte_size. Check +# that we report an error in such cases. +# +# DW_TAG_compile_unit +# DW_AT_name ("main.cpp") +# DW_AT_language (DW_LANG_C) +# +# DW_TAG_base_type +# DW_AT_name ("int") +# DW_AT_encoding (DW_ATE_signed) +# DW_AT_byte_size (0x04) +# +# DW_TAG_structure_type +# DW_AT_name ("Foo") +# DW_AT_byte_size (0x04) +# +# DW_TAG_member +# DW_AT_name ("mem") +# DW_AT_data_member_location ("0x05") +# DW_AT_type (0x00000011 "int") +# +# NULL +# +# NULL + +# RUN: yaml2obj %s > %t +# RUN: lldb-test symbols --name=Foo --find=type %t 2>&1 | FileCheck %s + +# CHECK: Found 1 types: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_str: + - main.cpp + - int + - Foo + - mem + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Code: 0x2 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_encoding + Form: DW_FORM_data1 + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x3 + Tag: DW_TAG_structure_type + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x4 + Tag: DW_TAG_member + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Attribute: DW_AT_data_member_location + Form: DW_FORM_data1 + debug_info: + - Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x0 + - Value: 0x2 + - AbbrCode: 0x2 + Values: + - Value: 0x9 + - Value: 0x5 + - Value: 0x4 + - AbbrCode: 0x3 + Values: + - Value: 0x0d + - Value: 0x04 + - AbbrCode: 0x4 + Values: + - Value: 0x11 + - Value: 0x11 + - Value: 0x05 + - AbbrCode: 0x0 + - AbbrCode: 0x0 +... diff --git a/lldb/test/Shell/SymbolFile/DWARF/member-on-parent-bounds.yaml b/lldb/test/Shell/SymbolFile/DWARF/member-on-parent-bounds.yaml new file mode 100644 index 000000000000..736697c002ee --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/member-on-parent-bounds.yaml @@ -0,0 +1,109 @@ +# This is malformed DWARF where we placed a non-zero sized type +# at an offset that is the parent DW_AT_byte_size. Check +# that we report an error in such cases. +# +# DW_TAG_compile_unit +# DW_AT_name ("main.cpp") +# DW_AT_language (DW_LANG_C) +# +# DW_TAG_base_type +# DW_AT_name ("int") +# DW_AT_encoding (DW_ATE_signed) +# DW_AT_byte_size (0x04) +# +# DW_TAG_structure_type +# DW_AT_name ("Foo") +# DW_AT_byte_size (0x04) +# +# DW_TAG_member +# DW_AT_name ("mem") +# DW_AT_data_member_location ("0x04") +# DW_AT_type (0x00000011 "int") +# +# NULL +# +# NULL + +# RUN: yaml2obj %s > %t +# RUN: lldb-test symbols --name=Foo --find=type %t 2>&1 | FileCheck %s + +# CHECK: Found 1 types: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_str: + - main.cpp + - int + - Foo + - mem + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Code: 0x2 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_encoding + Form: DW_FORM_data1 + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x3 + Tag: DW_TAG_structure_type + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x4 + Tag: DW_TAG_member + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Attribute: DW_AT_data_member_location + Form: DW_FORM_data1 + debug_info: + - Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x0 + - Value: 0x2 + - AbbrCode: 0x2 + Values: + - Value: 0x9 + - Value: 0x5 + - Value: 0x4 + - AbbrCode: 0x3 + Values: + - Value: 0x0d + - Value: 0x04 + - AbbrCode: 0x4 + Values: + - Value: 0x11 + - Value: 0x11 + - Value: 0x04 + - AbbrCode: 0x0 + - AbbrCode: 0x0 +... diff --git a/lldb/test/Shell/SymbolFile/DWARF/union-types-no-member-location.yaml b/lldb/test/Shell/SymbolFile/DWARF/union-types-no-member-location.yaml index fbdc626ed113..1d1e129cdb7c 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/union-types-no-member-location.yaml +++ b/lldb/test/Shell/SymbolFile/DWARF/union-types-no-member-location.yaml @@ -48,14 +48,10 @@ # RUN: yaml2obj %s > %t # RUN: lldb-test symbols --name=UnionType --find=type %t > %t.stdout # RUN: cat %t.stdout | FileCheck --check-prefix=STDOUT %s -# RUN: lldb-test symbols --name=UnionType --find=type %t 2> %t.stderr -# RUN: cat %t.stderr | FileCheck --allow-empty --check-prefix=STDERR %s # STDOUT: Found 1 types: # STDOUT: {{(0x)?[0-9a-fA-F]+}}: Type{0x0000002b} , name = "UnionType", size = 32, compiler_type = 0x{{[0-9a-fA-F]+}} union UnionType { -# STDERR-NOT: error: union-types-no-member-location.yaml.tmp 0x00000031: DW_TAG_member 'array' refers to type 0x000000000000001f which extends beyond the bounds of 0x0000002b - --- !ELF FileHeader: Class: ELFCLASS64 diff --git a/lldb/test/Shell/SymbolFile/DWARF/zero-sized-member-in-parent-bounds.yaml b/lldb/test/Shell/SymbolFile/DWARF/zero-sized-member-in-parent-bounds.yaml new file mode 100644 index 000000000000..a98f62cd3405 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/zero-sized-member-in-parent-bounds.yaml @@ -0,0 +1,105 @@ +# This is DWARF where we placed a zero-sized type +# at an offset that is the parent DW_AT_byte_size. Check +# that we don't report an error in such cases. +# +# DW_TAG_compile_unit +# DW_AT_name ("main.cpp") +# DW_AT_language (DW_LANG_C) +# +# DW_TAG_structure_type +# DW_AT_name ("Bar") +# DW_AT_byte_size (0x00) +# +# DW_TAG_structure_type +# DW_AT_name ("Foo") +# DW_AT_byte_size (0x04) +# +# DW_TAG_member +# DW_AT_name ("mem") +# DW_AT_data_member_location ("0x04") +# DW_AT_type (0x00000011 "Bar") +# +# NULL +# +# NULL + +# RUN: yaml2obj %s > %t +# RUN: lldb-test symbols --name=Foo --find=type %t 2>&1 | FileCheck %s + +# CHECK: Found 1 types: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_str: + - main.cpp + - Bar + - Foo + - mem + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Code: 0x2 + Tag: DW_TAG_structure_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x3 + Tag: DW_TAG_structure_type + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x4 + Tag: DW_TAG_member + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Attribute: DW_AT_data_member_location + Form: DW_FORM_data1 + debug_info: + - Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x0 + - Value: 0x2 + - AbbrCode: 0x2 + Values: + - Value: 0x9 + - Value: 0x0 + - AbbrCode: 0x3 + Values: + - Value: 0x0d + - Value: 0x04 + - AbbrCode: 0x4 + Values: + - Value: 0x11 + - Value: 0x11 + - Value: 0x04 + - AbbrCode: 0x0 + - AbbrCode: 0x0 +... diff --git a/lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp b/lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp index a580d574a9ca..d4499373bb86 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp @@ -50,9 +50,9 @@ int main(int argc, char **argv) { // CHECK: 1: name = 'main', locations = 1 // CHECK: 1.1: where = break-by-function.cpp.tmp.exe`main + {{[0-9]+}} // CHECK: 2: name = 'OvlGlobalFn', locations = 3 -// CHECK: 2.1: where = break-by-function.cpp.tmp.exe`OvlGlobalFn + {{[0-9]+}} -// CHECK: 2.2: where = break-by-function.cpp.tmp.exe`OvlGlobalFn -// CHECK: 2.3: where = break-by-function.cpp.tmp.exe`OvlGlobalFn + {{[0-9]+}} +// CHECK: 2.1: where = break-by-function.cpp.tmp.exe`int OvlGlobalFn(int) + {{[0-9]+}} +// CHECK: 2.2: where = break-by-function.cpp.tmp.exe`int OvlGlobalFn(int, int) +// CHECK: 2.3: where = break-by-function.cpp.tmp.exe`int OvlGlobalFn(int, int, int) + {{[0-9]+}} // CHECK: 3: name = 'StaticFn', locations = 1 // CHECK: 3.1: where = break-by-function.cpp.tmp.exe`StaticFn + {{[0-9]+}} // CHECK: 4: name = 'DoesntExist', locations = 0 (pending) diff --git a/lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp b/lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp index 90ac633b0163..3d7de3275ed6 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp @@ -24,4 +24,4 @@ int main(int argc, char **argv) { // CHECK: (lldb) target create "{{.*}}break-by-line.cpp.tmp.exe" // CHECK: Current executable set to '{{.*}}break-by-line.cpp.tmp.exe' // CHECK: (lldb) break set -f break-by-line.cpp -l 15 -// CHECK: Breakpoint 1: where = break-by-line.cpp.tmp.exe`NS::NamespaceFn + {{[0-9]+}} at break-by-line.cpp:15 +// CHECK: Breakpoint 1: where = break-by-line.cpp.tmp.exe`int NS::NamespaceFn(int) + {{[0-9]+}} at break-by-line.cpp:15 diff --git a/lldb/test/Shell/SymbolFile/NativePDB/c-calling-conventions.cpp b/lldb/test/Shell/SymbolFile/NativePDB/c-calling-conventions.cpp new file mode 100644 index 000000000000..d1d0bb08dfec --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/c-calling-conventions.cpp @@ -0,0 +1,51 @@ +// clang-format off +// REQUIRES: lld, (target-x86 || target-x86_64) + +// RUN: %build --compiler=clang-cl --arch=32 --nodefaultlib --output=%t-32.exe %s +// RUN: lldb-test symbols %t-32.exe | FileCheck --check-prefixes CHECK-32,CHECK-BOTH %s +// RUN: %build --compiler=clang-cl --arch=64 --nodefaultlib --output=%t-64.exe %s +// RUN: lldb-test symbols %t-64.exe | FileCheck --check-prefixes CHECK-64,CHECK-BOTH %s + +extern "C" { +int FuncCCall() { return 0; } +int __stdcall FuncStdCall() { return 0; } +int __fastcall FuncFastCall() { return 0; } +int __vectorcall FuncVectorCall() { return 0; } + +int __cdecl _underscoreCdecl() { return 0; } +int __stdcall _underscoreStdcall() { return 0; } +int __fastcall _underscoreFastcall() { return 0; } +int __vectorcall _underscoreVectorcall() { return 0; } +} + +int main() { + FuncCCall(); + FuncStdCall(); + FuncFastCall(); + FuncVectorCall(); + _underscoreCdecl(); + _underscoreStdcall(); + _underscoreFastcall(); + _underscoreVectorcall(); + return 0; +} + +// CHECK-BOTH-DAG: Function{{.*}}, demangled = FuncCCall, +// CHECK-BOTH-DAG: Function{{.*}}, demangled = FuncVectorCall@@0, +// CHECK-BOTH-DAG: Function{{.*}}, demangled = _underscoreCdecl, +// CHECK-BOTH-DAG: Function{{.*}}, demangled = _underscoreVectorcall@@0, +// CHECK-BOTH-DAG: Function{{.*}}, demangled = main, + +// __stdcall and __fastcall aren't available on 64 bit + +// CHECK-32-DAG: Function{{.*}}, demangled = _FuncStdCall@0, +// CHECK-64-DAG: Function{{.*}}, demangled = FuncStdCall, + +// CHECK-32-DAG: Function{{.*}}, demangled = @FuncFastCall@0, +// CHECK-64-DAG: Function{{.*}}, demangled = FuncFastCall, + +// CHECK-32-DAG: Function{{.*}}, demangled = __underscoreStdcall@0, +// CHECK-64-DAG: Function{{.*}}, demangled = _underscoreStdcall, + +// CHECK-32-DAG: Function{{.*}}, demangled = @_underscoreFastcall@0, +// CHECK-64-DAG: Function{{.*}}, demangled = _underscoreFastcall, diff --git a/lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp b/lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp index b3f7b098a95d..05074aa61d32 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp @@ -25,7 +25,7 @@ int main(int argc, char **argv) { // CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+12>: mov qword ptr [rsp + 0x28], rdx // CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+17>: mov dword ptr [rsp + 0x24], ecx // CHECK: ** 15 foo(); -// CHECK: disassembly.cpp.tmp.exe[{{.*}}] <+21>: call {{.*}} ; foo at disassembly.cpp:12 +// CHECK: disassembly.cpp.tmp.exe[{{.*}}] <+21>: call {{.*}} ; int foo(void) at disassembly.cpp:12 // CHECK: ** 16 return 0; // CHECK-NEXT: 17 } // CHECK-NEXT: 18 diff --git a/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp b/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp index 3ef7a4c94c28..6204cbd34a58 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp @@ -148,11 +148,12 @@ int main(int argc, char **argv) { // FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (void)" // FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (char)" // FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (char, int, ...)" -// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "Class::overloaded_method" +// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "int Class::overloaded_method(bool)" // FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (void)" // FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (int)" // FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (_Bool)" -// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "overloaded_method" +// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "char overloaded_method(void)" +// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "char overloaded_method(int)" // FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "char (void)" // FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "char (int)" @@ -160,6 +161,6 @@ int main(int argc, char **argv) { // FIND-OVERLOAD-METHOD-DAG: Function: id = {{.*}}, name = "{{.*}}Struct::overloaded_method{{.*}}" // FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "int (void)" // FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "int (char)" -// FIND-OVERLOAD-METHOD-DAG: Function: id = {{.*}}, name = "Class::overloaded_method" +// FIND-OVERLOAD-METHOD-DAG: Function: id = {{.*}}, name = "bool Class::overloaded_method(void)" // FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (void)" // FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (int)" diff --git a/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s b/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s index fe2f397d60c0..b44b99a33626 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s +++ b/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s @@ -578,12 +578,12 @@ main: # @main # CHECK: (lldb) image lookup -a 0x14000104e -v # CHECK: LineEntry: [0x000000014000104e-0x0000000140001050): C:\src\test\a.cpp:1004 # CHECK-NEXT: Symbol: id = {{.*}}, range = [0x0000000140001011-0x0000000140001050), name="main" -# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "int64_t", valid ranges = <block>, location = [0x000000014000104e, 0x000000014000104f) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_reg24 XMM7, DW_OP_piece 0x4 +# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "long long", valid ranges = <block>, location = [0x000000014000104e, 0x000000014000104f) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_reg24 XMM7, DW_OP_piece 0x4 # CHECK-EMPTY: # CHECK: (lldb) image lookup -a 0x14000104f -v # CHECK: LineEntry: [0x000000014000104e-0x0000000140001050): C:\src\test\a.cpp:1004 # CHECK-NEXT: Symbol: id = {{.*}}, range = [0x0000000140001011-0x0000000140001050), name="main" -# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "int64_t", valid ranges = <block>, location = [0x000000014000104f, 0x0000000140001050) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_piece 0x4 +# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "long long", valid ranges = <block>, location = [0x000000014000104f, 0x0000000140001050) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_piece 0x4 # CHECK-EMPTY: .Ltmp26: diff --git a/lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp b/lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp index 44a8dc14c615..f44a5b9dd56e 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp @@ -55,7 +55,7 @@ int main(int argc, char **argv) { // CHECK-NEXT: (lldb) step // CHECK-NEXT: Process {{.*}} stopped // CHECK-NEXT: * thread #1, stop reason = step in -// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} +// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} // CHECK-NEXT: 6 // CHECK-NEXT: 7 // CHECK-NEXT: 8 int Function(int Param1, char Param2) { @@ -71,7 +71,7 @@ int main(int argc, char **argv) { // CHECK-NEXT: (lldb) step // CHECK-NEXT: Process {{.*}} stopped // CHECK-NEXT: * thread #1, stop reason = step in -// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} +// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} // CHECK-NEXT: 7 // CHECK-NEXT: 8 int Function(int Param1, char Param2) { // CHECK-NEXT: 9 unsigned Local1 = Param1 + 1; @@ -89,7 +89,7 @@ int main(int argc, char **argv) { // CHECK-NEXT: (lldb) step // CHECK-NEXT: Process {{.*}} stopped // CHECK-NEXT: * thread #1, stop reason = step in -// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} +// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} // CHECK-NEXT: 8 int Function(int Param1, char Param2) { // CHECK-NEXT: 9 unsigned Local1 = Param1 + 1; // CHECK-NEXT: 10 char Local2 = Param2 + 1; @@ -109,7 +109,7 @@ int main(int argc, char **argv) { // CHECK-NEXT: (lldb) step // CHECK-NEXT: Process {{.*}} stopped // CHECK-NEXT: * thread #1, stop reason = step in -// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} +// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} // CHECK-NEXT: 9 unsigned Local1 = Param1 + 1; // CHECK-NEXT: 10 char Local2 = Param2 + 1; // CHECK-NEXT: 11 ++Local1; @@ -129,7 +129,7 @@ int main(int argc, char **argv) { // CHECK-NEXT: (lldb) step // CHECK-NEXT: Process {{.*}} stopped // CHECK-NEXT: * thread #1, stop reason = step in -// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} +// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}} // CHECK-NEXT: 10 char Local2 = Param2 + 1; // CHECK-NEXT: 11 ++Local1; // CHECK-NEXT: 12 ++Local2; diff --git a/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp new file mode 100644 index 000000000000..3781194e2e99 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp @@ -0,0 +1,142 @@ +// REQUIRES: lld + +// Test that simple types can be found +// RUN: %build --std=c++20 --nodefaultlib --compiler=clang-cl --arch=64 -o %t.exe -- %s +// RUN: lldb-test symbols %t.exe | FileCheck %s +// RUN: lldb-test symbols %t.exe | FileCheck --check-prefix=FUNC-PARAMS %s + +bool *PB; +bool &RB = *PB; +bool *&RPB = PB; +const bool &CRB = RB; +bool *const BC = 0; +const bool *const CBC = 0; + +long AL[2]; + +const volatile short CVS = 0; +const short CS = 0; +volatile short VS; + +struct ReturnedStruct1 {}; +struct ReturnedStruct2 {}; + +struct MyStruct { + static ReturnedStruct1 static_fn(char *) { return {}; } + ReturnedStruct2 const_member_fn(char *) const { return {}; } + void volatile_member_fn() volatile {}; + void member_fn() {}; +}; + +void (*PF)(int, bool *, const float, double, ...); + +using Func = void(char16_t, MyStruct &); +Func *PF2; + +using SomeTypedef = long; +SomeTypedef ST; + +int main() { + bool b; + char c; + unsigned char uc; + char8_t c8; + + short s; + unsigned short us; + wchar_t wc; + char16_t c16; + + int i; + unsigned int ui; + long l; + unsigned long ul; + char32_t c32; + + long long ll; + unsigned long long ull; + + MyStruct my_struct; + + _Float16 f16; + + _Complex float cf; + _Complex double cd; + + __int128 i128; + unsigned __int128 ui128; + + decltype(nullptr) np; +} + +// CHECK-DAG: Type{{.*}} , name = "decltype(nullptr)", compiler_type = 0x{{[0-9a-f]+}} nullptr_t + +// CHECK-DAG: Type{{.*}} , name = "bool", size = 1, compiler_type = 0x{{[0-9a-f]+}} _Bool +// CHECK-DAG: Type{{.*}} , name = "char", size = 1, compiler_type = 0x{{[0-9a-f]+}} char +// CHECK-DAG: Type{{.*}} , name = "unsigned char", size = 1, compiler_type = 0x{{[0-9a-f]+}} unsigned char +// CHECK-DAG: Type{{.*}} , name = "char8_t", size = 1, compiler_type = 0x{{[0-9a-f]+}} char8_t + +// CHECK-DAG: Type{{.*}} , name = "short", size = 2, compiler_type = 0x{{[0-9a-f]+}} short +// CHECK-DAG: Type{{.*}} , name = "const volatile short", size = 2, compiler_type = 0x{{[0-9a-f]+}} const volatile short +// CHECK-DAG: Type{{.*}} , name = "const short", size = 2, compiler_type = 0x{{[0-9a-f]+}} const short +// CHECK-DAG: Type{{.*}} , name = "volatile short", size = 2, compiler_type = 0x{{[0-9a-f]+}} volatile short + +// CHECK-DAG: Type{{.*}} , name = "unsigned short", size = 2, compiler_type = 0x{{[0-9a-f]+}} unsigned short +// CHECK-DAG: Type{{.*}} , name = "wchar_t", size = 2, compiler_type = 0x{{[0-9a-f]+}} wchar_t +// CHECK-DAG: Type{{.*}} , name = "char16_t", size = 2, compiler_type = 0x{{[0-9a-f]+}} char16_t + +// CHECK-DAG: Type{{.*}} , name = "int", size = 4, compiler_type = 0x{{[0-9a-f]+}} int +// CHECK-DAG: Type{{.*}} , name = "unsigned", size = 4, compiler_type = 0x{{[0-9a-f]+}} unsigned int +// CHECK-DAG: Type{{.*}} , name = "long", size = 4, compiler_type = 0x{{[0-9a-f]+}} long +// CHECK-DAG: Type{{.*}} , name = "unsigned long", size = 4, compiler_type = 0x{{[0-9a-f]+}} unsigned long +// CHECK-DAG: Type{{.*}} , name = "char32_t", size = 4, compiler_type = 0x{{[0-9a-f]+}} char32_t + +// CHECK-DAG: Type{{.*}} , name = "long long", size = 8, compiler_type = 0x{{[0-9a-f]+}} long long +// CHECK-DAG: Type{{.*}} , name = "unsigned long long", size = 8, compiler_type = 0x{{[0-9a-f]+}} unsigned long long + +// CHECK-DAG: Type{{.*}} , name = "__int128", size = 16, compiler_type = 0x{{[0-9a-f]+}} __int128 +// CHECK-DAG: Type{{.*}} , name = "unsigned __int128", size = 16, compiler_type = 0x{{[0-9a-f]+}} unsigned __int128 + +// CHECK-DAG: Type{{.*}} , name = "_Float16", size = 2, compiler_type = 0x{{[0-9a-f]+}} __fp16 +// CHECK-DAG: Type{{.*}} , name = "float", size = 4, compiler_type = 0x{{[0-9a-f]+}} float +// CHECK-DAG: Type{{.*}} , name = "const float", size = 4, compiler_type = 0x{{[0-9a-f]+}} const float + +// CHECK-DAG: Type{{.*}} , name = "_Complex float", size = 4, compiler_type = 0x{{[0-9a-f]+}} _Complex float +// CHECK-DAG: Type{{.*}} , name = "_Complex double", size = 8, compiler_type = 0x{{[0-9a-f]+}} _Complex double + +// CHECK-DAG: Type{{.*}} , name = "ReturnedStruct1", size = 1, decl = simple-types.cpp:21, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct1 { +// CHECK-DAG: Type{{.*}} , name = "ReturnedStruct2", size = 1, decl = simple-types.cpp:22, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct2 { +// CHECK-DAG: Type{{.*}} , name = "MyStruct", size = 1, decl = simple-types.cpp:24, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct { + +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct *const +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} const struct MyStruct *const +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} volatile struct MyStruct *const +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct & + +// CHECK-DAG: Type{{.*}} , name = "const bool", size = 1, compiler_type = 0x{{[0-9a-f]+}} const _Bool +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} _Bool & +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} _Bool * +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} _Bool *& +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} const _Bool & +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} _Bool *const +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} const _Bool *const + +// CHECK-DAG: Type{{.*}} , name = "SomeTypedef", size = 4, compiler_type = 0x{{[0-9a-f]+}} typedef SomeTypedef +// CHECK-DAG: Type{{.*}} , name = "Func", size = 0, compiler_type = 0x{{[0-9a-f]+}} typedef Func + +// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} int (void) +// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} void (void) + +// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} void (int, _Bool *, const float, double, ...) +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} void (*)(int, _Bool *, const float, double, ...) + +// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} void (char16_t, struct MyStruct &) +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} void (*)(char16_t, struct MyStruct &) + +// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct1 (char *) +// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct2 (char *) + +// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} long[2] + +// double is used as a parameter to `PF`, but not created as an LLDB type +// FUNC-PARAMS-NOT: Type{{.*}} , name = "double" diff --git a/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp b/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp index 596a826f4a11..87eeebe7aa1b 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp @@ -24,19 +24,19 @@ int main(int argc, char **argv) { // CHECK: (lldb) thread backtrace // CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1 -// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12 +// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12 // CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20 // CHECK: (lldb) thread backtrace // CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1 -// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12 -// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12 +// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12 +// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12 // CHECK-NEXT: frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20 // CHECK: (lldb) thread backtrace // CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1 -// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=4, b=2) at stack_unwinding01.cpp:12 -// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12 -// CHECK-NEXT: frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12 +// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=4, b=2) at stack_unwinding01.cpp:12 +// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12 +// CHECK-NEXT: frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12 // CHECK-NEXT: frame #3: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20 diff --git a/lldb/test/Shell/SymbolFile/NativePDB/symtab.cpp b/lldb/test/Shell/SymbolFile/NativePDB/symtab.cpp index 81d643d9572d..beb5ae2f9025 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/symtab.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/symtab.cpp @@ -1,4 +1,4 @@ -// REQUIRES: x86 +// REQUIRES: lld, x86 // Test symtab reading // RUN: %build --compiler=clang-cl --arch=64 --nodefaultlib -o %t.exe -- %s diff --git a/lldb/test/Shell/SymbolFile/PDB/function-nested-block.test b/lldb/test/Shell/SymbolFile/PDB/function-nested-block.test index 9057d01c2584..4a2355bf23c9 100644 --- a/lldb/test/Shell/SymbolFile/PDB/function-nested-block.test +++ b/lldb/test/Shell/SymbolFile/PDB/function-nested-block.test @@ -4,7 +4,7 @@ RUN: lldb-test symbols -find=function -file FunctionNestedBlockTest.cpp -line 4 RUN: lldb-test symbols -find=block -file FunctionNestedBlockTest.cpp -line 4 %t.exe | FileCheck --check-prefix=CHECK-BLOCK %s CHECK-FUNCTION: Found 1 functions: -CHECK-FUNCTION: name = "{{.*}}", mangled = "{{_?}}main" +CHECK-FUNCTION: name = "main" CHECK-BLOCK: Found 1 blocks: CHECK-BLOCK: Blocks: id = {{.*}}, range = {{.*}} diff --git a/lldb/test/Shell/SymbolFile/PDB/variables.test b/lldb/test/Shell/SymbolFile/PDB/variables.test index 970d714c29c3..cb761de38241 100644 --- a/lldb/test/Shell/SymbolFile/PDB/variables.test +++ b/lldb/test/Shell/SymbolFile/PDB/variables.test @@ -42,7 +42,7 @@ GLOBALS-DAG: Variable{{.*}}, name = "g_Const" GLOBALS-SAME: scope = ??? (2) GLOBALS: Function -FUNC-F: Function{{.*}}, {{mangled = \?f@@YAHHH@Z|demangled = f}} +FUNC-F: Function{{.*}}, mangled = ?f@@YAHHH@Z FUNC-F-NEXT: Block FUNC-F-NEXT: Variable{{.*}}, name = "var_arg1" FUNC-F-SAME: scope = parameter @@ -64,14 +64,14 @@ FUNC-MAIN-SAME: scope = local FUNC-MAIN-NEXT: Variable{{.*}}, name = "a" FUNC-MAIN-SAME: scope = local -FUNC-CONSTRUCTOR: Function{{.*}}, {{(de)?}}mangled = {{.*}}Class::Class{{.*}} +FUNC-CONSTRUCTOR: Function{{.*}}, {{mangled = \?\?0Class@@QEAA@H@Z|demangled = .*Class::Class}} FUNC-CONSTRUCTOR-NEXT: Block FUNC-CONSTRUCTOR-NEXT: Variable{{.*}}, name = "this" FUNC-CONSTRUCTOR-SAME: scope = parameter FUNC-CONSTRUCTOR-NEXT: Variable{{.*}}, name = "a" FUNC-CONSTRUCTOR-SAME: scope = parameter -FUNC-MEMBER: Function{{.*}}, {{(de)?}}mangled = {{.*}}{{(Class::)?}}Func{{.*}} +FUNC-MEMBER: Function{{.*}}, {{mangled = \?Func@Class@@QEAAXXZ|demangled = .*Class::Func}} FUNC-MEMBER-NEXT: Block FUNC-MEMBER-NEXT: Variable{{.*}}, name = "this" FUNC-MEMBER-SAME: scope = parameter diff --git a/lldb/test/Shell/helper/build.py b/lldb/test/Shell/helper/build.py index caaa14f90af1..a5a7e997be04 100755 --- a/lldb/test/Shell/helper/build.py +++ b/lldb/test/Shell/helper/build.py @@ -9,12 +9,8 @@ import subprocess import sys if sys.platform == "win32": - # This module was renamed in Python 3. Make sure to import it using a - # consistent name regardless of python version. - try: - import winreg - except: - import _winreg as winreg + import winreg + if __name__ != "__main__": raise RuntimeError("Do not import this script, run it instead") diff --git a/lldb/test/Shell/lit.cfg.py b/lldb/test/Shell/lit.cfg.py index 505847fb763e..cdc0cfe51f7c 100644 --- a/lldb/test/Shell/lit.cfg.py +++ b/lldb/test/Shell/lit.cfg.py @@ -33,7 +33,7 @@ config.test_format = toolchain.ShTestLldb(not use_lit_shell) # suffixes: A list of file extensions to treat as test files. This is overriden # by individual lit.local.cfg files in the test subdirectories. -config.suffixes = [".test", ".cpp", ".s", ".m", ".ll"] +config.suffixes = [".test", ".cpp", ".s", ".m", ".ll", ".c"] # excludes: A list of directories to exclude from the testsuite. The 'Inputs' # subdirectories contain auxiliary inputs for various tests in their parent |
