From d9442afba1bd65fd0b5c93b67922eaed923445e2 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Tue, 10 Sep 2019 12:04:04 +0000 Subject: [PATCH] [lldb] Readd missing functionalities/breakpoint tests It seems when I restructured the test folders the functionalities/breakpoint was deleted. This just reverts this change and re-adds the tests. llvm-svn: 371512 --- .../breakpoint/address_breakpoints/Makefile | 6 + .../address_breakpoints/TestAddressBreakpoints.py | 96 ++++++ .../TestBadAddressBreakpoints.py | 47 +++ .../breakpoint/address_breakpoints/main.c | 8 + .../breakpoint/auto_continue/Makefile | 6 + .../auto_continue/TestBreakpointAutoContinue.py | 101 ++++++ .../breakpoint/auto_continue/main.c | 19 ++ .../breakpoint_by_line_and_column/Makefile | 6 + .../TestBreakpointByLineAndColumn.py | 45 +++ .../breakpoint_by_line_and_column/main.c | 22 ++ .../breakpoint/breakpoint_command/Makefile | 5 + .../breakpoint_command/TestBreakpointCommand.py | 285 ++++++++++++++++ .../TestBreakpointCommandsFromPython.py | 99 ++++++ .../breakpoint_command/TestRegexpBreakCommand.py | 71 ++++ .../breakpoint/breakpoint_command/a.c | 9 + .../breakpoint/breakpoint_command/b.c | 9 + .../breakpoint/breakpoint_command/bktptcmd.py | 5 + .../breakpoint/breakpoint_command/main.c | 16 + .../breakpoint/breakpoint_command/side_effect.py | 5 + .../breakpoint/breakpoint_conditions/Makefile | 6 + .../TestBreakpointConditions.py | 226 +++++++++++++ .../breakpoint/breakpoint_conditions/main.c | 53 +++ .../breakpoint/breakpoint_hit_count/Makefile | 5 + .../breakpoint_hit_count/TestBreakpointHitCount.py | 134 ++++++++ .../breakpoint/breakpoint_hit_count/main.cpp | 26 ++ .../breakpoint/breakpoint_ids/Makefile | 9 + .../breakpoint/breakpoint_ids/TestBreakpointIDs.py | 58 ++++ .../breakpoint/breakpoint_ids/main.cpp | 64 ++++ .../breakpoint/breakpoint_ignore_count/Makefile | 5 + .../TestBreakpointIgnoreCount.py | 151 +++++++++ .../breakpoint/breakpoint_ignore_count/main.c | 53 +++ .../breakpoint/breakpoint_in_delayslot/Makefile | 6 + .../TestAvoidBreakpointInDelaySlot.py | 87 +++++ .../breakpoint/breakpoint_in_delayslot/main.c | 21 ++ .../breakpoint/breakpoint_language/Makefile | 6 + .../breakpoint_language/TestBreakpointLanguage.py | 133 ++++++++ .../breakpoint/breakpoint_language/a.c | 5 + .../breakpoint/breakpoint_language/b.cpp | 5 + .../breakpoint/breakpoint_language/main.cpp | 11 + .../breakpoint/breakpoint_locations/Makefile | 9 + .../TestBreakpointLocations.py | 198 +++++++++++ .../breakpoint/breakpoint_locations/main.c | 43 +++ .../breakpoint/breakpoint_names/Makefile | 5 + .../breakpoint_names/TestBreakpointNames.py | 365 +++++++++++++++++++++ .../breakpoint/breakpoint_names/main.c | 53 +++ .../breakpoint/breakpoint_options/Makefile | 5 + .../breakpoint_options/TestBreakpointOptions.py | 114 +++++++ .../breakpoint/breakpoint_options/foo.cpp | 12 + .../breakpoint/breakpoint_options/main.cpp | 4 + .../breakpoint/breakpoint_set_restart/Makefile | 5 + .../TestBreakpointSetRestart.py | 50 +++ .../breakpoint/breakpoint_set_restart/main.cpp | 24 ++ .../breakpoint/comp_dir_symlink/Makefile | 14 + .../comp_dir_symlink/TestCompDirSymLink.py | 79 +++++ .../breakpoint/comp_dir_symlink/main.cpp | 12 + .../breakpoint/consecutive_breakpoints/Makefile | 9 + .../TestConsecutiveBreakpoints.py | 104 ++++++ .../breakpoint/consecutive_breakpoints/main.cpp | 18 + .../test/functionalities/breakpoint/cpp/Makefile | 9 + .../breakpoint/cpp/TestCPPBreakpointLocations.py | 112 +++++++ .../test/functionalities/breakpoint/cpp/main.cpp | 82 +++++ .../breakpoint/cpp_exception/Makefile | 5 + .../cpp_exception/TestCPPExceptionBreakpoint.py | 52 +++ .../breakpoint/cpp_exception/main.cpp | 13 + .../functionalities/breakpoint/debugbreak/Makefile | 5 + .../breakpoint/debugbreak/TestDebugBreak.py | 58 ++++ .../functionalities/breakpoint/debugbreak/main.c | 29 ++ .../breakpoint/dummy_target_breakpoints/Makefile | 9 + .../TestBreakpointsWithNoTargets.py | 72 ++++ .../breakpoint/dummy_target_breakpoints/main.c | 11 + .../breakpoint/global_constructor/Makefile | 7 + .../TestBreakpointInGlobalConstructor.py | 47 +++ .../breakpoint/global_constructor/foo.cpp | 7 + .../breakpoint/global_constructor/foo.h | 11 + .../breakpoint/global_constructor/main.cpp | 14 + .../Makefile | 6 + .../TestHWBreakMultiThread.py | 105 ++++++ .../main.cpp | 50 +++ .../breakpoint/inlined_breakpoints/Makefile | 5 + .../inlined_breakpoints/TestInlinedBreakpoints.py | 67 ++++ .../breakpoint/inlined_breakpoints/basic_type.cpp | 178 ++++++++++ .../breakpoint/inlined_breakpoints/int.cpp | 9 + .../breakpoint/move_nearest/Makefile | 7 + .../breakpoint/move_nearest/TestMoveNearest.py | 69 ++++ .../breakpoint/move_nearest/foo.cpp | 3 + .../functionalities/breakpoint/move_nearest/foo.h | 5 + .../breakpoint/move_nearest/main.cpp | 9 + .../test/functionalities/breakpoint/objc/Makefile | 7 + .../breakpoint/objc/TestObjCBreakpoints.py | 130 ++++++++ .../test/functionalities/breakpoint/objc/main.m | 98 ++++++ .../breakpoint/require_hw_breakpoints/Makefile | 9 + .../TestRequireHWBreakpoints.py | 103 ++++++ .../breakpoint/require_hw_breakpoints/main.c | 9 + .../breakpoint/scripted_bkpt/Makefile | 6 + .../scripted_bkpt/TestScriptedResolver.py | 197 +++++++++++ .../breakpoint/scripted_bkpt/main.c | 21 ++ .../breakpoint/scripted_bkpt/resolver.py | 54 +++ .../functionalities/breakpoint/serialize/Makefile | 5 + .../serialize/TestBreakpointSerialization.py | 291 ++++++++++++++++ .../functionalities/breakpoint/serialize/main.c | 53 +++ .../breakpoint/source_regexp/Makefile | 5 + .../source_regexp/TestSourceRegexBreakpoints.py | 104 ++++++ .../functionalities/breakpoint/source_regexp/a.c | 16 + .../functionalities/breakpoint/source_regexp/a.h | 1 + .../breakpoint/source_regexp/main.c | 17 + .../breakpoint/step_over_breakpoint/Makefile | 9 + .../step_over_breakpoint/TestStepOverBreakpoint.py | 119 +++++++ .../breakpoint/step_over_breakpoint/main.cpp | 12 + 108 files changed, 5369 insertions(+) create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestAddressBreakpoints.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/a.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/b.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/side_effect.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/TestBreakpointHitCount.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/TestBreakpointLanguage.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/a.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/b.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/foo.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/TestBreakpointsWithNoTargets.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/TestBreakpointInGlobalConstructor.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.h create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/TestInlinedBreakpoints.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/int.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/main.m create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/Makefile new file mode 100644 index 0000000..6067ee45 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestAddressBreakpoints.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestAddressBreakpoints.py new file mode 100644 index 0000000..f4d5411 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestAddressBreakpoints.py @@ -0,0 +1,96 @@ +""" +Test address breakpoints set with shared library of SBAddress work correctly. +""" + +from __future__ import print_function + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class AddressBreakpointTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_address_breakpoints(self): + """Test address breakpoints set with shared library of SBAddress work correctly.""" + self.build() + self.address_breakpoints() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def address_breakpoints(self): + """Test address breakpoints set with shared library of SBAddress work correctly.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateBySourceRegex( + "Set a breakpoint here", lldb.SBFileSpec("main.c")) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() >= 1, + VALID_BREAKPOINT) + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Next get the address from the location, and create an address breakpoint using + # that address: + + address = location.GetAddress() + target.BreakpointDelete(breakpoint.GetID()) + + breakpoint = target.BreakpointCreateBySBAddress(address) + + # Disable ASLR. This will allow us to actually test (on platforms that support this flag) + # that the breakpoint was able to track the module. + + launch_info = lldb.SBLaunchInfo(None) + flags = launch_info.GetLaunchFlags() + flags &= ~lldb.eLaunchFlagDisableASLR + launch_info.SetLaunchFlags(flags) + + error = lldb.SBError() + + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + # Did we hit our breakpoint? + from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint + threads = get_threads_stopped_at_breakpoint(process, breakpoint) + self.assertTrue( + len(threads) == 1, + "There should be a thread stopped at our breakpoint") + + # The hit count for the breakpoint should be 1. + self.assertTrue(breakpoint.GetHitCount() == 1) + + process.Kill() + + # Now re-launch and see that we hit the breakpoint again: + launch_info.Clear() + launch_info.SetLaunchFlags(flags) + + process = target.Launch(launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + thread = get_threads_stopped_at_breakpoint(process, breakpoint) + self.assertTrue( + len(threads) == 1, + "There should be a thread stopped at our breakpoint") + + # The hit count for the breakpoint should now be 2. + self.assertTrue(breakpoint.GetHitCount() == 2) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py new file mode 100644 index 0000000..2dcce03 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py @@ -0,0 +1,47 @@ +""" +Test that breakpoints set on a bad address say they are bad. +""" + +from __future__ import print_function + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class BadAddressBreakpointTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_bad_address_breakpoints(self): + """Test that breakpoints set on a bad address say they are bad.""" + self.build() + self.address_breakpoints() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def address_breakpoints(self): + """Test that breakpoints set on a bad address say they are bad.""" + target, process, thread, bkpt = \ + lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", + lldb.SBFileSpec("main.c")) + + # Now see if we can read from 0. If I can't do that, I don't + # have a good way to know what an illegal address is... + error = lldb.SBError() + + ptr = process.ReadPointerFromMemory(0x0, error) + + if not error.Success(): + bkpt = target.BreakpointCreateByAddress(0x0) + for bp_loc in bkpt: + self.assertTrue(bp_loc.IsResolved() == False) + else: + self.fail( + "Could not find an illegal address at which to set a bad breakpoint.") diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/main.c new file mode 100644 index 0000000..6b77929 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/main.c @@ -0,0 +1,8 @@ +#include + +int +main() +{ + printf ("Set a breakpoint here.\n"); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/Makefile new file mode 100644 index 0000000..6067ee45 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py new file mode 100644 index 0000000..411e0cf --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/TestBreakpointAutoContinue.py @@ -0,0 +1,101 @@ +""" +Test that the breakpoint auto-continue flag works correctly. +""" + +from __future__ import print_function + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class BreakpointAutoContinue(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_breakpoint_auto_continue(self): + """Make sure the auto continue continues with no other complications""" + self.build() + self.simple_auto_continue() + + def test_auto_continue_with_command(self): + """Add a command, make sure the command gets run""" + self.build() + self.auto_continue_with_command() + + def test_auto_continue_on_location(self): + """Set auto-continue on a location and make sure only that location continues""" + self.build() + self.auto_continue_location() + + def make_target_and_bkpt(self, additional_options=None, num_expected_loc=1, + pattern="Set a breakpoint here"): + exe = self.getBuildArtifact("a.out") + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target.IsValid(), "Target is not valid") + + extra_options_txt = "--auto-continue 1 " + if additional_options: + extra_options_txt += additional_options + bpno = lldbutil.run_break_set_by_source_regexp(self, pattern, + extra_options = extra_options_txt, + num_expected_locations = num_expected_loc) + return bpno + + def launch_it (self, expected_state): + error = lldb.SBError() + launch_info = lldb.SBLaunchInfo(None) + launch_info.SetWorkingDirectory(self.get_process_working_directory()) + + process = self.target.Launch(launch_info, error) + self.assertTrue(error.Success(), "Launch failed.") + + state = process.GetState() + self.assertEqual(state, expected_state, "Didn't get expected state") + + return process + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def simple_auto_continue(self): + bpno = self.make_target_and_bkpt() + process = self.launch_it(lldb.eStateExited) + + bkpt = self.target.FindBreakpointByID(bpno) + self.assertEqual(bkpt.GetHitCount(), 2, "Should have run through the breakpoint twice") + + def auto_continue_with_command(self): + bpno = self.make_target_and_bkpt("-N BKPT -C 'break modify --auto-continue 0 BKPT'") + process = self.launch_it(lldb.eStateStopped) + state = process.GetState() + self.assertEqual(state, lldb.eStateStopped, "Process should be stopped") + bkpt = self.target.FindBreakpointByID(bpno) + threads = lldbutil.get_threads_stopped_at_breakpoint(process, bkpt) + self.assertEqual(len(threads), 1, "There was a thread stopped at our breakpoint") + self.assertEqual(bkpt.GetHitCount(), 2, "Should have hit the breakpoint twice") + + def auto_continue_location(self): + bpno = self.make_target_and_bkpt(pattern="Set a[^ ]* breakpoint here", num_expected_loc=2) + bkpt = self.target.FindBreakpointByID(bpno) + bkpt.SetAutoContinue(False) + + loc = lldb.SBBreakpointLocation() + for i in range(0,2): + func_name = bkpt.location[i].GetAddress().function.name + if func_name == "main": + loc = bkpt.location[i] + + self.assertTrue(loc.IsValid(), "Didn't find a location in main") + loc.SetAutoContinue(True) + + process = self.launch_it(lldb.eStateStopped) + + threads = lldbutil.get_threads_stopped_at_breakpoint(process, bkpt) + self.assertEqual(len(threads), 1, "Didn't get one thread stopped at our breakpoint") + func_name = threads[0].frame[0].function.name + self.assertEqual(func_name, "call_me") diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/main.c new file mode 100644 index 0000000..a37f05e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/auto_continue/main.c @@ -0,0 +1,19 @@ +#include + +void +call_me() +{ + printf("Set another breakpoint here.\n"); +} + +int +main() +{ + int change_me = 0; + for (int i = 0; i < 2; i++) + { + printf ("Set a breakpoint here: %d with: %d.\n", i, change_me); + } + call_me(); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile new file mode 100644 index 0000000..6c22351 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 -gcolumn-info + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py new file mode 100644 index 0000000..6179469 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py @@ -0,0 +1,45 @@ +""" +Test setting a breakpoint by line and column. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointByLineAndColumnTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + ## Skip gcc version less 7.1 since it doesn't support -gcolumn-info + @skipIf(compiler="gcc", compiler_version=['<', '7.1']) + def testBreakpointByLineAndColumn(self): + self.build() + main_c = lldb.SBFileSpec("main.c") + _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self, + main_c, 19, 50) + self.expect("fr v did_call", substrs='1') + in_then = False + for i in range(breakpoint.GetNumLocations()): + b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry() + self.assertEqual(b_loc.GetLine(), 19) + in_then |= b_loc.GetColumn() == 50 + self.assertTrue(in_then) + + ## Skip gcc version less 7.1 since it doesn't support -gcolumn-info + @skipIf(compiler="gcc", compiler_version=['<', '7.1']) + def testBreakpointByLine(self): + self.build() + main_c = lldb.SBFileSpec("main.c") + _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self, main_c, 19) + self.expect("fr v did_call", substrs='0') + in_condition = False + for i in range(breakpoint.GetNumLocations()): + b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry() + self.assertEqual(b_loc.GetLine(), 19) + in_condition |= b_loc.GetColumn() < 30 + self.assertTrue(in_condition) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c new file mode 100644 index 0000000..f9adad3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c @@ -0,0 +1,22 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int square(int x) +{ + return x * x; +} + +int main (int argc, char const *argv[]) +{ + int did_call = 0; + + // Line 20. v Column 50. + if(square(argc+1) != 0) { did_call = 1; return square(argc); } + // ^ + return square(0); +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/Makefile new file mode 100644 index 0000000..a6376f9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c a.c b.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py new file mode 100644 index 0000000..b75a6db --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py @@ -0,0 +1,285 @@ +""" +Test lldb breakpoint command add/list/delete. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import side_effect + + +class BreakpointCommandTestCase(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_breakpoint_command_sequence(self): + """Test a sequence of breakpoint command add, list, and delete.""" + self.build() + self.breakpoint_command_sequence() + + def test_script_parameters(self): + """Test a sequence of breakpoint command add, list, and delete.""" + self.build() + self.breakpoint_command_script_parameters() + + def test_commands_on_creation(self): + self.build() + self.breakpoint_commands_on_creation() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', '// Set break point at this line.') + # disable "There is a running process, kill it and restart?" prompt + self.runCmd("settings set auto-confirm true") + self.addTearDownHook( + lambda: self.runCmd("settings clear auto-confirm")) + + def test_delete_all_breakpoints(self): + """Test that deleting all breakpoints works.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_symbol(self, "main") + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + self.runCmd("breakpoint delete") + self.runCmd("process continue") + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* exited with status = 0']) + + + def breakpoint_command_sequence(self): + """Test a sequence of breakpoint command add, list, and delete.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add three breakpoints on the same line. The first time we don't specify the file, + # since the default file is the one containing main: + lldbutil.run_break_set_by_file_and_line( + self, None, self.line, num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + # Breakpoint 4 - set at the same location as breakpoint 1 to test + # setting breakpoint commands on two breakpoints at a time + lldbutil.run_break_set_by_file_and_line( + self, None, self.line, num_expected_locations=1, loc_exact=True) + # Make sure relative path source breakpoints work as expected. We test + # with partial paths with and without "./" prefixes. + lldbutil.run_break_set_by_file_and_line( + self, "./main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "./breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "breakpoint/breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "./breakpoint/breakpoint_command/main.c", self.line, + num_expected_locations=1, loc_exact=True) + # Test relative breakpoints with incorrect paths and make sure we get + # no breakpoint locations + lldbutil.run_break_set_by_file_and_line( + self, "invalid/main.c", self.line, + num_expected_locations=0, loc_exact=True) + lldbutil.run_break_set_by_file_and_line( + self, "./invalid/main.c", self.line, + num_expected_locations=0, loc_exact=True) + # Now add callbacks for the breakpoints just created. + self.runCmd( + "breakpoint command add -s command -o 'frame variable --show-types --scope' 1 4") + self.runCmd( + "breakpoint command add -s python -o 'import side_effect; side_effect.one_liner = \"one liner was here\"' 2") + self.runCmd( + "breakpoint command add --python-function bktptcmd.function 3") + + # Check that the breakpoint commands are correctly set. + + # The breakpoint list now only contains breakpoint 1. + self.expect( + "breakpoint list", "Breakpoints 1 & 2 created", substrs=[ + "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" % + self.line], patterns=[ + "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" % + self.line]) + + self.expect( + "breakpoint list -f", + "Breakpoints 1 & 2 created", + substrs=[ + "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" % + self.line], + patterns=[ + "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" % + self.line, + "1.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % + self.line, + "2.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" % + self.line]) + + self.expect("breakpoint command list 1", "Breakpoint 1 command ok", + substrs=["Breakpoint commands:", + "frame variable --show-types --scope"]) + self.expect("breakpoint command list 2", "Breakpoint 2 command ok", + substrs=["Breakpoint commands (Python):", + "import side_effect", + "side_effect.one_liner"]) + self.expect("breakpoint command list 3", "Breakpoint 3 command ok", + substrs=["Breakpoint commands (Python):", + "bktptcmd.function(frame, bp_loc, internal_dict)"]) + + self.expect("breakpoint command list 4", "Breakpoint 4 command ok", + substrs=["Breakpoint commands:", + "frame variable --show-types --scope"]) + + self.runCmd("breakpoint delete 4") + + self.runCmd("command script import --allow-reload ./bktptcmd.py") + + # Next lets try some other breakpoint kinds. First break with a regular expression + # and then specify only one file. The first time we should get two locations, + # the second time only one: + + lldbutil.run_break_set_by_regexp( + self, r"._MyFunction", num_expected_locations=2) + + lldbutil.run_break_set_by_regexp( + self, + r"._MyFunction", + extra_options="-f a.c", + num_expected_locations=1) + + lldbutil.run_break_set_by_regexp( + self, + r"._MyFunction", + extra_options="-f a.c -f b.c", + num_expected_locations=2) + + # Now try a source regex breakpoint: + lldbutil.run_break_set_by_source_regexp( + self, + r"is about to return [12]0", + extra_options="-f a.c -f b.c", + num_expected_locations=2) + + lldbutil.run_break_set_by_source_regexp( + self, + r"is about to return [12]0", + extra_options="-f a.c", + num_expected_locations=1) + + # Reset our canary variables and run the program. + side_effect.one_liner = None + side_effect.bktptcmd = None + self.runCmd("run", RUN_SUCCEEDED) + + # Check the value of canary variables. + self.assertEquals("one liner was here", side_effect.one_liner) + self.assertEquals("function was here", side_effect.bktptcmd) + + # Finish the program. + self.runCmd("process continue") + + # Remove the breakpoint command associated with breakpoint 1. + self.runCmd("breakpoint command delete 1") + + # Remove breakpoint 2. + self.runCmd("breakpoint delete 2") + + self.expect( + "breakpoint command list 1", + startstr="Breakpoint 1 does not have an associated command.") + self.expect( + "breakpoint command list 2", + error=True, + startstr="error: '2' is not a currently valid breakpoint ID.") + + # The breakpoint list now only contains breakpoint 1. + self.expect( + "breakpoint list -f", + "Breakpoint 1 exists", + patterns=[ + "1: file = '.*main.c', line = %d, exact_match = 0, locations = 1, resolved = 1" % + self.line, + "hit count = 1"]) + + # Not breakpoint 2. + self.expect( + "breakpoint list -f", + "No more breakpoint 2", + matching=False, + substrs=[ + "2: file = 'main.c', line = %d, exact_match = 0, locations = 1, resolved = 1" % + self.line]) + + # Run the program again, with breakpoint 1 remaining. + self.runCmd("run", RUN_SUCCEEDED) + + # We should be stopped again due to breakpoint 1. + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 2. + self.expect("breakpoint list -f", BREAKPOINT_HIT_TWICE, + substrs=['resolved, hit count = 2']) + + def breakpoint_command_script_parameters(self): + """Test that the frame and breakpoint location are being properly passed to the script breakpoint command function.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint. + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + + # Now add callbacks for the breakpoints just created. + self.runCmd("breakpoint command add -s python -o 'import side_effect; side_effect.frame = str(frame); side_effect.bp_loc = str(bp_loc)' 1") + + # Reset canary variables and run. + side_effect.frame = None + side_effect.bp_loc = None + self.runCmd("run", RUN_SUCCEEDED) + + self.expect(side_effect.frame, exe=False, startstr="frame #0:") + self.expect(side_effect.bp_loc, exe=False, + patterns=["1.* where = .*main .* resolved, hit count = 1"]) + + def breakpoint_commands_on_creation(self): + """Test that setting breakpoint commands when creating the breakpoint works""" + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target.IsValid(), "Created an invalid target.") + + # Add a breakpoint. + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True, + extra_options='-C bt -C "thread list" -C continue') + + bkpt = target.FindBreakpointByID(1) + self.assertTrue(bkpt.IsValid(), "Couldn't find breakpoint 1") + com_list = lldb.SBStringList() + bkpt.GetCommandLineCommands(com_list) + self.assertEqual(com_list.GetSize(), 3, "Got the wrong number of commands") + self.assertEqual(com_list.GetStringAtIndex(0), "bt", "First bt") + self.assertEqual(com_list.GetStringAtIndex(1), "thread list", "Next thread list") + self.assertEqual(com_list.GetStringAtIndex(2), "continue", "Last continue") diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py new file mode 100644 index 0000000..962728a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py @@ -0,0 +1,99 @@ +""" +Test that you can set breakpoint commands successfully with the Python API's: +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import side_effect + + +class PythonBreakpointCommandSettingTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @add_test_categories(['pyapi']) + def test_step_out_python(self): + """Test stepping out using avoid-no-debug with dsyms.""" + self.build() + self.do_set_python_command_from_python() + + def setUp(self): + TestBase.setUp(self) + self.main_source = "main.c" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + def do_set_python_command_from_python(self): + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + body_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set break point at this line.", self.main_source_spec) + self.assertTrue(body_bkpt, VALID_BREAKPOINT) + + func_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set break point at this line.", self.main_source_spec) + self.assertTrue(func_bkpt, VALID_BREAKPOINT) + + # Also test that setting a source regex breakpoint with an empty file + # spec list sets it on all files: + no_files_bkpt = self.target.BreakpointCreateBySourceRegex( + "Set a breakpoint here", lldb.SBFileSpecList(), lldb.SBFileSpecList()) + self.assertTrue(no_files_bkpt, VALID_BREAKPOINT) + num_locations = no_files_bkpt.GetNumLocations() + self.assertTrue( + num_locations >= 2, + "Got at least two breakpoint locations") + got_one_in_A = False + got_one_in_B = False + for idx in range(0, num_locations): + comp_unit = no_files_bkpt.GetLocationAtIndex(idx).GetAddress().GetSymbolContext( + lldb.eSymbolContextCompUnit).GetCompileUnit().GetFileSpec() + print("Got comp unit: ", comp_unit.GetFilename()) + if comp_unit.GetFilename() == "a.c": + got_one_in_A = True + elif comp_unit.GetFilename() == "b.c": + got_one_in_B = True + + self.assertTrue(got_one_in_A, "Failed to match the pattern in A") + self.assertTrue(got_one_in_B, "Failed to match the pattern in B") + self.target.BreakpointDelete(no_files_bkpt.GetID()) + + error = lldb.SBError() + error = body_bkpt.SetScriptCallbackBody( + "import side_effect; side_effect.callback = 'callback was here'") + self.assertTrue( + error.Success(), + "Failed to set the script callback body: %s." % + (error.GetCString())) + + self.dbg.HandleCommand( + "command script import --allow-reload ./bktptcmd.py") + func_bkpt.SetScriptCallbackFunction("bktptcmd.function") + + # Clear out canary variables + side_effect.bktptcmd = None + side_effect.callback = None + + # Now launch the process, and do not stop at entry point. + self.process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + + self.assertTrue(self.process, PROCESS_IS_VALID) + + # Now finish, and make sure the return value is correct. + threads = lldbutil.get_threads_stopped_at_breakpoint( + self.process, body_bkpt) + self.assertTrue(len(threads) == 1, "Stopped at inner breakpoint.") + self.thread = threads[0] + + self.assertEquals("callback was here", side_effect.callback) + self.assertEquals("function was here", side_effect.bktptcmd) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py new file mode 100644 index 0000000..8774d37 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py @@ -0,0 +1,71 @@ +""" +Test _regexp-break command which uses regular expression matching to dispatch to other built in breakpoint commands. +""" + +from __future__ import print_function + + +import os +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class RegexpBreakCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + """Test _regexp-break command.""" + self.build() + self.regexp_break_command() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.source = 'main.c' + self.line = line_number( + self.source, '// Set break point at this line.') + + def regexp_break_command(self): + """Test the super consie "b" command, which is analias for _regexp-break.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + break_results = lldbutil.run_break_set_command( + self, "b %d" % + self.line) + lldbutil.check_breakpoint_result( + self, + break_results, + file_name='main.c', + line_number=self.line, + num_locations=1) + + break_results = lldbutil.run_break_set_command( + self, "b %s:%d" % (self.source, self.line)) + lldbutil.check_breakpoint_result( + self, + break_results, + file_name='main.c', + line_number=self.line, + num_locations=1) + + # Check breakpoint with full file path. + full_path = os.path.join(self.getSourceDir(), self.source) + break_results = lldbutil.run_break_set_command( + self, "b %s:%d" % (full_path, self.line)) + lldbutil.check_breakpoint_result( + self, + break_results, + file_name='main.c', + line_number=self.line, + num_locations=1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/a.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/a.c new file mode 100644 index 0000000..870e4a6 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/a.c @@ -0,0 +1,9 @@ +#include + +int +a_MyFunction () +{ + // Set a breakpoint here. + printf ("a is about to return 10.\n"); + return 10; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/b.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/b.c new file mode 100644 index 0000000..02b78e7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/b.c @@ -0,0 +1,9 @@ +#include + +int +b_MyFunction () +{ + // Set a breakpoint here. + printf ("b is about to return 20.\n"); + return 20; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py new file mode 100644 index 0000000..ac0f753 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py @@ -0,0 +1,5 @@ +from __future__ import print_function +import side_effect + +def function(frame, bp_loc, dict): + side_effect.bktptcmd = "function was here" diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c new file mode 100644 index 0000000..8bebb94 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c @@ -0,0 +1,16 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int main (int argc, char const *argv[]) +{ + // Add a body to the function, so we can set more than one + // breakpoint in it. + static volatile int var = 0; + var++; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/side_effect.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/side_effect.py new file mode 100644 index 0000000..ef4ab2b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/side_effect.py @@ -0,0 +1,5 @@ +""" +A dummy module for testing the execution of various breakpoint commands. A +command will modify a global variable in this module and test will check its +value. +""" diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/Makefile new file mode 100644 index 0000000..6067ee45 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py new file mode 100644 index 0000000..96ed32a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py @@ -0,0 +1,226 @@ +""" +Test breakpoint conditions with 'breakpoint modify -c id'. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointConditionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_breakpoint_condition_and_run_command(self): + """Exercise breakpoint condition with 'breakpoint modify -c id'.""" + self.build() + self.breakpoint_conditions() + + def test_breakpoint_condition_inline_and_run_command(self): + """Exercise breakpoint condition inline with 'breakpoint set'.""" + self.build() + self.breakpoint_conditions(inline=True) + + @add_test_categories(['pyapi']) + def test_breakpoint_condition_and_python_api(self): + """Use Python APIs to set breakpoint conditions.""" + self.build() + self.breakpoint_conditions_python() + + @add_test_categories(['pyapi']) + def test_breakpoint_invalid_condition_and_python_api(self): + """Use Python APIs to set breakpoint conditions.""" + self.build() + self.breakpoint_invalid_conditions_python() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.line1 = line_number( + 'main.c', '// Find the line number of function "c" here.') + self.line2 = line_number( + 'main.c', "// Find the line number of c's parent call here.") + + def breakpoint_conditions(self, inline=False): + """Exercise breakpoint condition with 'breakpoint modify -c id'.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + if inline: + # Create a breakpoint by function name 'c' and set the condition. + lldbutil.run_break_set_by_symbol( + self, + "c", + extra_options="-c 'val == 3'", + num_expected_locations=1, + sym_exact=True) + else: + # Create a breakpoint by function name 'c'. + lldbutil.run_break_set_by_symbol( + self, "c", num_expected_locations=1, sym_exact=True) + + # And set a condition on the breakpoint to stop on when 'val == 3'. + self.runCmd("breakpoint modify -c 'val == 3' 1") + + # Now run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The process should be stopped at this point. + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* stopped']) + + # 'frame variable --show-types val' should return 3 due to breakpoint condition. + self.expect( + "frame variable --show-types val", + VARIABLES_DISPLAYED_CORRECTLY, + startstr='(int) val = 3') + + # Also check the hit count, which should be 3, by design. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs=["resolved = 1", + "Condition: val == 3", + "hit count = 1"]) + + # The frame #0 should correspond to main.c:36, the executable statement + # in function name 'c'. And the parent frame should point to + # main.c:24. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT_CONDITION, + #substrs = ["stop reason = breakpoint"], + patterns=["frame #0.*main.c:%d" % self.line1, + "frame #1.*main.c:%d" % self.line2]) + + # Test that "breakpoint modify -c ''" clears the condition for the last + # created breakpoint, so that when the breakpoint hits, val == 1. + self.runCmd("process kill") + self.runCmd("breakpoint modify -c ''") + self.expect( + "breakpoint list -f", + BREAKPOINT_STATE_CORRECT, + matching=False, + substrs=["Condition:"]) + + # Now run the program again. + self.runCmd("run", RUN_SUCCEEDED) + + # The process should be stopped at this point. + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* stopped']) + + # 'frame variable --show-types val' should return 1 since it is the first breakpoint hit. + self.expect( + "frame variable --show-types val", + VARIABLES_DISPLAYED_CORRECTLY, + startstr='(int) val = 1') + + self.runCmd("process kill") + + def breakpoint_conditions_python(self): + """Use Python APIs to set breakpoint conditions.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # We didn't associate a thread index with the breakpoint, so it should + # be invalid. + self.assertTrue(breakpoint.GetThreadIndex() == lldb.UINT32_MAX, + "The thread index should be invalid") + # The thread name should be invalid, too. + self.assertTrue(breakpoint.GetThreadName() is None, + "The thread name should be invalid") + + # Let's set the thread index for this breakpoint and verify that it is, + # indeed, being set correctly. + # There's only one thread for the process. + breakpoint.SetThreadIndex(1) + self.assertTrue(breakpoint.GetThreadIndex() == 1, + "The thread index has been set correctly") + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Set the condition on the breakpoint location. + location.SetCondition('val == 3') + self.expect(location.GetCondition(), exe=False, + startstr='val == 3') + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1 and the break condition should hold. + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + var = frame0.FindValue('val', lldb.eValueTypeVariableArgument) + self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1 and + var.GetValue() == '3') + + # The hit count for the breakpoint should be 1. + self.assertTrue(breakpoint.GetHitCount() == 1) + + # Test that the condition expression didn't create a result variable: + options = lldb.SBExpressionOptions() + value = frame0.EvaluateExpression("$0", options) + self.assertTrue(value.GetError().Fail(), + "Conditions should not make result variables.") + process.Continue() + + def breakpoint_invalid_conditions_python(self): + """Use Python APIs to set breakpoint conditions.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Set the condition on the breakpoint. + breakpoint.SetCondition('no_such_variable == not_this_one_either') + self.expect(breakpoint.GetCondition(), exe=False, + startstr='no_such_variable == not_this_one_either') + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1 and the break condition should hold. + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + var = frame0.FindValue('val', lldb.eValueTypeVariableArgument) + self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1) + + # The hit count for the breakpoint should be 1. + self.assertTrue(breakpoint.GetHitCount() == 1) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/main.c new file mode 100644 index 0000000..c830b17 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint modify -c 'val == 3' breakpt-id" to break within c(int val) only +// when the value of the arg is 3. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // Find the line number of c's parent call here. + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) + printf("a(3) returns %d\n", A3); + + for (int i = 0; i < 2; ++i) + printf("Loop\n"); + + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/Makefile new file mode 100644 index 0000000..314f1cb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/TestBreakpointHitCount.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/TestBreakpointHitCount.py new file mode 100644 index 0000000..6f696be --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/TestBreakpointHitCount.py @@ -0,0 +1,134 @@ +""" +Test breakpoint hit count features. +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointHitCountTestCase(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + def test_breakpoint_location_hit_count(self): + """Use Python APIs to check breakpoint hit count.""" + self.build() + self.do_test_breakpoint_location_hit_count() + + def test_breakpoint_one_shot(self): + """Check that one-shot breakpoints trigger only once.""" + self.build() + + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + self.runCmd("tb a") + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + + frame0 = thread.GetFrameAtIndex(0) + self.assertTrue(frame0.GetFunctionName() == "a(int)" or frame0.GetFunctionName() == "int a(int)"); + + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.a_int_body_line_no = line_number( + 'main.cpp', '// Breakpoint Location 1') + self.a_float_body_line_no = line_number( + 'main.cpp', '// Breakpoint Location 2') + + def do_test_breakpoint_location_hit_count(self): + """Use Python APIs to check breakpoint hit count.""" + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create a breakpoint in main.cpp by name 'a', + # there should be two locations. + breakpoint = target.BreakpointCreateByName('a', 'a.out') + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 2, + VALID_BREAKPOINT) + + # Verify all breakpoint locations are enabled. + location1 = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location1 and + location1.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + location2 = breakpoint.GetLocationAtIndex(1) + self.assertTrue(location2 and + location2.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Verify 1st breakpoint location is hit. + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + + frame0 = thread.GetFrameAtIndex(0) + location1 = breakpoint.FindLocationByAddress(frame0.GetPC()) + self.assertTrue( + frame0.GetLineEntry().GetLine() == self.a_int_body_line_no, + "Stopped in int a(int)") + self.assertTrue(location1) + self.assertEqual(location1.GetHitCount(), 1) + self.assertEqual(breakpoint.GetHitCount(), 1) + + process.Continue() + + # Verify 2nd breakpoint location is hit. + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + + frame0 = thread.GetFrameAtIndex(0) + location2 = breakpoint.FindLocationByAddress(frame0.GetPC()) + self.assertTrue( + frame0.GetLineEntry().GetLine() == self.a_float_body_line_no, + "Stopped in float a(float)") + self.assertTrue(location2) + self.assertEqual(location2.GetHitCount(), 1) + self.assertEqual(location1.GetHitCount(), 1) + self.assertEqual(breakpoint.GetHitCount(), 2) + + process.Continue() + + # Verify 2nd breakpoint location is hit again. + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + + self.assertEqual(location2.GetHitCount(), 2) + self.assertEqual(location1.GetHitCount(), 1) + self.assertEqual(breakpoint.GetHitCount(), 3) + + process.Continue() diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/main.cpp new file mode 100644 index 0000000..9fc133f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_hit_count/main.cpp @@ -0,0 +1,26 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int a(int val) +{ + return val; // Breakpoint Location 1 +} + +float a(float val) +{ + return val; // Breakpoint Location 2 +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); + float A2 = a(2.0f); + float A3 = a(3.0f); + + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/Makefile new file mode 100644 index 0000000..f89b52a9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py new file mode 100644 index 0000000..8386ea1 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/TestBreakpointIDs.py @@ -0,0 +1,58 @@ +""" +Test lldb breakpoint ids. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class BreakpointIDTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + self.build() + + exe = self.getBuildArtifact("a.out") + self.expect("file " + exe, + patterns=["Current executable set to .*a.out"]) + + bpno = lldbutil.run_break_set_by_symbol( + self, 'product', num_expected_locations=-1, sym_exact=False) + self.assertTrue(bpno == 1, "First breakpoint number is 1.") + + bpno = lldbutil.run_break_set_by_symbol( + self, 'sum', num_expected_locations=-1, sym_exact=False) + self.assertTrue(bpno == 2, "Second breakpoint number is 2.") + + bpno = lldbutil.run_break_set_by_symbol( + self, 'junk', num_expected_locations=0, sym_exact=False) + self.assertTrue(bpno == 3, "Third breakpoint number is 3.") + + self.expect( + "breakpoint disable 1.1 - 2.2 ", + COMMAND_FAILED_AS_EXPECTED, + error=True, + startstr="error: Invalid range: Ranges that specify particular breakpoint locations must be within the same major breakpoint; you specified two different major breakpoints, 1 and 2.") + + self.expect( + "breakpoint disable 2 - 2.2", + COMMAND_FAILED_AS_EXPECTED, + error=True, + startstr="error: Invalid breakpoint id range: Either both ends of range must specify a breakpoint location, or neither can specify a breakpoint location.") + + self.expect( + "breakpoint disable 2.1 - 2", + COMMAND_FAILED_AS_EXPECTED, + error=True, + startstr="error: Invalid breakpoint id range: Either both ends of range must specify a breakpoint location, or neither can specify a breakpoint location.") + + self.expect("breakpoint disable 2.1 - 2.2", + startstr="2 breakpoints disabled.") + + self.expect("breakpoint enable 2.*", + patterns=[".* breakpoints enabled."]) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/main.cpp new file mode 100644 index 0000000..3c98e147 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ids/main.cpp @@ -0,0 +1,64 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include + + +#define INLINE inline __attribute__((always_inline)) + +INLINE int +product (int x, int y) +{ + int result = x * y; + return result; +} + +INLINE int +sum (int a, int b) +{ + int result = a + b; + return result; +} + +int +strange_max (int m, int n) +{ + if (m > n) + return m; + else if (n > m) + return n; + else + return 0; +} + +int +foo (int i, int j) +{ + if (strange_max (i, j) == i) + return product (i, j); + else if (strange_max (i, j) == j) + return sum (i, j); + else + return product (sum (i, i), sum (j, j)); +} + +int +main(int argc, char const *argv[]) +{ + + int array[3]; + + array[0] = foo (1238, 78392); + array[1] = foo (379265, 23674); + array[2] = foo (872934, 234); + + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py new file mode 100644 index 0000000..12c8068 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py @@ -0,0 +1,151 @@ +""" +Test breakpoint ignore count features. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointIgnoreCountTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows # This test will hang on windows llvm.org/pr21753 + def test_with_run_command(self): + """Exercise breakpoint ignore count with 'breakpoint set -i '.""" + self.build() + self.breakpoint_ignore_count() + + @add_test_categories(['pyapi']) + @skipIfWindows # This test will hang on windows llvm.org/pr21753 + def test_with_python_api(self): + """Use Python APIs to set breakpoint ignore count.""" + self.build() + self.breakpoint_ignore_count_python() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.line1 = line_number( + 'main.c', '// Find the line number of function "c" here.') + self.line2 = line_number( + 'main.c', '// b(2) -> c(2) Find the call site of b(2).') + self.line3 = line_number( + 'main.c', '// a(3) -> c(3) Find the call site of c(3).') + self.line4 = line_number( + 'main.c', '// a(3) -> c(3) Find the call site of a(3).') + self.line5 = line_number( + 'main.c', '// Find the call site of c in main.') + + def breakpoint_ignore_count(self): + """Exercise breakpoint ignore count with 'breakpoint set -i '.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Create a breakpoint in main.c at line1. + lldbutil.run_break_set_by_file_and_line( + self, + 'main.c', + self.line1, + extra_options='-i 1', + num_expected_locations=1, + loc_exact=True) + + # Now run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The process should be stopped at this point. + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* stopped']) + + # Also check the hit count, which should be 2, due to ignore count of + # 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_THRICE, + substrs=["resolved = 1", + "hit count = 2"]) + + # The frame #0 should correspond to main.c:37, the executable statement + # in function name 'c'. And frame #2 should point to main.c:45. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT, + #substrs = ["stop reason = breakpoint"], + patterns=["frame #0.*main.c:%d" % self.line1, + "frame #2.*main.c:%d" % self.line2]) + + # continue -i 1 is the same as setting the ignore count to 1 again, try that: + # Now run the program. + self.runCmd("process continue -i 1", RUN_SUCCEEDED) + + # The process should be stopped at this point. + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* stopped']) + + # Also check the hit count, which should be 2, due to ignore count of + # 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_THRICE, + substrs=["resolved = 1", + "hit count = 4"]) + + # The frame #0 should correspond to main.c:37, the executable statement + # in function name 'c'. And frame #2 should point to main.c:45. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT, + #substrs = ["stop reason = breakpoint"], + patterns=["frame #0.*main.c:%d" % self.line1, + "frame #1.*main.c:%d" % self.line5]) + + def breakpoint_ignore_count_python(self): + """Use Python APIs to set breakpoint ignore count.""" + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Set the ignore count on the breakpoint location. + location.SetIgnoreCount(2) + self.assertTrue(location.GetIgnoreCount() == 2, + "SetIgnoreCount() works correctly") + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame#0 should be on main.c:37, frame#1 should be on main.c:25, and + # frame#2 should be on main.c:48. + # lldbutil.print_stacktraces(process) + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint") + frame0 = thread.GetFrameAtIndex(0) + frame1 = thread.GetFrameAtIndex(1) + frame2 = thread.GetFrameAtIndex(2) + self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1 and + frame1.GetLineEntry().GetLine() == self.line3 and + frame2.GetLineEntry().GetLine() == self.line4, + STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT) + + # The hit count for the breakpoint should be 3. + self.assertTrue(breakpoint.GetHitCount() == 3) + + process.Continue() diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/main.c new file mode 100644 index 0000000..b1ed446 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint modify -i breakpt-id" to set the number of times a +// breakpoint is skipped before stopping. Ignore count can also be set upon +// breakpoint creation by 'breakpoint set ... -i '. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // a(3) -> c(3) Find the call site of c(3). + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) Find the call site of b(2). + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) Find the call site of a(3). + printf("a(3) returns %d\n", A3); + + int C1 = c(5); // Find the call site of c in main. + printf ("c(5) returns %d\n", C1); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/Makefile new file mode 100644 index 0000000..77aa24a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py new file mode 100644 index 0000000..ff08715 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py @@ -0,0 +1,87 @@ +""" +Test specific to MIPS +""" + +from __future__ import print_function + +import re +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AvoidBreakpointInDelaySlotAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(archs=no_match(re.compile('mips*'))) + def test(self): + self.build() + exe = self.getBuildArtifact("a.out") + self.expect("file " + exe, + patterns=["Current executable set to .*a.out.*"]) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByName('main', 'a.out') + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + list = target.FindFunctions('foo', lldb.eFunctionNameTypeAuto) + self.assertTrue(list.GetSize() == 1) + sc = list.GetContextAtIndex(0) + self.assertTrue(sc.GetSymbol().GetName() == "foo") + function = sc.GetFunction() + self.assertTrue(function) + self.function(function, target) + + def function(self, function, target): + """Iterate over instructions in function and place a breakpoint on delay slot instruction""" + # Get the list of all instructions in the function + insts = function.GetInstructions(target) + print(insts) + i = 0 + for inst in insts: + if (inst.HasDelaySlot()): + # Remember the address of branch instruction. + branchinstaddress = inst.GetAddress().GetLoadAddress(target) + + # Get next instruction i.e delay slot instruction. + delayinst = insts.GetInstructionAtIndex(i + 1) + delayinstaddr = delayinst.GetAddress().GetLoadAddress(target) + + # Set breakpoint on delay slot instruction + breakpoint = target.BreakpointCreateByAddress(delayinstaddr) + + # Verify the breakpoint. + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + # Get the location from breakpoint + location = breakpoint.GetLocationAtIndex(0) + + # Get the address where breakpoint is actually set. + bpaddr = location.GetLoadAddress() + + # Breakpoint address should be adjusted to the address of + # branch instruction. + self.assertTrue(branchinstaddress == bpaddr) + i += 1 + else: + i += 1 + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/main.c new file mode 100644 index 0000000..bc3ecee --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/main.c @@ -0,0 +1,21 @@ +#include + +foo (int a, int b) +{ + int c; + if (a<=b) + c=b-a; + else + c=b+a; + return c; +} + +int main() +{ + int a=7, b=8, c; + + c = foo(a, b); + +return 0; +} + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/Makefile new file mode 100644 index 0000000..4f6b058 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := a.c +CXX_SOURCES := main.cpp b.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/TestBreakpointLanguage.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/TestBreakpointLanguage.py new file mode 100644 index 0000000..c22d22f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/TestBreakpointLanguage.py @@ -0,0 +1,133 @@ +""" +Test that the language option for breakpoints works correctly +parser. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestBreakpointLanguage(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + + def check_location_file(self, bp, loc, test_name): + bp_loc = bp.GetLocationAtIndex(loc) + addr = bp_loc.GetAddress() + comp_unit = addr.GetCompileUnit() + comp_name = comp_unit.GetFileSpec().GetFilename() + return comp_name == test_name + + def test_regex_breakpoint_language(self): + """Test that the name regex breakpoint commands obey the language filter.""" + + self.build() + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + # Don't read in dependencies so we don't come across false matches that + # add unwanted breakpoint hits. + self.target = self.dbg.CreateTarget(exe, None, None, False, error) + self.assertTrue(self.target, VALID_TARGET) + + cpp_bp = self.target.BreakpointCreateByRegex( + "func_from", + lldb.eLanguageTypeC_plus_plus, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + cpp_bp.GetNumLocations() == 1, + "Only one C++ symbol matches") + self.assertTrue(self.check_location_file(cpp_bp, 0, "b.cpp")) + + c_bp = self.target.BreakpointCreateByRegex( + "func_from", + lldb.eLanguageTypeC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + c_bp.GetNumLocations() == 1, + "Only one C symbol matches") + self.assertTrue(self.check_location_file(c_bp, 0, "a.c")) + + objc_bp = self.target.BreakpointCreateByRegex( + "func_from", + lldb.eLanguageTypeObjC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + objc_bp.GetNumLocations() == 0, + "No ObjC symbol matches") + + def test_by_name_breakpoint_language(self): + """Test that the name regex breakpoint commands obey the language filter.""" + + self.build() + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + # Don't read in dependencies so we don't come across false matches that + # add unwanted breakpoint hits. + self.target = self.dbg.CreateTarget(exe, None, None, False, error) + self.assertTrue(self.target, VALID_TARGET) + + cpp_bp = self.target.BreakpointCreateByName( + "func_from_cpp", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeC_plus_plus, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + cpp_bp.GetNumLocations() == 1, + "Only one C++ symbol matches") + self.assertTrue(self.check_location_file(cpp_bp, 0, "b.cpp")) + + no_cpp_bp = self.target.BreakpointCreateByName( + "func_from_c", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeC_plus_plus, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + no_cpp_bp.GetNumLocations() == 0, + "And the C one doesn't match") + + c_bp = self.target.BreakpointCreateByName( + "func_from_c", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + c_bp.GetNumLocations() == 1, + "Only one C symbol matches") + self.assertTrue(self.check_location_file(c_bp, 0, "a.c")) + + no_c_bp = self.target.BreakpointCreateByName( + "func_from_cpp", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + no_c_bp.GetNumLocations() == 0, + "And the C++ one doesn't match") + + objc_bp = self.target.BreakpointCreateByName( + "func_from_cpp", + lldb.eFunctionNameTypeAuto, + lldb.eLanguageTypeObjC, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + objc_bp.GetNumLocations() == 0, + "No ObjC symbol matches") diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/a.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/a.c new file mode 100644 index 0000000..b90e2bd --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/a.c @@ -0,0 +1,5 @@ +int +func_from_c () +{ + return 5; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/b.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/b.cpp new file mode 100644 index 0000000..8937344 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/b.cpp @@ -0,0 +1,5 @@ +int +func_from_cpp() +{ + return 10; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/main.cpp new file mode 100644 index 0000000..b7d00a6 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_language/main.cpp @@ -0,0 +1,11 @@ +#include +extern "C" int func_from_c(); +extern int func_from_cpp(); + +int +main() +{ + func_from_c(); + func_from_cpp(); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/Makefile new file mode 100644 index 0000000..7934cd5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +ifneq (,$(findstring icc,$(CC))) + CFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py new file mode 100644 index 0000000..052b125 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py @@ -0,0 +1,198 @@ +""" +Test breakpoint commands for a breakpoint ID with multiple locations. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointLocationsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_enable(self): + """Test breakpoint enable/disable for a breakpoint ID with multiple locations.""" + self.build() + self.breakpoint_locations_test() + + def test_shadowed_cond_options(self): + """Test that options set on the breakpoint and location behave correctly.""" + self.build() + self.shadowed_bkpt_cond_test() + + + def test_shadowed_command_options(self): + """Test that options set on the breakpoint and location behave correctly.""" + self.build() + self.shadowed_bkpt_command_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', '// Set break point at this line.') + + def set_breakpoint (self): + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, "Target %s is not valid"%(exe)) + + # This should create a breakpoint with 3 locations. + + bkpt = target.BreakpointCreateByLocation("main.c", self.line) + + # The breakpoint list should show 3 locations. + self.assertEqual(bkpt.GetNumLocations(), 3, "Wrong number of locations") + + self.expect( + "breakpoint list -f", + "Breakpoint locations shown correctly", + substrs=[ + "1: file = 'main.c', line = %d, exact_match = 0, locations = 3" % + self.line], + patterns=[ + "where = a.out`func_inlined .+unresolved, hit count = 0", + "where = a.out`main .+\[inlined\].+unresolved, hit count = 0"]) + + return bkpt + + def shadowed_bkpt_cond_test(self): + """Test that options set on the breakpoint and location behave correctly.""" + # Breakpoint option propagation from bkpt to loc used to be done the first time + # a breakpoint location option was specifically set. After that the other options + # on that location would stop tracking the breakpoint. That got fixed, and this test + # makes sure only the option touched is affected. + + bkpt = self.set_breakpoint() + bkpt_cond = "1 == 0" + bkpt.SetCondition(bkpt_cond) + self.assertEqual(bkpt.GetCondition(), bkpt_cond,"Successfully set condition") + self.assertTrue(bkpt.location[0].GetCondition() == bkpt.GetCondition(), "Conditions are the same") + + # Now set a condition on the locations, make sure that this doesn't effect the bkpt: + bkpt_loc_1_cond = "1 == 1" + bkpt.location[0].SetCondition(bkpt_loc_1_cond) + self.assertEqual(bkpt.location[0].GetCondition(), bkpt_loc_1_cond, "Successfully changed location condition") + self.assertNotEqual(bkpt.GetCondition(), bkpt_loc_1_cond, "Changed location changed Breakpoint condition") + self.assertEqual(bkpt.location[1].GetCondition(), bkpt_cond, "Changed another location's condition") + + # Now make sure that setting one options doesn't fix the value of another: + bkpt.SetIgnoreCount(10) + self.assertEqual(bkpt.GetIgnoreCount(), 10, "Set the ignore count successfully") + self.assertEqual(bkpt.location[0].GetIgnoreCount(), 10, "Location doesn't track top-level bkpt.") + + # Now make sure resetting the condition to "" resets the tracking: + bkpt.location[0].SetCondition("") + bkpt_new_cond = "1 == 3" + bkpt.SetCondition(bkpt_new_cond) + self.assertEqual(bkpt.location[0].GetCondition(), bkpt_new_cond, "Didn't go back to tracking condition") + + def shadowed_bkpt_command_test(self): + """Test that options set on the breakpoint and location behave correctly.""" + # Breakpoint option propagation from bkpt to loc used to be done the first time + # a breakpoint location option was specifically set. After that the other options + # on that location would stop tracking the breakpoint. That got fixed, and this test + # makes sure only the option touched is affected. + + bkpt = self.set_breakpoint() + commands = ["AAAAAA", "BBBBBB", "CCCCCC"] + str_list = lldb.SBStringList() + str_list.AppendList(commands, len(commands)) + + bkpt.SetCommandLineCommands(str_list) + cmd_list = lldb.SBStringList() + bkpt.GetCommandLineCommands(cmd_list) + list_size = str_list.GetSize() + self.assertEqual(cmd_list.GetSize() , list_size, "Added the right number of commands") + for i in range(0,list_size): + self.assertEqual(str_list.GetStringAtIndex(i), cmd_list.GetStringAtIndex(i), "Mismatched commands.") + + commands = ["DDDDDD", "EEEEEE", "FFFFFF", "GGGGGG"] + loc_list = lldb.SBStringList() + loc_list.AppendList(commands, len(commands)) + bkpt.location[1].SetCommandLineCommands(loc_list) + loc_cmd_list = lldb.SBStringList() + bkpt.location[1].GetCommandLineCommands(loc_cmd_list) + + loc_list_size = loc_list.GetSize() + + # Check that the location has the right commands: + self.assertEqual(loc_cmd_list.GetSize() , loc_list_size, "Added the right number of commands to location") + for i in range(0,loc_list_size): + self.assertEqual(loc_list.GetStringAtIndex(i), loc_cmd_list.GetStringAtIndex(i), "Mismatched commands.") + + # Check that we didn't mess up the breakpoint level commands: + self.assertEqual(cmd_list.GetSize() , list_size, "Added the right number of commands") + for i in range(0,list_size): + self.assertEqual(str_list.GetStringAtIndex(i), cmd_list.GetStringAtIndex(i), "Mismatched commands.") + + # And check we didn't mess up another location: + untouched_loc_cmds = lldb.SBStringList() + bkpt.location[0].GetCommandLineCommands(untouched_loc_cmds) + self.assertEqual(untouched_loc_cmds.GetSize() , 0, "Changed the wrong location") + + def breakpoint_locations_test(self): + """Test breakpoint enable/disable for a breakpoint ID with multiple locations.""" + self.set_breakpoint() + + # The 'breakpoint disable 3.*' command should fail gracefully. + self.expect("breakpoint disable 3.*", + "Disabling an invalid breakpoint should fail gracefully", + error=True, + startstr="error: '3' is not a valid breakpoint ID.") + + # The 'breakpoint disable 1.*' command should disable all 3 locations. + self.expect( + "breakpoint disable 1.*", + "All 3 breakpoint locatons disabled correctly", + startstr="3 breakpoints disabled.") + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # We should not stopped on any breakpoint at all. + self.expect("process status", "No stopping on any disabled breakpoint", + patterns=["^Process [0-9]+ exited with status = 0"]) + + # The 'breakpoint enable 1.*' command should enable all 3 breakpoints. + self.expect( + "breakpoint enable 1.*", + "All 3 breakpoint locatons enabled correctly", + startstr="3 breakpoints enabled.") + + # The 'breakpoint disable 1.1' command should disable 1 location. + self.expect( + "breakpoint disable 1.1", + "1 breakpoint locatons disabled correctly", + startstr="1 breakpoints disabled.") + + # Run the program again. We should stop on the two breakpoint + # locations. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Continue the program, there should be another stop. + self.runCmd("process continue") + + # Stopped again. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # At this point, 1.1 has a hit count of 0 and the other a hit count of + # 1". + self.expect( + "breakpoint list -f", + "The breakpoints should report correct hit counts", + patterns=[ + "1\.1: .+ unresolved, hit count = 0 +Options: disabled", + "1\.2: .+ resolved, hit count = 1", + "1\.3: .+ resolved, hit count = 1"]) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/main.c new file mode 100644 index 0000000..7ec3ded --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/main.c @@ -0,0 +1,43 @@ +#include + +#define INLINE inline __attribute__((always_inline)) + +int +func_not_inlined (void) +{ + printf ("Called func_not_inlined.\n"); + return 0; +} + +INLINE int +func_inlined (void) +{ + static int func_inline_call_count = 0; + printf ("Called func_inlined.\n"); + ++func_inline_call_count; + printf ("Returning func_inlined call count: %d.\n", func_inline_call_count); + return func_inline_call_count; // Set break point at this line. +} + +extern int func_inlined (void); + +int +main (int argc, char **argv) +{ + printf ("Starting...\n"); + + int (*func_ptr) (void); + func_ptr = func_inlined; + + int a = func_inlined(); + printf("First call to func_inlined() returns: %d.\n", a); + + func_not_inlined (); + + func_ptr (); + + printf("Last call to func_inlined() returns: %d.\n", func_inlined ()); + return 0; +} + + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py new file mode 100644 index 0000000..4a5ed87 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py @@ -0,0 +1,365 @@ +""" +Test breakpoint names. +""" + +from __future__ import print_function + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointNames(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @add_test_categories(['pyapi']) + def test_setting_names(self): + """Use Python APIs to test that we can set breakpoint names.""" + self.build() + self.setup_target() + self.do_check_names() + + def test_illegal_names(self): + """Use Python APIs to test that we don't allow illegal names.""" + self.build() + self.setup_target() + self.do_check_illegal_names() + + def test_using_names(self): + """Use Python APIs to test that operations on names works correctly.""" + self.build() + self.setup_target() + self.do_check_using_names() + + def test_configuring_names(self): + """Use Python APIs to test that configuring options on breakpoint names works correctly.""" + self.build() + self.make_a_dummy_name() + self.setup_target() + self.do_check_configuring_names() + + def test_configuring_permissions_sb(self): + """Use Python APIs to test that configuring permissions on names works correctly.""" + self.build() + self.setup_target() + self.do_check_configuring_permissions_sb() + + def test_configuring_permissions_cli(self): + """Use Python APIs to test that configuring permissions on names works correctly.""" + self.build() + self.setup_target() + self.do_check_configuring_permissions_cli() + + def setup_target(self): + exe = self.getBuildArtifact("a.out") + + # Create a targets we are making breakpoint in and copying to: + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + self.main_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "main.c")) + + def check_name_in_target(self, bkpt_name): + name_list = lldb.SBStringList() + self.target.GetBreakpointNames(name_list) + found_it = False + for name in name_list: + if name == bkpt_name: + found_it = True + break + self.assertTrue(found_it, "Didn't find the name %s in the target's name list:"%(bkpt_name)) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + # These are the settings we're going to be putting into names & breakpoints: + self.bp_name_string = "ABreakpoint" + self.is_one_shot = True + self.ignore_count = 1000 + self.condition = "1 == 2" + self.auto_continue = True + self.tid = 0xaaaa + self.tidx = 10 + self.thread_name = "Fooey" + self.queue_name = "Blooey" + self.cmd_list = lldb.SBStringList() + self.cmd_list.AppendString("frame var") + self.cmd_list.AppendString("bt") + self.help_string = "I do something interesting" + + + def do_check_names(self): + """Use Python APIs to check that we can set & retrieve breakpoint names""" + bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + bkpt_name = "ABreakpoint" + other_bkpt_name = "_AnotherBreakpoint" + + # Add a name and make sure we match it: + success = bkpt.AddName(bkpt_name) + self.assertTrue(success, "We couldn't add a legal name to a breakpoint.") + + matches = bkpt.MatchesName(bkpt_name) + self.assertTrue(matches, "We didn't match the name we just set") + + # Make sure we don't match irrelevant names: + matches = bkpt.MatchesName("NotABreakpoint") + self.assertTrue(not matches, "We matched a name we didn't set.") + + # Make sure the name is also in the target: + self.check_name_in_target(bkpt_name) + + # Add another name, make sure that works too: + bkpt.AddName(other_bkpt_name) + + matches = bkpt.MatchesName(bkpt_name) + self.assertTrue(matches, "Adding a name means we didn't match the name we just set") + self.check_name_in_target(other_bkpt_name) + + # Remove the name and make sure we no longer match it: + bkpt.RemoveName(bkpt_name) + matches = bkpt.MatchesName(bkpt_name) + self.assertTrue(not matches,"We still match a name after removing it.") + + # Make sure the name list has the remaining name: + name_list = lldb.SBStringList() + bkpt.GetNames(name_list) + num_names = name_list.GetSize() + self.assertTrue(num_names == 1, "Name list has %d items, expected 1."%(num_names)) + + name = name_list.GetStringAtIndex(0) + self.assertTrue(name == other_bkpt_name, "Remaining name was: %s expected %s."%(name, other_bkpt_name)) + + def do_check_illegal_names(self): + """Use Python APIs to check that we reject illegal names.""" + bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + bad_names = ["-CantStartWithADash", + "1CantStartWithANumber", + "^CantStartWithNonAlpha", + "CantHave-ADash", + "Cant Have Spaces"] + for bad_name in bad_names: + success = bkpt.AddName(bad_name) + self.assertTrue(not success,"We allowed an illegal name: %s"%(bad_name)) + bp_name = lldb.SBBreakpointName(self.target, bad_name) + self.assertFalse(bp_name.IsValid(), "We made a breakpoint name with an illegal name: %s"%(bad_name)); + + retval =lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand("break set -n whatever -N '%s'"%(bad_name), retval) + self.assertTrue(not retval.Succeeded(), "break set succeeded with: illegal name: %s"%(bad_name)) + + def do_check_using_names(self): + """Use Python APIs to check names work in place of breakpoint ID's.""" + + bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + bkpt_name = "ABreakpoint" + other_bkpt_name= "_AnotherBreakpoint" + + # Add a name and make sure we match it: + success = bkpt.AddName(bkpt_name) + self.assertTrue(success, "We couldn't add a legal name to a breakpoint.") + + bkpts = lldb.SBBreakpointList(self.target) + self.target.FindBreakpointsByName(bkpt_name, bkpts) + + self.assertTrue(bkpts.GetSize() == 1, "One breakpoint matched.") + found_bkpt = bkpts.GetBreakpointAtIndex(0) + self.assertTrue(bkpt.GetID() == found_bkpt.GetID(),"The right breakpoint.") + + retval = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand("break disable %s"%(bkpt_name), retval) + self.assertTrue(retval.Succeeded(), "break disable failed with: %s."%(retval.GetError())) + self.assertTrue(not bkpt.IsEnabled(), "We didn't disable the breakpoint.") + + # Also make sure we don't apply commands to non-matching names: + self.dbg.GetCommandInterpreter().HandleCommand("break modify --one-shot 1 %s"%(other_bkpt_name), retval) + self.assertTrue(retval.Succeeded(), "break modify failed with: %s."%(retval.GetError())) + self.assertTrue(not bkpt.IsOneShot(), "We applied one-shot to the wrong breakpoint.") + + def check_option_values(self, bp_object): + self.assertEqual(bp_object.IsOneShot(), self.is_one_shot, "IsOneShot") + self.assertEqual(bp_object.GetIgnoreCount(), self.ignore_count, "IgnoreCount") + self.assertEqual(bp_object.GetCondition(), self.condition, "Condition") + self.assertEqual(bp_object.GetAutoContinue(), self.auto_continue, "AutoContinue") + self.assertEqual(bp_object.GetThreadID(), self.tid, "Thread ID") + self.assertEqual(bp_object.GetThreadIndex(), self.tidx, "Thread Index") + self.assertEqual(bp_object.GetThreadName(), self.thread_name, "Thread Name") + self.assertEqual(bp_object.GetQueueName(), self.queue_name, "Queue Name") + set_cmds = lldb.SBStringList() + bp_object.GetCommandLineCommands(set_cmds) + self.assertEqual(set_cmds.GetSize(), self.cmd_list.GetSize(), "Size of command line commands") + for idx in range(0, set_cmds.GetSize()): + self.assertEqual(self.cmd_list.GetStringAtIndex(idx), set_cmds.GetStringAtIndex(idx), "Command %d"%(idx)) + + def make_a_dummy_name(self): + "This makes a breakpoint name in the dummy target to make sure it gets copied over" + + dummy_target = self.dbg.GetDummyTarget() + self.assertTrue(dummy_target.IsValid(), "Dummy target was not valid.") + + def cleanup (): + self.dbg.GetDummyTarget().DeleteBreakpointName(self.bp_name_string) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Now find it in the dummy target, and make sure these settings took: + bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string) + # Make sure the name is right: + self.assertTrue (bp_name.GetName() == self.bp_name_string, "Wrong bp_name: %s"%(bp_name.GetName())) + bp_name.SetOneShot(self.is_one_shot) + bp_name.SetIgnoreCount(self.ignore_count) + bp_name.SetCondition(self.condition) + bp_name.SetAutoContinue(self.auto_continue) + bp_name.SetThreadID(self.tid) + bp_name.SetThreadIndex(self.tidx) + bp_name.SetThreadName(self.thread_name) + bp_name.SetQueueName(self.queue_name) + bp_name.SetCommandLineCommands(self.cmd_list) + + # Now look it up again, and make sure it got set correctly. + bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string) + self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.") + self.check_option_values(bp_name) + + def do_check_configuring_names(self): + """Use Python APIs to check that configuring breakpoint names works correctly.""" + other_bp_name_string = "AnotherBreakpointName" + cl_bp_name_string = "CLBreakpointName" + + # Now find the version copied in from the dummy target, and make sure these settings took: + bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) + self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.") + self.check_option_values(bp_name) + + # Now add this name to a breakpoint, and make sure it gets configured properly + bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + success = bkpt.AddName(self.bp_name_string) + self.assertTrue(success, "Couldn't add this name to the breakpoint") + self.check_option_values(bkpt) + + # Now make a name from this breakpoint, and make sure the new name is properly configured: + new_name = lldb.SBBreakpointName(bkpt, other_bp_name_string) + self.assertTrue(new_name.IsValid(), "Couldn't make a valid bp_name from a breakpoint.") + self.check_option_values(bkpt) + + # Now change the name's option and make sure it gets propagated to + # the breakpoint: + new_auto_continue = not self.auto_continue + bp_name.SetAutoContinue(new_auto_continue) + self.assertEqual(bp_name.GetAutoContinue(), new_auto_continue, "Couldn't change auto-continue on the name") + self.assertEqual(bkpt.GetAutoContinue(), new_auto_continue, "Option didn't propagate to the breakpoint.") + + # Now make this same breakpoint name - but from the command line + cmd_str = "breakpoint name configure %s -o %d -i %d -c '%s' -G %d -t %d -x %d -T '%s' -q '%s' -H '%s'"%(cl_bp_name_string, + self.is_one_shot, + self.ignore_count, + self.condition, + self.auto_continue, + self.tid, + self.tidx, + self.thread_name, + self.queue_name, + self.help_string) + for cmd in self.cmd_list: + cmd_str += " -C '%s'"%(cmd) + + self.runCmd(cmd_str, check=True) + # Now look up this name again and check its options: + cl_name = lldb.SBBreakpointName(self.target, cl_bp_name_string) + self.check_option_values(cl_name) + # Also check the help string: + self.assertEqual(self.help_string, cl_name.GetHelpString(), "Help string didn't match") + # Change the name and make sure that works: + new_help = "I do something even more interesting" + cl_name.SetHelpString(new_help) + self.assertEqual(new_help, cl_name.GetHelpString(), "SetHelpString didn't") + + # We should have three names now, make sure the target can list them: + name_list = lldb.SBStringList() + self.target.GetBreakpointNames(name_list) + for name_string in [self.bp_name_string, other_bp_name_string, cl_bp_name_string]: + self.assertTrue(name_string in name_list, "Didn't find %s in names"%(name_string)) + + # Delete the name from the current target. Make sure that works and deletes the + # name from the breakpoint as well: + self.target.DeleteBreakpointName(self.bp_name_string) + name_list.Clear() + self.target.GetBreakpointNames(name_list) + self.assertTrue(self.bp_name_string not in name_list, "Didn't delete %s from a real target"%(self.bp_name_string)) + # Also make sure the name got removed from breakpoints holding it: + self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.") + + # Test that deleting the name we injected into the dummy target works (there's also a + # cleanup that will do this, but that won't test the result... + dummy_target = self.dbg.GetDummyTarget() + dummy_target.DeleteBreakpointName(self.bp_name_string) + name_list.Clear() + dummy_target.GetBreakpointNames(name_list) + self.assertTrue(self.bp_name_string not in name_list, "Didn't delete %s from the dummy target"%(self.bp_name_string)) + # Also make sure the name got removed from breakpoints holding it: + self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.") + + def check_permission_results(self, bp_name): + self.assertEqual(bp_name.GetAllowDelete(), False, "Didn't set allow delete.") + protected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + protected_id = protected_bkpt.GetID() + + unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + unprotected_id = unprotected_bkpt.GetID() + + success = protected_bkpt.AddName(self.bp_name_string) + self.assertTrue(success, "Couldn't add this name to the breakpoint") + + self.target.DisableAllBreakpoints() + self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled") + self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.") + + # Try from the command line too: + unprotected_bkpt.SetEnabled(True) + result = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand("break disable", result) + self.assertTrue(result.Succeeded()) + self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled") + self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.") + + self.target.DeleteAllBreakpoints() + bkpt = self.target.FindBreakpointByID(protected_id) + self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.") + bkpt = self.target.FindBreakpointByID(unprotected_id) + self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.") + + # Remake the unprotected breakpoint and try again from the command line: + unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) + unprotected_id = unprotected_bkpt.GetID() + + self.dbg.GetCommandInterpreter().HandleCommand("break delete -f", result) + self.assertTrue(result.Succeeded()) + bkpt = self.target.FindBreakpointByID(protected_id) + self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.") + bkpt = self.target.FindBreakpointByID(unprotected_id) + self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.") + + def do_check_configuring_permissions_sb(self): + bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) + + # Make a breakpoint name with delete disallowed: + bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) + self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name for valid name.") + + bp_name.SetAllowDelete(False) + bp_name.SetAllowDisable(False) + bp_name.SetAllowList(False) + self.check_permission_results(bp_name) + + def do_check_configuring_permissions_cli(self): + # Make the name with the right options using the command line: + self.runCmd("breakpoint name configure -L 0 -D 0 -A 0 %s"%(self.bp_name_string), check=True) + # Now look up the breakpoint we made, and check that it works. + bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) + self.assertTrue(bp_name.IsValid(), "Didn't make a breakpoint name we could find.") + self.check_permission_results(bp_name) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/main.c new file mode 100644 index 0000000..b1ed446 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_names/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint modify -i breakpt-id" to set the number of times a +// breakpoint is skipped before stopping. Ignore count can also be set upon +// breakpoint creation by 'breakpoint set ... -i '. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // a(3) -> c(3) Find the call site of c(3). + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) Find the call site of b(2). + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) Find the call site of a(3). + printf("a(3) returns %d\n", A3); + + int C1 = c(5); // Find the call site of c in main. + printf ("c(5) returns %d\n", C1); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/Makefile new file mode 100644 index 0000000..457c497 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp foo.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py new file mode 100644 index 0000000..66ec116 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py @@ -0,0 +1,114 @@ +""" +Test breakpoint command for different options. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class BreakpointOptionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + """Test breakpoint command for different options.""" + self.build() + self.breakpoint_options_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// Set break point at this line.') + + def breakpoint_options_test(self): + """Test breakpoint command for different options.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint with 1 locations. + lldbutil.run_break_set_by_file_and_line( + self, + "main.cpp", + self.line, + extra_options="-K 1", + num_expected_locations=1) + lldbutil.run_break_set_by_file_and_line( + self, + "main.cpp", + self.line, + extra_options="-K 0", + num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 2."]) + + # Check the list of breakpoint. + self.expect( + "breakpoint list -f", + "Breakpoint locations shown correctly", + substrs=[ + "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.line, + "2: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % + self.line]) + + # Continue the program, there should be another stop. + self.runCmd("process continue") + + # Stopped again. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Continue the program, we should exit. + self.runCmd("process continue") + + # We should exit. + self.expect("process status", "Process exited successfully", + patterns=["^Process [0-9]+ exited with status = 0"]) + + def breakpoint_options_language_test(self): + """Test breakpoint command for language option.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint with 1 locations. + lldbutil.run_break_set_by_symbol( + self, + 'ns::func', + sym_exact=False, + extra_options="-L c++", + num_expected_locations=1) + + # This should create a breakpoint with 0 locations. + lldbutil.run_break_set_by_symbol( + self, + 'ns::func', + sym_exact=False, + extra_options="-L c", + num_expected_locations=0) + self.runCmd("settings set target.language c") + lldbutil.run_break_set_by_symbol( + self, 'ns::func', sym_exact=False, num_expected_locations=0) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Continue the program, we should exit. + self.runCmd("process continue") + + # We should exit. + self.expect("process status", "Process exited successfully", + patterns=["^Process [0-9]+ exited with status = 0"]) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/foo.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/foo.cpp new file mode 100644 index 0000000..e5d0e09 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/foo.cpp @@ -0,0 +1,12 @@ + +namespace ns { + int func(void) + { + return 0; + } +} + +extern "C" int foo(void) +{ + return ns::func(); +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/main.cpp new file mode 100644 index 0000000..b2e8f52 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_options/main.cpp @@ -0,0 +1,4 @@ +extern "C" int foo(void); +int main (int argc, char **argv) { // Set break point at this line. + return foo(); +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile new file mode 100644 index 0000000..314f1cb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py new file mode 100644 index 0000000..40a20a0 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py @@ -0,0 +1,50 @@ +""" +Test inferior restart when breakpoint is set on running target. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class BreakpointSetRestart(TestBase): + + mydir = TestBase.compute_mydir(__file__) + BREAKPOINT_TEXT = 'Set a breakpoint here' + + @skipIfNetBSD + def test_breakpoint_set_restart(self): + self.build() + + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + self.dbg.SetAsync(True) + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + event = lldb.SBEvent() + # Wait for inferior to transition to running state + while self.dbg.GetListener().WaitForEvent(2, event): + if lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateRunning: + break + + bp = target.BreakpointCreateBySourceRegex( + self.BREAKPOINT_TEXT, lldb.SBFileSpec('main.cpp')) + self.assertTrue( + bp.IsValid() and bp.GetNumLocations() == 1, + VALID_BREAKPOINT) + + while self.dbg.GetListener().WaitForEvent(2, event): + if lldb.SBProcess.GetStateFromEvent( + event) == lldb.eStateStopped and lldb.SBProcess.GetRestartedFromEvent(event): + continue + if lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateRunning: + continue + self.fail( + "Setting a breakpoint generated an unexpected event: %s" % + lldb.SBDebugger.StateAsCString( + lldb.SBProcess.GetStateFromEvent(event))) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp new file mode 100644 index 0000000..46682ec --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp @@ -0,0 +1,24 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + + +int main(int argc, char const *argv[]) +{ + static bool done = false; + while (!done) + { + std::this_thread::sleep_for(std::chrono::milliseconds{100}); + } + printf("Set a breakpoint here.\n"); + return 0; +} + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/Makefile new file mode 100644 index 0000000..2d7f20f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/Makefile @@ -0,0 +1,14 @@ +LEVEL = ../../../make + +CXX_SOURCES := relative.cpp + +EXE := CompDirSymLink + +include $(LEVEL)/Makefile.rules + +# Force relative filenames by copying it into the build directory. +relative.cpp: main.cpp + cp -f $< $@ + +clean:: + rm -rf relative.cpp diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py new file mode 100644 index 0000000..5b2c35f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py @@ -0,0 +1,79 @@ +""" +Test breakpoint command with AT_comp_dir set to symbolic link. +""" +from __future__ import print_function + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +_EXE_NAME = 'CompDirSymLink' # Must match Makefile +_SRC_FILE = 'relative.cpp' +_COMP_DIR_SYM_LINK_PROP = 'plugin.symbol-file.dwarf.comp-dir-symlink-paths' + + +class CompDirSymLinkTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number( + os.path.join(self.getSourceDir(), "main.cpp"), + '// Set break point at this line.') + + @skipIf(hostoslist=["windows"]) + def test_symlink_paths_set(self): + pwd_symlink = self.create_src_symlink() + self.doBuild(pwd_symlink) + self.runCmd( + "settings set %s %s" % + (_COMP_DIR_SYM_LINK_PROP, pwd_symlink)) + src_path = self.getBuildArtifact(_SRC_FILE) + lldbutil.run_break_set_by_file_and_line(self, src_path, self.line) + + @skipIf(hostoslist=no_match(["linux"])) + def test_symlink_paths_set_procselfcwd(self): + os.chdir(self.getBuildDir()) + pwd_symlink = '/proc/self/cwd' + self.doBuild(pwd_symlink) + self.runCmd( + "settings set %s %s" % + (_COMP_DIR_SYM_LINK_PROP, pwd_symlink)) + src_path = self.getBuildArtifact(_SRC_FILE) + # /proc/self/cwd points to a realpath form of current directory. + src_path = os.path.realpath(src_path) + lldbutil.run_break_set_by_file_and_line(self, src_path, self.line) + + @skipIf(hostoslist=["windows"]) + def test_symlink_paths_unset(self): + pwd_symlink = self.create_src_symlink() + self.doBuild(pwd_symlink) + self.runCmd('settings clear ' + _COMP_DIR_SYM_LINK_PROP) + src_path = self.getBuildArtifact(_SRC_FILE) + self.assertRaises( + AssertionError, + lldbutil.run_break_set_by_file_and_line, + self, + src_path, + self.line) + + def create_src_symlink(self): + pwd_symlink = self.getBuildArtifact('pwd_symlink') + if os.path.exists(pwd_symlink): + os.unlink(pwd_symlink) + os.symlink(self.getBuildDir(), pwd_symlink) + self.addTearDownHook(lambda: os.remove(pwd_symlink)) + return pwd_symlink + + def doBuild(self, pwd_symlink): + self.build(None, None, {'PWD': pwd_symlink}) + + exe = self.getBuildArtifact(_EXE_NAME) + self.runCmd('file ' + exe, CURRENT_EXECUTABLE_SET) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/main.cpp new file mode 100644 index 0000000..13e5e3e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/main.cpp @@ -0,0 +1,12 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int main (int argc, char const *argv[]) +{ + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile new file mode 100644 index 0000000..f89b52a9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py new file mode 100644 index 0000000..6afde15 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py @@ -0,0 +1,104 @@ +""" +Test that we handle breakpoints on consecutive instructions correctly. +""" + +from __future__ import print_function + + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ConsecutiveBreakpointsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def prepare_test(self): + self.build() + + (self.target, self.process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Set breakpoint here", lldb.SBFileSpec("main.cpp")) + + # Set breakpoint to the next instruction + frame = self.thread.GetFrameAtIndex(0) + + address = frame.GetPCAddress() + instructions = self.target.ReadInstructions(address, 2) + self.assertTrue(len(instructions) == 2) + self.bkpt_address = instructions[1].GetAddress() + self.breakpoint2 = self.target.BreakpointCreateByAddress( + self.bkpt_address.GetLoadAddress(self.target)) + self.assertTrue( + self.breakpoint2 and self.breakpoint2.GetNumLocations() == 1, + VALID_BREAKPOINT) + + def finish_test(self): + # Run the process until termination + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateExited) + + @no_debug_info_test + def test_continue(self): + """Test that continue stops at the second breakpoint.""" + self.prepare_test() + + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + # We should be stopped at the second breakpoint + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint( + self.process, self.breakpoint2) + self.assertIsNotNone( + self.thread, + "Expected one thread to be stopped at breakpoint 2") + + self.finish_test() + + @no_debug_info_test + def test_single_step(self): + """Test that single step stops at the second breakpoint.""" + self.prepare_test() + + step_over = False + self.thread.StepInstruction(step_over) + + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals( + self.thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress( + self.target), self.bkpt_address.GetLoadAddress( + self.target)) + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint( + self.process, self.breakpoint2) + self.assertIsNotNone( + self.thread, + "Expected one thread to be stopped at breakpoint 2") + + self.finish_test() + + @no_debug_info_test + def test_single_step_thread_specific(self): + """Test that single step stops, even though the second breakpoint is not valid.""" + self.prepare_test() + + # Choose a thread other than the current one. A non-existing thread is + # fine. + thread_index = self.process.GetNumThreads() + 1 + self.assertFalse(self.process.GetThreadAtIndex(thread_index).IsValid()) + self.breakpoint2.SetThreadIndex(thread_index) + + step_over = False + self.thread.StepInstruction(step_over) + + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals( + self.thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress( + self.target), self.bkpt_address.GetLoadAddress( + self.target)) + self.assertEquals( + self.thread.GetStopReason(), + lldb.eStopReasonPlanComplete, + "Stop reason should be 'plan complete'") + + self.finish_test() diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp new file mode 100644 index 0000000..94d0a04 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp @@ -0,0 +1,18 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int +main(int argc, char const *argv[]) +{ + int a = 0; + int b = 1; + a = b + 1; // Set breakpoint here + b = a + 1; + return 0; +} + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/Makefile new file mode 100644 index 0000000..f89b52a9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py new file mode 100644 index 0000000..be21c6e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py @@ -0,0 +1,112 @@ +""" +Test lldb breakpoint ids. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCPPBreakpointLocations(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") + def test(self): + self.build() + self.breakpoint_id_tests() + + def verify_breakpoint_locations(self, target, bp_dict): + + name = bp_dict['name'] + names = bp_dict['loc_names'] + bp = target.BreakpointCreateByName(name) + self.assertEquals( + bp.GetNumLocations(), + len(names), + "Make sure we find the right number of breakpoint locations") + + bp_loc_names = list() + for bp_loc in bp: + bp_loc_names.append(bp_loc.GetAddress().GetFunction().GetName()) + + for name in names: + found = name in bp_loc_names + if not found: + print("Didn't find '%s' in: %s" % (name, bp_loc_names)) + self.assertTrue(found, "Make sure we find all required locations") + + def breakpoint_id_tests(self): + + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + bp_dicts = [ + {'name': 'func1', 'loc_names': ['a::c::func1()', 'b::c::func1()']}, + {'name': 'func2', 'loc_names': ['a::c::func2()', 'c::d::func2()']}, + {'name': 'func3', 'loc_names': ['a::c::func3()', 'b::c::func3()', 'c::d::func3()']}, + {'name': 'c::func1', 'loc_names': ['a::c::func1()', 'b::c::func1()']}, + {'name': 'c::func2', 'loc_names': ['a::c::func2()']}, + {'name': 'c::func3', 'loc_names': ['a::c::func3()', 'b::c::func3()']}, + {'name': 'a::c::func1', 'loc_names': ['a::c::func1()']}, + {'name': 'b::c::func1', 'loc_names': ['b::c::func1()']}, + {'name': 'c::d::func2', 'loc_names': ['c::d::func2()']}, + {'name': 'a::c::func1()', 'loc_names': ['a::c::func1()']}, + {'name': 'b::c::func1()', 'loc_names': ['b::c::func1()']}, + {'name': 'c::d::func2()', 'loc_names': ['c::d::func2()']}, + ] + + for bp_dict in bp_dicts: + self.verify_breakpoint_locations(target, bp_dict) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") + def test_destructors(self): + self.build() + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + + # Don't skip prologue, so we can check the breakpoint address more + # easily + self.runCmd("settings set target.skip-prologue false") + try: + names = ['~c', 'c::~c', 'c::~c()'] + loc_names = {'a::c::~c()', 'b::c::~c()'} + # TODO: For windows targets we should put windows mangled names + # here + symbols = [ + '_ZN1a1cD1Ev', + '_ZN1a1cD2Ev', + '_ZN1b1cD1Ev', + '_ZN1b1cD2Ev'] + + for name in names: + bp = target.BreakpointCreateByName(name) + + bp_loc_names = {bp_loc.GetAddress().GetFunction().GetName() + for bp_loc in bp} + self.assertEquals( + bp_loc_names, + loc_names, + "Breakpoint set on the correct symbol") + + bp_addresses = {bp_loc.GetLoadAddress() for bp_loc in bp} + symbol_addresses = set() + for symbol in symbols: + sc_list = target.FindSymbols(symbol, lldb.eSymbolTypeCode) + self.assertEquals( + sc_list.GetSize(), 1, "Found symbol " + symbol) + symbol = sc_list.GetContextAtIndex(0).GetSymbol() + symbol_addresses.add( + symbol.GetStartAddress().GetLoadAddress(target)) + + self.assertEquals( + symbol_addresses, + bp_addresses, + "Breakpoint set on correct address") + finally: + self.runCmd("settings clear target.skip-prologue") diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp new file mode 100644 index 0000000..4afabcb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp @@ -0,0 +1,82 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include +#include + +namespace a { + class c { + public: + c(); + ~c(); + void func1() + { + puts (__PRETTY_FUNCTION__); + } + void func2() + { + puts (__PRETTY_FUNCTION__); + } + void func3() + { + puts (__PRETTY_FUNCTION__); + } + }; + + c::c() {} + c::~c() {} +} + +namespace b { + class c { + public: + c(); + ~c(); + void func1() + { + puts (__PRETTY_FUNCTION__); + } + void func3() + { + puts (__PRETTY_FUNCTION__); + } + }; + + c::c() {} + c::~c() {} +} + +namespace c { + class d { + public: + d () {} + ~d() {} + void func2() + { + puts (__PRETTY_FUNCTION__); + } + void func3() + { + puts (__PRETTY_FUNCTION__); + } + }; +} + +int main (int argc, char const *argv[]) +{ + a::c ac; + b::c bc; + c::d cd; + ac.func1(); + ac.func2(); + ac.func3(); + bc.func1(); + bc.func3(); + cd.func2(); + cd.func3(); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/Makefile new file mode 100644 index 0000000..314f1cb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py new file mode 100644 index 0000000..e8a1b81 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py @@ -0,0 +1,52 @@ +""" +Test that you can set breakpoint and hit the C++ language exception breakpoint +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCPPExceptionBreakpoint (TestBase): + + mydir = TestBase.compute_mydir(__file__) + my_var = 10 + + @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24538") + @expectedFailureNetBSD + def test_cpp_exception_breakpoint(self): + """Test setting and hitting the C++ exception breakpoint.""" + self.build() + self.do_cpp_exception_bkpt() + + def setUp(self): + TestBase.setUp(self) + self.main_source = "main.c" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + def do_cpp_exception_bkpt(self): + exe = self.getBuildArtifact("a.out") + error = lldb.SBError() + + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + exception_bkpt = self.target.BreakpointCreateForException( + lldb.eLanguageTypeC_plus_plus, False, True) + self.assertTrue( + exception_bkpt.IsValid(), + "Created exception breakpoint.") + + process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + thread_list = lldbutil.get_threads_stopped_at_breakpoint( + process, exception_bkpt) + self.assertTrue(len(thread_list) == 1, + "One thread stopped at the exception breakpoint.") diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/main.cpp new file mode 100644 index 0000000..76cb227 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/main.cpp @@ -0,0 +1,13 @@ +#include + +void +throws_int () +{ + throw 5; +} + +int +main () +{ + throws_int(); +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py new file mode 100644 index 0000000..f8d5704 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py @@ -0,0 +1,58 @@ +""" +Test embedded breakpoints, like `asm int 3;` in x86 or or `__debugbreak` on Windows. +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class DebugBreakTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(archs=no_match(["i386", "i686", "x86_64"])) + @no_debug_info_test + def test_asm_int_3(self): + """Test that intrinsics like `__debugbreak();` and `asm {"int3"}` are treated like breakpoints.""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Run the program. + target = self.dbg.CreateTarget(exe) + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + # We've hit the first stop, so grab the frame. + self.assertEqual(process.GetState(), lldb.eStateStopped) + stop_reason = lldb.eStopReasonException if (lldbplatformutil.getPlatform( + ) == "windows" or lldbplatformutil.getPlatform() == "macosx") else lldb.eStopReasonSignal + thread = lldbutil.get_stopped_thread(process, stop_reason) + self.assertIsNotNone( + thread, "Unable to find thread stopped at the __debugbreak()") + frame = thread.GetFrameAtIndex(0) + + # We should be in funciton 'bar'. + self.assertTrue(frame.IsValid()) + function_name = frame.GetFunctionName() + self.assertTrue('bar' in function_name, + "Unexpected function name {}".format(function_name)) + + # We should be able to evaluate the parameter foo. + value = frame.EvaluateExpression('*foo') + self.assertEqual(value.GetValueAsSigned(), 42) + + # The counter should be 1 at the first stop and increase by 2 for each + # subsequent stop. + counter = 1 + while counter < 20: + value = frame.EvaluateExpression('count') + self.assertEqual(value.GetValueAsSigned(), counter) + counter += 2 + process.Continue() + + # The inferior should exit after the last iteration. + self.assertEqual(process.GetState(), lldb.eStateExited) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c new file mode 100644 index 0000000..5f93632 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/main.c @@ -0,0 +1,29 @@ +#ifdef _MSC_VER +#include +#define BREAKPOINT_INTRINSIC() __debugbreak() +#else +#define BREAKPOINT_INTRINSIC() __asm__ __volatile__ ("int3") +#endif + +int +bar(int const *foo) +{ + int count = 0, i = 0; + for (; i < 10; ++i) + { + count += 1; + BREAKPOINT_INTRINSIC(); + count += 1; + } + return *foo; +} + +int +main(int argc, char **argv) +{ + int foo = 42; + bar(&foo); + return 0; +} + + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/Makefile new file mode 100644 index 0000000..7934cd5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +ifneq (,$(findstring icc,$(CC))) + CFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/TestBreakpointsWithNoTargets.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/TestBreakpointsWithNoTargets.py new file mode 100644 index 0000000..f1c8aba --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/TestBreakpointsWithNoTargets.py @@ -0,0 +1,72 @@ +""" +Test breakpoint commands set before we have a target +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class BreakpointInDummyTarget (TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + """Test breakpoint set before we have a target. """ + self.build() + self.dummy_breakpoint_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', 'Set a breakpoint on this line.') + self.line2 = line_number('main.c', 'Set another on this line.') + + def dummy_breakpoint_test(self): + """Test breakpoint set before we have a target. """ + + # This should create a breakpoint with 3 locations. + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=0) + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line2, num_expected_locations=0) + + # This is the function to remove breakpoints from the dummy target + # to get a clean slate for the next test case. + def cleanup(): + self.runCmd('breakpoint delete -D -f', check=False) + self.runCmd('breakpoint list', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # The breakpoint list should show 3 locations. + self.expect( + "breakpoint list -f", + "Breakpoint locations shown correctly", + substrs=[ + "1: file = 'main.c', line = %d, exact_match = 0, locations = 1" % + self.line, + "2: file = 'main.c', line = %d, exact_match = 0, locations = 1" % + self.line2]) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # Stopped once. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 1."]) + + # Continue the program, there should be another stop. + self.runCmd("process continue") + + # Stopped again. + self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, + substrs=["stop reason = breakpoint 2."]) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/main.c new file mode 100644 index 0000000..e1f0323 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/dummy_target_breakpoints/main.c @@ -0,0 +1,11 @@ +#include + +int +main (int argc, char **argv) +{ + printf ("Set a breakpoint on this line.\n"); + + return 0; // Set another on this line. +} + + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/Makefile new file mode 100644 index 0000000..06ef85c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +DYLIB_NAME := foo +DYLIB_CXX_SOURCES := foo.cpp +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/TestBreakpointInGlobalConstructor.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/TestBreakpointInGlobalConstructor.py new file mode 100644 index 0000000..9ca44a9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/TestBreakpointInGlobalConstructor.py @@ -0,0 +1,47 @@ +""" +Test that we can hit breakpoints in global constructors +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestBreakpointInGlobalConstructors(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @expectedFailureNetBSD + def test(self): + self.build() + self.line_foo = line_number('foo.cpp', '// !BR_foo') + self.line_main = line_number('main.cpp', '// !BR_main') + + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + env= self.registerSharedLibrariesWithTarget(target, ["foo"]) + + bp_main = lldbutil.run_break_set_by_file_and_line( + self, 'main.cpp', self.line_main) + + bp_foo = lldbutil.run_break_set_by_file_and_line( + self, 'foo.cpp', self.line_foo, num_expected_locations=-2) + + process = target.LaunchSimple( + None, env, self.get_process_working_directory()) + + self.assertIsNotNone( + lldbutil.get_one_thread_stopped_at_breakpoint_id( + self.process(), bp_foo)) + + self.runCmd("continue") + + self.assertIsNotNone( + lldbutil.get_one_thread_stopped_at_breakpoint_id( + self.process(), bp_main)) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.cpp new file mode 100644 index 0000000..f959a29 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.cpp @@ -0,0 +1,7 @@ +#include "foo.h" + +Foo::Foo() : x(42) { + bool some_code = x == 42; // !BR_foo +} + +Foo FooObj; diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.h b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.h new file mode 100644 index 0000000..3bc63fe --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/foo.h @@ -0,0 +1,11 @@ +#ifndef FOO_H +#define FOO_H + +struct LLDB_TEST_API Foo { + Foo(); + int x; +}; + +extern LLDB_TEST_API Foo FooObj; + +#endif diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/main.cpp new file mode 100644 index 0000000..d1c8038 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/global_constructor/main.cpp @@ -0,0 +1,14 @@ +#include "foo.h" + +struct Main { + Main(); + int x; +}; + +Main::Main() : x(47) { + bool some_code = x == 47; // !BR_main +} + +Main MainObj; + +int main() { return MainObj.x + FooObj.x; } diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/Makefile new file mode 100644 index 0000000..3665ae3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../../make + +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py new file mode 100644 index 0000000..95c7966 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py @@ -0,0 +1,105 @@ +""" +Test hardware breakpoints for multiple threads. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +# Hardware breakpoints are supported only by platforms mentioned in oslist. +@skipUnlessPlatform(oslist=['linux']) +class HardwareBreakpointMultiThreadTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + # LLDB supports hardware breakpoints for arm and aarch64 architectures. + @skipIf(archs=no_match(['arm', 'aarch64'])) + def test_hw_break_set_delete_multi_thread(self): + self.build() + self.setTearDownCleanup() + self.break_multi_thread('delete') + + # LLDB supports hardware breakpoints for arm and aarch64 architectures. + @skipIf(archs=no_match(['arm', 'aarch64'])) + def test_hw_break_set_disable_multi_thread(self): + self.build() + self.setTearDownCleanup() + self.break_multi_thread('disable') + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.cpp' + # Find the line number to break inside main(). + self.first_stop = line_number( + self.source, 'Starting thread creation with hardware breakpoint set') + + def break_multi_thread(self, removal_type): + """Test that lldb hardware breakpoints work for multiple threads.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), + CURRENT_EXECUTABLE_SET) + + # Stop in main before creating any threads. + lldbutil.run_break_set_by_file_and_line( + self, None, self.first_stop, num_expected_locations=1) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # We should be stopped again due to the breakpoint. + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + # Now set a hardware breakpoint in thread function. + self.expect("breakpoint set -b hw_break_function --hardware", + substrs=[ + 'Breakpoint', + 'hw_break_function', + 'address = 0x']) + + # We should stop in hw_break_function function for 4 threads. + count = 0 + + while count < 2 : + + self.runCmd("process continue") + + # We should be stopped in hw_break_function + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=[ + 'stop reason = breakpoint', + 'hw_break_function']) + + # Continue the loop and test that we are stopped 4 times. + count += 1 + + if removal_type == 'delete': + self.runCmd("settings set auto-confirm true") + + # Now 'breakpoint delete' should just work fine without confirmation + # prompt from the command interpreter. + self.expect("breakpoint delete", + startstr="All breakpoints removed") + + # Restore the original setting of auto-confirm. + self.runCmd("settings clear auto-confirm") + + elif removal_type == 'disable': + self.expect("breakpoint disable", + startstr="All breakpoints disabled.") + + # Continue. Program should exit without stopping anywhere. + self.runCmd("process continue") + + # Process should have stopped and exited with status = 0 + self.expect("process status", PROCESS_STOPPED, + patterns=['Process .* exited with status = 0']) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp new file mode 100644 index 0000000..94a12c6 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp @@ -0,0 +1,50 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include + +#define NUM_OF_THREADS 4 + +std::mutex hw_break_mutex; + +void +hw_break_function (uint32_t thread_index) { + printf ("%s called by Thread #%u...\n", __FUNCTION__, thread_index); +} + + +void +thread_func (uint32_t thread_index) { + printf ("%s (thread index = %u) starting...\n", __FUNCTION__, thread_index); + + hw_break_mutex.lock(); + + hw_break_function(thread_index); // Call hw_break_function + + hw_break_mutex.unlock(); +} + + +int main (int argc, char const *argv[]) +{ + std::thread threads[NUM_OF_THREADS]; + + printf ("Starting thread creation with hardware breakpoint set...\n"); + + for (auto &thread : threads) + thread = std::thread{thread_func, std::distance(threads, &thread)}; + + for (auto &thread : threads) + thread.join(); + + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/Makefile new file mode 100644 index 0000000..5b73ae6 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := int.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/TestInlinedBreakpoints.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/TestInlinedBreakpoints.py new file mode 100644 index 0000000..9f184fb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/TestInlinedBreakpoints.py @@ -0,0 +1,67 @@ +""" +Test that inlined breakpoints (breakpoint set on a file/line included from +another source file) works correctly. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class InlinedBreakpointsTestCase(TestBase): + """Bug fixed: rdar://problem/8464339""" + + mydir = TestBase.compute_mydir(__file__) + + def test_with_run_command(self): + """Test 'b basic_types.cpp:176' does break (where int.cpp includes basic_type.cpp).""" + self.build() + self.inlined_breakpoints() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside basic_type.cpp. + self.line = line_number( + 'basic_type.cpp', + '// Set break point at this line.') + + def inlined_breakpoints(self): + """Test 'b basic_types.cpp:176' does break (where int.cpp includes basic_type.cpp).""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # With the inline-breakpoint-strategy, our file+line breakpoint should + # not resolve to a location. + self.runCmd('settings set target.inline-breakpoint-strategy headers') + + # Set a breakpoint and fail because it is in an inlined source + # implemenation file + lldbutil.run_break_set_by_file_and_line( + self, "basic_type.cpp", self.line, num_expected_locations=0) + + # Now enable breakpoints in implementation files and see the breakpoint + # set succeed + self.runCmd('settings set target.inline-breakpoint-strategy always') + # And add hooks to restore the settings during tearDown(). + self.addTearDownHook(lambda: self.runCmd( + "settings set target.inline-breakpoint-strategy always")) + + lldbutil.run_break_set_by_file_and_line( + self, + "basic_type.cpp", + self.line, + num_expected_locations=1, + loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + # And it should break at basic_type.cpp:176. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint', + 'basic_type.cpp:%d' % self.line]) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp new file mode 100644 index 0000000..75d2c36 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp @@ -0,0 +1,178 @@ +// This file must have the following defined before it is included: +// T defined to the type to test (int, float, etc) +// T_CSTR a C string representation of the type T ("int", "float") +// T_VALUE_1 defined to a valid initializer value for TEST_TYPE (7 for int, 2.0 for float) +// T_VALUE_2, T_VALUE_3, T_VALUE_4 defined to a valid initializer value for TEST_TYPE that is different from TEST_VALUE_1 +// T_PRINTF_FORMAT defined if T can be printed with printf +// +// An example for integers is below +#if 0 + +#define T int +#define T_CSTR "int" +#define T_VALUE_1 11001110 +#define T_VALUE_2 22002220 +#define T_VALUE_3 33003330 +#define T_VALUE_4 44044440 +#define T_PRINTF_FORMAT "%i" + +#include "basic_type.cpp" + +#endif + +#include +#include + +class a_class +{ +public: + a_class (const T& a, const T& b) : + m_a (a), + m_b (b) + { + } + + ~a_class () + { + } + + const T& + get_a() + { + return m_a; + } + + void + set_a (const T& a) + { + m_a = a; + } + + const T& + get_b() + { + return m_b; + } + + void + set_b (const T& b) + { + m_b = b; + } + +protected: + T m_a; + T m_b; +}; + +typedef struct a_struct_tag { + T a; + T b; +} a_struct_t; + + +typedef union a_union_zero_tag { + T a; + double a_double; +} a_union_zero_t; + +typedef struct a_union_nonzero_tag { + double a_double; + a_union_zero_t u; +} a_union_nonzero_t; + + +void Puts(char const *msg) +{ + std::puts(msg); +} + +int +main (int argc, char const *argv[]) +{ + T a = T_VALUE_1; + T* a_ptr = &a; + T& a_ref = a; + T a_array_bounded[2] = { T_VALUE_1, T_VALUE_2 }; + T a_array_unbounded[] = { T_VALUE_1, T_VALUE_2 }; + + a_class a_class_instance (T_VALUE_1, T_VALUE_2); + a_class *a_class_ptr = &a_class_instance; + a_class &a_class_ref = a_class_instance; + + a_struct_t a_struct = { T_VALUE_1, T_VALUE_2 }; + a_struct_t *a_struct_ptr = &a_struct; + a_struct_t &a_struct_ref = a_struct; + + // Create a union with type T at offset zero + a_union_zero_t a_union_zero; + a_union_zero.a = T_VALUE_1; + a_union_zero_t *a_union_zero_ptr = &a_union_zero; + a_union_zero_t &a_union_zero_ref = a_union_zero; + + // Create a union with type T at a non-zero offset + a_union_nonzero_t a_union_nonzero; + a_union_nonzero.u.a = T_VALUE_1; + a_union_nonzero_t *a_union_nonzero_ptr = &a_union_nonzero; + a_union_nonzero_t &a_union_nonzero_ref = a_union_nonzero; + + a_struct_t a_struct_array_bounded[2] = {{ T_VALUE_1, T_VALUE_2 }, { T_VALUE_3, T_VALUE_4 }}; + a_struct_t a_struct_array_unbounded[] = {{ T_VALUE_1, T_VALUE_2 }, { T_VALUE_3, T_VALUE_4 }}; + a_union_zero_t a_union_zero_array_bounded[2]; + a_union_zero_array_bounded[0].a = T_VALUE_1; + a_union_zero_array_bounded[1].a = T_VALUE_2; + a_union_zero_t a_union_zero_array_unbounded[] = {{ T_VALUE_1 }, { T_VALUE_2 }}; + +#ifdef T_PRINTF_FORMAT + std::printf ("%s: a = '" T_PRINTF_FORMAT "'\n", T_CSTR, a); + std::printf ("%s*: %p => *a_ptr = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_ptr, *a_ptr); + std::printf ("%s&: @%p => a_ref = '" T_PRINTF_FORMAT "'\n", T_CSTR, &a_ref, a_ref); + + std::printf ("%s[2]: a_array_bounded[0] = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_array_bounded[0]); + std::printf ("%s[2]: a_array_bounded[1] = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_array_bounded[1]); + + std::printf ("%s[]: a_array_unbounded[0] = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_array_unbounded[0]); + std::printf ("%s[]: a_array_unbounded[1] = '" T_PRINTF_FORMAT "'\n", T_CSTR, a_array_unbounded[1]); + + std::printf ("(a_class) a_class_instance.m_a = '" T_PRINTF_FORMAT "'\n", a_class_instance.get_a()); + std::printf ("(a_class) a_class_instance.m_b = '" T_PRINTF_FORMAT "'\n", a_class_instance.get_b()); + std::printf ("(a_class*) a_class_ptr = %p, a_class_ptr->m_a = '" T_PRINTF_FORMAT "'\n", a_class_ptr, a_class_ptr->get_a()); + std::printf ("(a_class*) a_class_ptr = %p, a_class_ptr->m_b = '" T_PRINTF_FORMAT "'\n", a_class_ptr, a_class_ptr->get_b()); + std::printf ("(a_class&) a_class_ref = %p, a_class_ref.m_a = '" T_PRINTF_FORMAT "'\n", &a_class_ref, a_class_ref.get_a()); + std::printf ("(a_class&) a_class_ref = %p, a_class_ref.m_b = '" T_PRINTF_FORMAT "'\n", &a_class_ref, a_class_ref.get_b()); + + std::printf ("(a_struct_t) a_struct.a = '" T_PRINTF_FORMAT "'\n", a_struct.a); + std::printf ("(a_struct_t) a_struct.b = '" T_PRINTF_FORMAT "'\n", a_struct.b); + std::printf ("(a_struct_t*) a_struct_ptr = %p, a_struct_ptr->a = '" T_PRINTF_FORMAT "'\n", a_struct_ptr, a_struct_ptr->a); + std::printf ("(a_struct_t*) a_struct_ptr = %p, a_struct_ptr->b = '" T_PRINTF_FORMAT "'\n", a_struct_ptr, a_struct_ptr->b); + std::printf ("(a_struct_t&) a_struct_ref = %p, a_struct_ref.a = '" T_PRINTF_FORMAT "'\n", &a_struct_ref, a_struct_ref.a); + std::printf ("(a_struct_t&) a_struct_ref = %p, a_struct_ref.b = '" T_PRINTF_FORMAT "'\n", &a_struct_ref, a_struct_ref.b); + + std::printf ("(a_union_zero_t) a_union_zero.a = '" T_PRINTF_FORMAT "'\n", a_union_zero.a); + std::printf ("(a_union_zero_t*) a_union_zero_ptr = %p, a_union_zero_ptr->a = '" T_PRINTF_FORMAT "'\n", a_union_zero_ptr, a_union_zero_ptr->a); + std::printf ("(a_union_zero_t&) a_union_zero_ref = %p, a_union_zero_ref.a = '" T_PRINTF_FORMAT "'\n", &a_union_zero_ref, a_union_zero_ref.a); + + std::printf ("(a_union_nonzero_t) a_union_nonzero.u.a = '" T_PRINTF_FORMAT "'\n", a_union_nonzero.u.a); + std::printf ("(a_union_nonzero_t*) a_union_nonzero_ptr = %p, a_union_nonzero_ptr->u.a = '" T_PRINTF_FORMAT "'\n", a_union_nonzero_ptr, a_union_nonzero_ptr->u.a); + std::printf ("(a_union_nonzero_t&) a_union_nonzero_ref = %p, a_union_nonzero_ref.u.a = '" T_PRINTF_FORMAT "'\n", &a_union_nonzero_ref, a_union_nonzero_ref.u.a); + + std::printf ("(a_struct_t[2]) a_struct_array_bounded[0].a = '" T_PRINTF_FORMAT "'\n", a_struct_array_bounded[0].a); + std::printf ("(a_struct_t[2]) a_struct_array_bounded[0].b = '" T_PRINTF_FORMAT "'\n", a_struct_array_bounded[0].b); + std::printf ("(a_struct_t[2]) a_struct_array_bounded[1].a = '" T_PRINTF_FORMAT "'\n", a_struct_array_bounded[1].a); + std::printf ("(a_struct_t[2]) a_struct_array_bounded[1].b = '" T_PRINTF_FORMAT "'\n", a_struct_array_bounded[1].b); + + std::printf ("(a_struct_t[]) a_struct_array_unbounded[0].a = '" T_PRINTF_FORMAT "'\n", a_struct_array_unbounded[0].a); + std::printf ("(a_struct_t[]) a_struct_array_unbounded[0].b = '" T_PRINTF_FORMAT "'\n", a_struct_array_unbounded[0].b); + std::printf ("(a_struct_t[]) a_struct_array_unbounded[1].a = '" T_PRINTF_FORMAT "'\n", a_struct_array_unbounded[1].a); + std::printf ("(a_struct_t[]) a_struct_array_unbounded[1].b = '" T_PRINTF_FORMAT "'\n", a_struct_array_unbounded[1].b); + + std::printf ("(a_union_zero_t[2]) a_union_zero_array_bounded[0].a = '" T_PRINTF_FORMAT "'\n", a_union_zero_array_bounded[0].a); + std::printf ("(a_union_zero_t[2]) a_union_zero_array_bounded[1].a = '" T_PRINTF_FORMAT "'\n", a_union_zero_array_bounded[1].a); + + std::printf ("(a_union_zero_t[]) a_union_zero_array_unbounded[0].a = '" T_PRINTF_FORMAT "'\n", a_union_zero_array_unbounded[0].a); + std::printf ("(a_union_zero_t[]) a_union_zero_array_unbounded[1].a = '" T_PRINTF_FORMAT "'\n", a_union_zero_array_unbounded[1].a); + +#endif + Puts("About to exit, break here to check values..."); // Set break point at this line. + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/int.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/int.cpp new file mode 100644 index 0000000..922398b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/inlined_breakpoints/int.cpp @@ -0,0 +1,9 @@ +#define T int +#define T_CSTR "int" +#define T_VALUE_1 11001110 +#define T_VALUE_2 22002220 +#define T_VALUE_3 33003330 +#define T_VALUE_4 44004440 +#define T_PRINTF_FORMAT "%i" + +#include "basic_type.cpp" diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile new file mode 100644 index 0000000..06ef85c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +DYLIB_NAME := foo +DYLIB_CXX_SOURCES := foo.cpp +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py new file mode 100644 index 0000000..b8281e9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py @@ -0,0 +1,69 @@ +from __future__ import print_function + + +import unittest2 +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestMoveNearest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line1 = line_number('foo.h', '// !BR1') + self.line2 = line_number('foo.h', '// !BR2') + self.line_between = line_number('main.cpp', "// BR_Between") + print("BR_Between found at", self.line_between) + self.line_main = line_number('main.cpp', '// !BR_main') + + def test(self): + """Test target.move-to-nearest logic""" + + self.build() + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + lldbutil.run_break_set_by_symbol(self, 'main', sym_exact=True) + environment = self.registerSharedLibrariesWithTarget(target, ["foo"]) + process = target.LaunchSimple(None, environment, self.get_process_working_directory()) + self.assertEquals(process.GetState(), lldb.eStateStopped) + + # Regardless of the -m value the breakpoint should have exactly one + # location on the foo functions + self.runCmd("settings set target.move-to-nearest-code true") + lldbutil.run_break_set_by_file_and_line(self, 'foo.h', self.line1, + loc_exact=True, extra_options="-m 1") + lldbutil.run_break_set_by_file_and_line(self, 'foo.h', self.line2, + loc_exact=True, extra_options="-m 1") + + self.runCmd("settings set target.move-to-nearest-code false") + lldbutil.run_break_set_by_file_and_line(self, 'foo.h', self.line1, + loc_exact=True, extra_options="-m 0") + lldbutil.run_break_set_by_file_and_line(self, 'foo.h', self.line2, + loc_exact=True, extra_options="-m 0") + + + # Make sure we set a breakpoint in main with -m 1 for various lines in + # the function declaration + # "int" + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_main-1, extra_options="-m 1") + # "main()" + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_main, extra_options="-m 1") + # "{" + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_main+1, extra_options="-m 1") + # "return .." + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_main+2, extra_options="-m 1") + + # Make sure we don't put move the breakpoint if it is set between two functions: + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', + self.line_between, extra_options="-m 1", num_expected_locations=0) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp new file mode 100644 index 0000000..8dad0a23 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.cpp @@ -0,0 +1,3 @@ +#include "foo.h" + +int call_foo1() { return foo1(); } diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h new file mode 100644 index 0000000..9f0e56d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/foo.h @@ -0,0 +1,5 @@ +inline int foo1() { return 1; } // !BR1 + +inline int foo2() { return 2; } // !BR2 + +LLDB_TEST_API extern int call_foo1(); diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp new file mode 100644 index 0000000..76a22a5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp @@ -0,0 +1,9 @@ +#include "foo.h" + +int call_foo2() { return foo2(); } +// BR_Between +int +main() // !BR_main +{ + return call_foo1() + call_foo2(); +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/Makefile new file mode 100644 index 0000000..ad3cb3f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py new file mode 100644 index 0000000..c33bd80 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py @@ -0,0 +1,130 @@ +""" +Test that objective-c constant strings are generated correctly by the expression +parser. +""" + +from __future__ import print_function + + +import shutil +import subprocess +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +@skipUnlessDarwin +class TestObjCBreakpoints(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_break(self): + """Test setting Objective-C specific breakpoints (DWARF in .o files).""" + self.build() + self.setTearDownCleanup() + self.check_objc_breakpoints(False) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.main_source = "main.m" + self.line = line_number(self.main_source, '// Set breakpoint here') + + def check_category_breakpoints(self): + name_bp = self.target.BreakpointCreateByName("myCategoryFunction") + selector_bp = self.target.BreakpointCreateByName( + "myCategoryFunction", + lldb.eFunctionNameTypeSelector, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + name_bp.GetNumLocations() == selector_bp.GetNumLocations(), + 'Make sure setting a breakpoint by name "myCategoryFunction" sets a breakpoint even though it is in a category') + for bp_loc in selector_bp: + function_name = bp_loc.GetAddress().GetSymbol().GetName() + self.assertTrue( + " myCategoryFunction]" in function_name, + 'Make sure all function names have " myCategoryFunction]" in their names') + + category_bp = self.target.BreakpointCreateByName( + "-[MyClass(MyCategory) myCategoryFunction]") + stripped_bp = self.target.BreakpointCreateByName( + "-[MyClass myCategoryFunction]") + stripped2_bp = self.target.BreakpointCreateByName( + "[MyClass myCategoryFunction]") + self.assertTrue( + category_bp.GetNumLocations() == 1, + "Make sure we can set a breakpoint using a full objective C function name with the category included (-[MyClass(MyCategory) myCategoryFunction])") + self.assertTrue( + stripped_bp.GetNumLocations() == 1, + "Make sure we can set a breakpoint using a full objective C function name without the category included (-[MyClass myCategoryFunction])") + self.assertTrue( + stripped2_bp.GetNumLocations() == 1, + "Make sure we can set a breakpoint using a full objective C function name without the category included ([MyClass myCategoryFunction])") + + def check_objc_breakpoints(self, have_dsym): + """Test constant string generation amd comparison by the expression parser.""" + + # Set debugger into synchronous mode + self.dbg.SetAsync(False) + + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + #---------------------------------------------------------------------- + # Set breakpoints on all selectors whose name is "count". This should + # catch breakpoints that are both C functions _and_ anything whose + # selector is "count" because just looking at "count" we can't tell + # definitively if the name is a selector or a C function + #---------------------------------------------------------------------- + name_bp = self.target.BreakpointCreateByName("count") + selector_bp = self.target.BreakpointCreateByName( + "count", + lldb.eFunctionNameTypeSelector, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + name_bp.GetNumLocations() >= selector_bp.GetNumLocations(), + 'Make sure we get at least the same amount of breakpoints if not more when setting by name "count"') + self.assertTrue( + selector_bp.GetNumLocations() > 50, + 'Make sure we find a lot of "count" selectors') # There are 93 on the latest MacOSX + for bp_loc in selector_bp: + function_name = bp_loc.GetAddress().GetSymbol().GetName() + self.assertTrue( + " count]" in function_name, + 'Make sure all function names have " count]" in their names') + + #---------------------------------------------------------------------- + # Set breakpoints on all selectors whose name is "isEqual:". This should + # catch breakpoints that are only ObjC selectors because no C function + # can end with a : + #---------------------------------------------------------------------- + name_bp = self.target.BreakpointCreateByName("isEqual:") + selector_bp = self.target.BreakpointCreateByName( + "isEqual:", + lldb.eFunctionNameTypeSelector, + lldb.SBFileSpecList(), + lldb.SBFileSpecList()) + self.assertTrue( + name_bp.GetNumLocations() == selector_bp.GetNumLocations(), + 'Make sure setting a breakpoint by name "isEqual:" only sets selector breakpoints') + for bp_loc in selector_bp: + function_name = bp_loc.GetAddress().GetSymbol().GetName() + self.assertTrue( + " isEqual:]" in function_name, + 'Make sure all function names have " isEqual:]" in their names') + + self.check_category_breakpoints() + + if have_dsym: + shutil.rmtree(exe + ".dSYM") + self.assertTrue(subprocess.call( + ['/usr/bin/strip', '-Sx', exe]) == 0, 'stripping dylib succeeded') + + # Check breakpoints again, this time using the symbol table only + self.check_category_breakpoints() diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/main.m b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/main.m new file mode 100644 index 0000000..5356749 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/main.m @@ -0,0 +1,98 @@ +#import +#include + +@interface MyClass : NSObject +@end + +@implementation MyClass : NSObject +@end + +@implementation MyClass (MyCategory) + + +- (void) myCategoryFunction { + NSLog (@"myCategoryFunction"); +} + +@end + + + +int +Test_Selector () +{ + SEL sel = @selector(length); + printf("sel = %p\n", sel); + // Expressions to test here for selector: + // expression (char *)sel_getName(sel) + // The expression above should return "sel" as it should be just + // a uniqued C string pointer. We were seeing the result pointer being + // truncated with recent LLDBs. + return 0; // Break here for selector: tests +} + +int +Test_NSString (const char *program) +{ + NSString *str = [NSString stringWithFormat:@"Hello from '%s'", program]; + NSLog(@"NSString instance: %@", str); + printf("str = '%s'\n", [str cStringUsingEncoding: [NSString defaultCStringEncoding]]); + printf("[str length] = %zu\n", (size_t)[str length]); + printf("[str description] = %s\n", [[str description] UTF8String]); + id str_id = str; + // Expressions to test here for NSString: + // expression (char *)sel_getName(sel) + // expression [str length] + // expression [str_id length] + // expression [str description] + // expression [str_id description] + // expression str.length + // expression str.description + // expression str = @"new" + // expression str = [NSString stringWithFormat: @"%cew", 'N'] + return 0; // Break here for NSString tests +} + +NSString *my_global_str = NULL; + +int +Test_NSArray () +{ + NSMutableArray *nil_mutable_array = nil; + NSArray *array1 = [NSArray arrayWithObjects: @"array1 object1", @"array1 object2", @"array1 object3", nil]; + NSArray *array2 = [NSArray arrayWithObjects: array1, @"array2 object2", @"array2 object3", nil]; + // Expressions to test here for NSArray: + // expression [nil_mutable_array count] + // expression [array1 count] + // expression array1.count + // expression [array2 count] + // expression array2.count + id obj; + // After each object at index call, use expression and validate object + obj = [array1 objectAtIndex: 0]; // Break here for NSArray tests + obj = [array1 objectAtIndex: 1]; + obj = [array1 objectAtIndex: 2]; + + obj = [array2 objectAtIndex: 0]; + obj = [array2 objectAtIndex: 1]; + obj = [array2 objectAtIndex: 2]; + NSUInteger count = [nil_mutable_array count]; + return 0; +} + + +int main (int argc, char const *argv[]) +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + Test_Selector(); // Set breakpoint here + Test_NSArray (); + Test_NSString (argv[0]); + MyClass *my_class = [[MyClass alloc] init]; + [my_class myCategoryFunction]; + printf("sizeof(id) = %zu\n", sizeof(id)); + printf("sizeof(Class) = %zu\n", sizeof(Class)); + printf("sizeof(SEL) = %zu\n", sizeof(SEL)); + + [pool release]; + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile new file mode 100644 index 0000000..7934cd5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +ifneq (,$(findstring icc,$(CC))) + CFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py new file mode 100644 index 0000000..020974e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py @@ -0,0 +1,103 @@ +""" +Test require hardware breakpoints. +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointLocationsTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) + + def test_breakpoint(self): + """Test regular breakpoints when hardware breakpoints are required.""" + self.build() + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + breakpoint = target.BreakpointCreateByLocation("main.c", 1) + self.assertTrue(breakpoint.IsHardware()) + + @skipIfWindows + def test_step_range(self): + """Test stepping when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 1) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + # Ensure we fail in the interpreter. + self.expect("thread step-in") + self.expect("thread step-in", error=True) + + # Ensure we fail when stepping through the API. + error = lldb.SBError() + thread.StepInto('', 4, error) + self.assertTrue(error.Fail()) + self.assertTrue("Could not create hardware breakpoint for thread plan" + in error.GetCString()) + + @skipIfWindows + def test_step_out(self): + """Test stepping out when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 1) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + # Ensure this fails in the command interpreter. + self.expect("thread step-out", error=True) + + # Ensure we fail when stepping through the API. + error = lldb.SBError() + thread.StepOut(error) + self.assertTrue(error.Fail()) + self.assertTrue("Could not create hardware breakpoint for thread plan" + in error.GetCString()) + + @skipIfWindows + def test_step_over(self): + """Test stepping over when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 7) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + # Step over doesn't fail immediately but fails later on. + self.expect( + "thread step-over", + error=True, + substrs=[ + 'error: Could not create hardware breakpoint for thread plan.' + ]) + + @skipIfWindows + def test_step_until(self): + """Test stepping until when hardware breakpoints are required.""" + self.build() + + _, _, thread, _ = lldbutil.run_to_line_breakpoint( + self, lldb.SBFileSpec("main.c"), 7) + + self.runCmd("settings set target.require-hardware-breakpoint true") + + self.expect("thread until 5", error=True) + + # Ensure we fail when stepping through the API. + error = thread.StepOverUntil(lldb.SBFrame(), lldb.SBFileSpec(), 5) + self.assertTrue(error.Fail()) + self.assertTrue("Could not create hardware breakpoint for thread plan" + in error.GetCString()) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c new file mode 100644 index 0000000..7d49a57 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c @@ -0,0 +1,9 @@ +int break_on_me() { + int i = 10; + i++; + return i; +} + +int main() { + return break_on_me(); +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile new file mode 100644 index 0000000..6067ee45 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py new file mode 100644 index 0000000..59abad6 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py @@ -0,0 +1,197 @@ +""" +Test setting breakpoints using a scripted resolver +""" + +from __future__ import print_function + + +import os +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class TestScriptedResolver(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_scripted_resolver(self): + """Use a scripted resolver to set a by symbol name breakpoint""" + self.build() + self.do_test() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_search_depths(self): + """ Make sure we are called at the right depths depending on what we return + from __get_depth__""" + self.build() + self.do_test_depths() + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") + def test_command_line(self): + """ Make sure we are called at the right depths depending on what we return + from __get_depth__""" + self.build() + self.do_test_cli() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def make_target_and_import(self): + target = lldbutil.run_to_breakpoint_make_target(self) + interp = self.dbg.GetCommandInterpreter() + error = lldb.SBError() + + script_name = os.path.join(self.getSourceDir(), "resolver.py") + source_name = os.path.join(self.getSourceDir(), "main.c") + + command = "command script import " + script_name + result = lldb.SBCommandReturnObject() + interp.HandleCommand(command, result) + self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError())) + return target + + def make_extra_args(self): + json_string = '{"symbol":"break_on_me", "test1": "value1"}' + json_stream = lldb.SBStream() + json_stream.Print(json_string) + extra_args = lldb.SBStructuredData() + error = extra_args.SetFromJSON(json_stream) + self.assertTrue(error.Success(), "Error making SBStructuredData: %s"%(error.GetCString())) + return extra_args + + 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() + + file_list = lldb.SBFileSpecList() + module_list = lldb.SBFileSpecList() + + # Make breakpoints with this resolver using different filters, first ones that will take: + right = [] + # one with no file or module spec - this one should fire: + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # one with the right source file and no module - should also fire: + file_list.Append(lldb.SBFileSpec("main.c")) + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + # Make sure the help text shows up in the "break list" output: + self.expect("break list", substrs=["I am a python breakpoint resolver"], msg="Help is listed in break list") + + # one with the right source file and right module - should also fire: + module_list.Append(lldb.SBFileSpec("a.out")) + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # And one with no source file but the right module: + file_list.Clear() + right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # Make sure these all got locations: + for i in range (0, len(right)): + self.assertTrue(right[i].GetNumLocations() >= 1, "Breakpoint %d has no locations."%(i)) + + # Now some ones that won't take: + + module_list.Clear() + file_list.Clear() + wrong = [] + + # one with the wrong module - should not fire: + module_list.Append(lldb.SBFileSpec("noSuchModule")) + wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # one with the wrong file - also should not fire: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("noFileOfThisName.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)) + + # Now make sure the CU level iteration obeys the file filters: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) + + # And the Module filters: + file_list.Clear() + module_list.Clear() + module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)) + + # Now make sure the Function level iteration obeys the file filters: + file_list.Clear() + module_list.Clear() + file_list.Append(lldb.SBFileSpec("no_such_file.xxx")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) + + # And the Module filters: + file_list.Clear() + module_list.Clear() + module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib")) + wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)) + + # Make sure these didn't get locations: + for i in range(0, len(wrong)): + self.assertEqual(wrong[i].GetNumLocations(), 0, "Breakpoint %d has locations."%(i)) + + # Now run to main and ensure we hit the breakpoints we should have: + + lldbutil.run_to_breakpoint_do_run(self, target, right[0]) + + # Test the hit counts: + for i in range(0, len(right)): + self.assertEqual(right[i].GetHitCount(), 1, "Breakpoint %d has the wrong hit count"%(i)) + + for i in range(0, len(wrong)): + self.assertEqual(wrong[i].GetHitCount(), 0, "Breakpoint %d has the wrong hit count"%(i)) + + def do_test_depths(self): + """This test uses a class variable in resolver.Resolver which gets set to 1 if we saw + compile unit and 2 if we only saw modules. If the search depth is module, you get passed just + the modules with no comp_unit. If the depth is comp_unit you get comp_units. So we can use + this to test that our callback gets called at the right depth.""" + + target = self.make_target_and_import() + extra_args = self.make_extra_args() + + file_list = lldb.SBFileSpecList() + module_list = lldb.SBFileSpecList() + module_list.Append(lldb.SBFileSpec("a.out")) + + # Make a breakpoint that has no __get_depth__, check that that is converted to eSearchDepthModule: + bkpt = target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "Resolver got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") + + # Make a breakpoint that asks for modules, check that we didn't get any files: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverModuleDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverModuleDepth got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") + + # Make a breakpoint that asks for compile units, check that we didn't get any files: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverCUDepth got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["1"], msg="Was passed compile units") + + # Make a breakpoint that returns a bad value - we should convert that to "modules" so check that: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverBadDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverBadDepth got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["2"], msg="Was only passed modules") + + # Make a breakpoint that searches at function depth: + bkpt = target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list) + self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverFuncDepth got no locations.") + self.expect("script print(resolver.Resolver.got_files)", substrs=["3"], msg="Was only passed modules") + self.expect("script print(resolver.Resolver.func_list)", substrs=["break_on_me", "main", "test_func"], msg="Saw all the functions") + + def do_test_cli(self): + target = self.make_target_and_import() + + lldbutil.run_break_set_by_script(self, "resolver.Resolver", extra_options="-k symbol -v break_on_me") diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c new file mode 100644 index 0000000..b91ccfc --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c @@ -0,0 +1,21 @@ +#include + +int +test_func() +{ + return printf("I am a test function."); +} + +void +break_on_me() +{ + printf("I was called.\n"); +} + +int +main() +{ + break_on_me(); + test_func(); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py new file mode 100644 index 0000000..61f5f2d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py @@ -0,0 +1,54 @@ +import lldb + +class Resolver: + got_files = 0 + func_list = [] + + def __init__(self, bkpt, extra_args, dict): + self.bkpt = bkpt + self.extra_args = extra_args + Resolver.func_list = [] + Resolver.got_files = 0 + + def __callback__(self, sym_ctx): + sym_name = "not_a_real_function_name" + sym_item = self.extra_args.GetValueForKey("symbol") + if sym_item.IsValid(): + sym_name = sym_item.GetStringValue(1000) + + if sym_ctx.compile_unit.IsValid(): + Resolver.got_files = 1 + else: + Resolver.got_files = 2 + + if sym_ctx.function.IsValid(): + Resolver.got_files = 3 + func_name = sym_ctx.function.GetName() + Resolver.func_list.append(func_name) + if sym_name == func_name: + self.bkpt.AddLocation(sym_ctx.function.GetStartAddress()) + return + + if sym_ctx.module.IsValid(): + sym = sym_ctx.module.FindSymbol(sym_name, lldb.eSymbolTypeCode) + if sym.IsValid(): + self.bkpt.AddLocation(sym.GetStartAddress()) + + def get_short_help(self): + return "I am a python breakpoint resolver" + +class ResolverModuleDepth(Resolver): + def __get_depth__ (self): + return lldb.eSearchDepthModule + +class ResolverCUDepth(Resolver): + def __get_depth__ (self): + return lldb.eSearchDepthCompUnit + +class ResolverFuncDepth(Resolver): + def __get_depth__ (self): + return lldb.eSearchDepthFunction + +class ResolverBadDepth(Resolver): + def __get_depth__ (self): + return lldb.kLastSearchDepthKind + 1 diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py new file mode 100644 index 0000000..086203e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py @@ -0,0 +1,291 @@ +""" +Test breakpoint serialization. +""" + +from __future__ import print_function + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointSerialization(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @add_test_categories(['pyapi']) + def test_resolvers(self): + """Use Python APIs to test that we serialize resolvers.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_resolvers() + + def test_filters(self): + """Use Python APIs to test that we serialize search filters correctly.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_filters() + + def test_options(self): + """Use Python APIs to test that we serialize breakpoint options correctly.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_options() + + def test_appending(self): + """Use Python APIs to test that we serialize breakpoint options correctly.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_appending() + + def test_name_filters(self): + """Use python APIs to test that reading in by name works correctly.""" + self.build() + self.setup_targets_and_cleanup() + self.do_check_names() + + def setup_targets_and_cleanup(self): + def cleanup (): + self.RemoveTempFile(self.bkpts_file_path) + + if self.orig_target.IsValid(): + self.dbg.DeleteTarget(self.orig_target) + self.dbg.DeleteTarget(self.copy_target) + + self.addTearDownHook(cleanup) + self.RemoveTempFile(self.bkpts_file_path) + + exe = self.getBuildArtifact("a.out") + + # Create the targets we are making breakpoints in and copying them to: + self.orig_target = self.dbg.CreateTarget(exe) + self.assertTrue(self.orig_target, VALID_TARGET) + + self.copy_target = self.dbg.CreateTarget(exe) + self.assertTrue(self.copy_target, VALID_TARGET) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.bkpts_file_path = self.getBuildArtifact("breakpoints.json") + self.bkpts_file_spec = lldb.SBFileSpec(self.bkpts_file_path) + + def check_equivalence(self, source_bps, do_write = True): + + error = lldb.SBError() + + if (do_write): + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps) + self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString())) + + copy_bps = lldb.SBBreakpointList(self.copy_target) + error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps) + self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString())) + + num_source_bps = source_bps.GetSize() + num_copy_bps = copy_bps.GetSize() + self.assertTrue(num_source_bps == num_copy_bps, "Didn't get same number of input and output breakpoints - orig: %d copy: %d"%(num_source_bps, num_copy_bps)) + + for i in range(0, num_source_bps): + source_bp = source_bps.GetBreakpointAtIndex(i) + source_desc = lldb.SBStream() + source_bp.GetDescription(source_desc, False) + source_text = source_desc.GetData() + + # I am assuming here that the breakpoints will get written out in breakpoint ID order, and + # read back in ditto. That is true right now, and I can't see any reason to do it differently + # but if we do we can go to writing the breakpoints one by one, or sniffing the descriptions to + # see which one is which. + copy_id = source_bp.GetID() + copy_bp = copy_bps.FindBreakpointByID(copy_id) + self.assertTrue(copy_bp.IsValid(), "Could not find copy breakpoint %d."%(copy_id)) + + copy_desc = lldb.SBStream() + copy_bp.GetDescription(copy_desc, False) + copy_text = copy_desc.GetData() + + # These two should be identical. + # print ("Source text for %d is %s."%(i, source_text)) + self.assertTrue (source_text == copy_text, "Source and dest breakpoints are not identical: \nsource: %s\ndest: %s"%(source_text, copy_text)) + + def do_check_resolvers(self): + """Use Python APIs to check serialization of breakpoint resolvers""" + + empty_module_list = lldb.SBFileSpecList() + empty_cu_list = lldb.SBFileSpecList() + blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) + + # It isn't actually important for these purposes that these breakpoint + # actually have locations. + source_bps = lldb.SBBreakpointList(self.orig_target) + source_bps.Append(self.orig_target.BreakpointCreateByLocation("blubby.c", 666)) + # Make sure we do one breakpoint right: + self.check_equivalence(source_bps) + source_bps.Clear() + + source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list)) + source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list)) + source_bps.Append(self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec)) + + # And some number greater than one: + self.check_equivalence(source_bps) + + def do_check_filters(self): + """Use Python APIs to check serialization of breakpoint filters.""" + module_list = lldb.SBFileSpecList() + module_list.Append(lldb.SBFileSpec("SomeBinary")) + module_list.Append(lldb.SBFileSpec("SomeOtherBinary")) + + cu_list = lldb.SBFileSpecList() + cu_list.Append(lldb.SBFileSpec("SomeCU.c")) + cu_list.Append(lldb.SBFileSpec("AnotherCU.c")) + cu_list.Append(lldb.SBFileSpec("ThirdCU.c")) + + blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) + + # It isn't actually important for these purposes that these breakpoint + # actually have locations. + source_bps = lldb.SBBreakpointList(self.orig_target) + bkpt = self.orig_target.BreakpointCreateByLocation(blubby_file_spec, 666, 0, module_list) + source_bps.Append(bkpt) + + # Make sure we do one right: + self.check_equivalence(source_bps) + source_bps.Clear() + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, module_list, cu_list) + source_bps.Append(bkpt) + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, module_list, cu_list) + source_bps.Append(bkpt) + bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec) + source_bps.Append(bkpt) + + # And some number greater than one: + self.check_equivalence(source_bps) + + def do_check_options(self): + """Use Python APIs to check serialization of breakpoint options.""" + + empty_module_list = lldb.SBFileSpecList() + empty_cu_list = lldb.SBFileSpecList() + blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) + + # It isn't actually important for these purposes that these breakpoint + # actually have locations. + source_bps = lldb.SBBreakpointList(self.orig_target) + + bkpt = self.orig_target.BreakpointCreateByLocation( + lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) + bkpt.SetEnabled(False) + bkpt.SetOneShot(True) + bkpt.SetThreadID(10) + source_bps.Append(bkpt) + + # Make sure we get one right: + self.check_equivalence(source_bps) + source_bps.Clear() + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list) + bkpt.SetIgnoreCount(10) + bkpt.SetThreadName("grubby") + source_bps.Append(bkpt) + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list) + bkpt.SetCondition("gonna remove this") + bkpt.SetCondition("") + source_bps.Append(bkpt) + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list) + bkpt.SetCondition("something != something_else") + bkpt.SetQueueName("grubby") + bkpt.AddName("FirstName") + bkpt.AddName("SecondName") + bkpt.SetScriptCallbackBody('\tprint("I am a function that prints.")\n\tprint("I don\'t do anything else")\n') + source_bps.Append(bkpt) + + bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec) + cmd_list = lldb.SBStringList() + cmd_list.AppendString("frame var") + cmd_list.AppendString("thread backtrace") + + bkpt.SetCommandLineCommands(cmd_list) + source_bps.Append(bkpt) + + self.check_equivalence(source_bps) + + def do_check_appending(self): + """Use Python APIs to check appending to already serialized options.""" + + empty_module_list = lldb.SBFileSpecList() + empty_cu_list = lldb.SBFileSpecList() + blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) + + # It isn't actually important for these purposes that these breakpoint + # actually have locations. + + all_bps = lldb.SBBreakpointList(self.orig_target) + source_bps = lldb.SBBreakpointList(self.orig_target) + + bkpt = self.orig_target.BreakpointCreateByLocation( + lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) + bkpt.SetEnabled(False) + bkpt.SetOneShot(True) + bkpt.SetThreadID(10) + source_bps.Append(bkpt) + all_bps.Append(bkpt) + + error = lldb.SBError() + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps) + self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString())) + + source_bps.Clear() + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list) + bkpt.SetIgnoreCount(10) + bkpt.SetThreadName("grubby") + source_bps.Append(bkpt) + all_bps.Append(bkpt) + + bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list) + bkpt.SetCondition("something != something_else") + bkpt.SetQueueName("grubby") + bkpt.AddName("FirstName") + bkpt.AddName("SecondName") + + source_bps.Append(bkpt) + all_bps.Append(bkpt) + + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps, True) + self.assertTrue(error.Success(), "Failed appending breakpoints to file: %s."%(error.GetCString())) + + self.check_equivalence(all_bps) + + def do_check_names(self): + bkpt = self.orig_target.BreakpointCreateByLocation( + lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) + good_bkpt_name = "GoodBreakpoint" + write_bps = lldb.SBBreakpointList(self.orig_target) + bkpt.AddName(good_bkpt_name) + write_bps.Append(bkpt) + + error = lldb.SBError() + error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps) + self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString())) + + copy_bps = lldb.SBBreakpointList(self.copy_target) + names_list = lldb.SBStringList() + names_list.AppendString("NoSuchName") + + error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps) + self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString())) + self.assertTrue(copy_bps.GetSize() == 0, "Found breakpoints with a nonexistent name.") + + names_list.AppendString(good_bkpt_name) + error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps) + self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString())) + self.assertTrue(copy_bps.GetSize() == 1, "Found the matching breakpoint.") diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/main.c new file mode 100644 index 0000000..b1ed446 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint modify -i breakpt-id" to set the number of times a +// breakpoint is skipped before stopping. Ignore count can also be set upon +// breakpoint creation by 'breakpoint set ... -i '. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // a(3) -> c(3) Find the call site of c(3). + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) Find the call site of b(2). + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) Find the call site of a(3). + printf("a(3) returns %d\n", A3); + + int C1 = c(5); // Find the call site of c in main. + printf ("c(5) returns %d\n", C1); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile new file mode 100644 index 0000000..ac984f1 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c a.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py new file mode 100644 index 0000000..2258989 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py @@ -0,0 +1,104 @@ +""" +Test lldb breakpoint setting by source regular expression. +This test just tests the source file & function restrictions. +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestSourceRegexBreakpoints(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_location(self): + self.build() + self.source_regex_locations() + + def test_restrictions(self): + self.build() + self.source_regex_restrictions() + + def source_regex_locations(self): + """ Test that restricting source expressions to files & to functions. """ + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # First look just in main: + target_files = lldb.SBFileSpecList() + target_files.Append(lldb.SBFileSpec("a.c")) + + func_names = lldb.SBStringList() + func_names.AppendString("a_func") + + source_regex = "Set . breakpoint here" + main_break = target.BreakpointCreateBySourceRegex( + source_regex, lldb.SBFileSpecList(), target_files, func_names) + num_locations = main_break.GetNumLocations() + self.assertTrue( + num_locations == 1, + "a.c in a_func should give one breakpoint, got %d." % + (num_locations)) + + loc = main_break.GetLocationAtIndex(0) + self.assertTrue(loc.IsValid(), "Got a valid location.") + address = loc.GetAddress() + self.assertTrue( + address.IsValid(), + "Got a valid address from the location.") + + a_func_line = line_number("a.c", "Set A breakpoint here") + line_entry = address.GetLineEntry() + self.assertTrue(line_entry.IsValid(), "Got a valid line entry.") + self.assertTrue(line_entry.line == a_func_line, + "Our line number matches the one lldbtest found.") + + def source_regex_restrictions(self): + """ Test that restricting source expressions to files & to functions. """ + # Create a target by the debugger. + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # First look just in main: + target_files = lldb.SBFileSpecList() + target_files.Append(lldb.SBFileSpec("main.c")) + source_regex = "Set . breakpoint here" + main_break = target.BreakpointCreateBySourceRegex( + source_regex, lldb.SBFileSpecList(), target_files, lldb.SBStringList()) + + num_locations = main_break.GetNumLocations() + self.assertTrue( + num_locations == 2, + "main.c should have 2 matches, got %d." % + (num_locations)) + + # Now look in both files: + target_files.Append(lldb.SBFileSpec("a.c")) + + main_break = target.BreakpointCreateBySourceRegex( + source_regex, lldb.SBFileSpecList(), target_files, lldb.SBStringList()) + + num_locations = main_break.GetNumLocations() + self.assertTrue( + num_locations == 4, + "main.c and a.c should have 4 matches, got %d." % + (num_locations)) + + # Now restrict it to functions: + func_names = lldb.SBStringList() + func_names.AppendString("main_func") + main_break = target.BreakpointCreateBySourceRegex( + source_regex, lldb.SBFileSpecList(), target_files, func_names) + + num_locations = main_break.GetNumLocations() + self.assertTrue( + num_locations == 2, + "main_func in main.c and a.c should have 2 matches, got %d." % + (num_locations)) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c new file mode 100644 index 0000000..056583f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c @@ -0,0 +1,16 @@ +#include + +#include "a.h" + +static int +main_func(int input) +{ + return printf("Set B breakpoint here: %d", input); +} + +int +a_func(int input) +{ + input += 1; // Set A breakpoint here; + return main_func(input); +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h new file mode 100644 index 0000000..f578ac0 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h @@ -0,0 +1 @@ +int a_func(int); diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c new file mode 100644 index 0000000..9c8625e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c @@ -0,0 +1,17 @@ +#include +#include "a.h" + +int +main_func(int input) +{ + return printf("Set B breakpoint here: %d.\n", input); +} + +int +main() +{ + a_func(10); + main_func(10); + printf("Set a breakpoint here:\n"); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile new file mode 100644 index 0000000..f89b52a9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py new file mode 100644 index 0000000..07fd049 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py @@ -0,0 +1,119 @@ +""" +Test that breakpoints do not affect stepping. +Check for correct StopReason when stepping to the line with breakpoint +which chould be eStopReasonBreakpoint in general, +and eStopReasonPlanComplete when breakpoint's condition fails. +""" + +from __future__ import print_function + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class StepOverBreakpointsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + + self.build() + exe = self.getBuildArtifact("a.out") + src = lldb.SBFileSpec("main.cpp") + + # Create a target by the debugger. + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + # Setup four breakpoints, two of them with false condition + self.line1 = line_number('main.cpp', "breakpoint_1") + self.line4 = line_number('main.cpp', "breakpoint_4") + + self.breakpoint1 = self.target.BreakpointCreateByLocation(src, self.line1) + self.assertTrue( + self.breakpoint1 and self.breakpoint1.GetNumLocations() == 1, + VALID_BREAKPOINT) + + self.breakpoint2 = self.target.BreakpointCreateBySourceRegex("breakpoint_2", src) + self.breakpoint2.GetLocationAtIndex(0).SetCondition('false') + + self.breakpoint3 = self.target.BreakpointCreateBySourceRegex("breakpoint_3", src) + self.breakpoint3.GetLocationAtIndex(0).SetCondition('false') + + self.breakpoint4 = self.target.BreakpointCreateByLocation(src, self.line4) + + # Start debugging + self.process = self.target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertIsNotNone(self.process, PROCESS_IS_VALID) + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint1) + self.assertIsNotNone(self.thread, "Didn't stop at breakpoint 1.") + + def test_step_instruction(self): + # Count instructions between breakpoint_1 and breakpoint_4 + contextList = self.target.FindFunctions('main', lldb.eFunctionNameTypeAuto) + self.assertEquals(contextList.GetSize(), 1) + symbolContext = contextList.GetContextAtIndex(0) + function = symbolContext.GetFunction() + self.assertTrue(function) + instructions = function.GetInstructions(self.target) + addr_1 = self.breakpoint1.GetLocationAtIndex(0).GetAddress() + addr_4 = self.breakpoint4.GetLocationAtIndex(0).GetAddress() + + # if third argument is true then the count will be the number of + # instructions on which a breakpoint can be set. + # start = addr_1, end = addr_4, canSetBreakpoint = True + steps_expected = instructions.GetInstructionsCount(addr_1, addr_4, True) + step_count = 0 + # Step from breakpoint_1 to breakpoint_4 + while True: + self.thread.StepInstruction(True) + step_count = step_count + 1 + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertTrue(self.thread.GetStopReason() == lldb.eStopReasonPlanComplete or + self.thread.GetStopReason() == lldb.eStopReasonBreakpoint) + if (self.thread.GetStopReason() == lldb.eStopReasonBreakpoint) : + # we should not stop on breakpoint_2 and _3 because they have false condition + self.assertEquals(self.thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.line4) + # breakpoint_2 and _3 should not affect step count + self.assertTrue(step_count >= steps_expected) + break + + # Run the process until termination + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateExited) + + @skipIf(bugnumber="llvm.org/pr31972", hostoslist=["windows"]) + def test_step_over(self): + #lldb.DBG.EnableLog("lldb", ["step","breakpoint"]) + + self.thread.StepOver() + # We should be stopped at the breakpoint_2 line with stop plan complete reason + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete) + + self.thread.StepOver() + # We should be stopped at the breakpoint_3 line with stop plan complete reason + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete) + + self.thread.StepOver() + # We should be stopped at the breakpoint_4 + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonBreakpoint) + thread1 = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint4) + self.assertEquals(self.thread, thread1, "Didn't stop at breakpoint 4.") + + # Check that stepping does not affect breakpoint's hit count + self.assertEquals(self.breakpoint1.GetHitCount(), 1) + self.assertEquals(self.breakpoint2.GetHitCount(), 0) + self.assertEquals(self.breakpoint3.GetHitCount(), 0) + self.assertEquals(self.breakpoint4.GetHitCount(), 1) + + # Run the process until termination + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateExited) + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp new file mode 100644 index 0000000..8cfd34b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp @@ -0,0 +1,12 @@ + +int func() { return 1; } + +int +main(int argc, char const *argv[]) +{ + int a = 0; // breakpoint_1 + int b = func(); // breakpoint_2 + a = b + func(); // breakpoint_3 + return 0; // breakpoint_4 +} + -- 2.7.4