diff options
4 files changed, 122 insertions, 3 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/Makefile new file mode 100644 index 00000000000..b09a579159d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/TestStepUntil.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/TestStepUntil.py new file mode 100644 index 00000000000..ec34c9985d3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/TestStepUntil.py @@ -0,0 +1,92 @@ +"""Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" + +from __future__ import print_function + + +import os +import time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCStepping(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def getCategories(self): + return ['basic_process'] + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers that we will step to in main: + self.main_source = "main.c" + self.less_than_two = line_number('main.c', 'Less than 2') + self.greater_than_two = line_number('main.c', 'Greater than or equal to 2.') + self.back_out_in_main = line_number('main.c', 'Back out in main') + + def do_until (self, args, until_lines, expected_linenum): + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + main_source_spec = lldb.SBFileSpec(self.main_source) + break_before = target.BreakpointCreateBySourceRegex( + 'At the start', + main_source_spec) + self.assertTrue(break_before, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + args, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + threads = lldbutil.get_threads_stopped_at_breakpoint( + process, break_before) + + if len(threads) != 1: + self.fail("Failed to stop at first breakpoint in main.") + + thread = threads[0] + return thread + + thread = self.common_setup(None) + + cmd_interp = self.dbg.GetCommandInterpreter() + ret_obj = lldb.SBCommandReturnObject() + + cmd_line = "thread until" + for line_num in until_lines: + cmd_line += " %d"%(line_num) + + cmd_interp.HandleCommand(cmd_line, ret_obj) + self.assertTrue(ret_obj.Succeeded(), "'%s' failed: %s."%(cmd_line, ret_obj.GetError())) + + frame = thread.frames[0] + line = frame.GetLineEntry().GetLine() + self.assertEqual(line, expected_linenum, 'Did not get the expected stop line number') + + def test_hitting_one (self): + """Test thread step until - targeting one line and hitting it.""" + self.do_until(None, [self.less_than_two], self.less_than_two) + + def test_targetting_two_hitting_first (self): + """Test thread step until - targeting two lines and hitting one.""" + self.do_until(["foo", "bar", "baz"], [self.less_than_two, self.greater_than_two], self.greater_than_two) + + def test_targetting_two_hitting_second (self): + """Test thread step until - targeting two lines and hitting the other one.""" + self.do_until(None, [self.less_than_two, self.greater_than_two], self.less_than_two) + + def test_missing_one (self): + """Test thread step until - targeting one line and missing it.""" + self.do_until(["foo", "bar", "baz"], [self.less_than_two], self.back_out_in_main) + + + diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/main.c new file mode 100644 index 00000000000..e0b4d8ab951 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_until/main.c @@ -0,0 +1,20 @@ +#include <stdio.h> + +void call_me(int argc) +{ + printf ("At the start, argc: %d.\n", argc); + + if (argc < 2) + printf("Less than 2.\n"); + else + printf("Greater than or equal to 2.\n"); +} + +int +main(int argc, char **argv) +{ + call_me(argc); + printf("Back out in main.\n"); + + return 0; +} diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 97718946395..28c06f38339 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -977,7 +977,9 @@ public: interpreter, "thread until", "Continue until a line number or address is reached by the " "current or specified thread. Stops when returning from " - "the current function as a safety measure.", + "the current function as a safety measure. " + "The target line number(s) are given as arguments, and if more than one" + " is provided, stepping will stop when the first one is hit.", nullptr, eCommandRequiresThread | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), @@ -1025,11 +1027,11 @@ protected: size_t num_args = command.GetArgumentCount(); for (size_t i = 0; i < num_args; i++) { uint32_t line_number; - line_number = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), + line_number = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), UINT32_MAX); if (line_number == UINT32_MAX) { result.AppendErrorWithFormat("invalid line number: '%s'.\n", - command.GetArgumentAtIndex(0)); + command.GetArgumentAtIndex(i)); result.SetStatus(eReturnStatusFailed); return false; } else |