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 --- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py @@ -16,21 +16,68 @@ mydir = TestBase.compute_mydir(__file__) - def test(self): - """Test _regexp-break command.""" + def test_line(self): + """Test _regexp-break command with a line number.""" self.build() - self.regexp_break_command() + self.regexp_break_command_line() + + def test_file_line(self): + """Test _regexp-break command with a file and a line number.""" + self.build() + self.regexp_break_command_file_line() + + def test_address(self): + """Test _regexp-break command with an address.""" + self.build() + self.regexp_break_command_address() + + def test_name(self): + """Test _regexp-break command with a name.""" + self.build() + self.regexp_break_command_name() + + def test_ampersand_name(self): + """Test _regexp-break command with an ampersand name.""" + self.build() + self.regexp_break_command_ampersand_name() + + def test_shlib_method(self): + """Test _regexp-break command with a shared library method.""" + self.build() + self.regexp_break_command_shlib_method() + + def test_regex(self): + """Test _regexp-break command with a regular expression.""" + self.build() + self.regexp_break_command_regex() def setUp(self): # Call super's setUp(). TestBase.setUp(self) + self.runCmd("settings set use-color false") # Find the line number to break inside main(). self.source = 'main.c' + self.regex = '// Set break point at this line.' self.line = line_number( - self.source, '// Set break point at this line.') + self.source, self.regex) + + def function_address(self, target, function_name, skip_prologue=False): + # Create a target by the debugger. + self.assertTrue(target, VALID_TARGET) - def regexp_break_command(self): - """Test the super consie "b" command, which is analias for _regexp-break.""" + sc_list = target.FindFunctions(str(function_name), lldb.eFunctionNameTypeAuto) + self.assertTrue(sc_list.GetSize() == 1) + + symbol = sc_list[0].GetSymbol() + start_addr = symbol.GetStartAddress() + prologue_size = symbol.GetPrologueByteSize() + addr = int(start_addr) + if skip_prologue: + addr = addr + prologue_size + return addr + + def regexp_break_command_line(self): + """Test the super consie "b" command with a line number, which is analias for _regexp-break.""" exe = self.getBuildArtifact("a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) @@ -44,6 +91,18 @@ 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']) + + def regexp_break_command_file_line(self): + """Test the super consie "b" command with a file and line number, 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 %s:%d" % (self.source, self.line)) lldbutil.check_breakpoint_result( @@ -70,3 +129,129 @@ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', 'stop reason = breakpoint']) + + def regexp_break_command_address(self): + """Test the super consie "b" command with an address, which is analias for _regexp-break.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + target = self.dbg.CreateTarget(exe) + + addr = self.function_address(target, "main") + self.runCmd("process launch -s", RUN_SUCCEEDED) + + break_results = lldbutil.run_break_set_command( + self, "b 0x%x" % + addr) + lldbutil.check_breakpoint_result( + self, + break_results, + file_name=self.source, + line_number=-1, + num_locations=1) + + self.runCmd("continue", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', + 'stop reason = breakpoint']) + + def regexp_break_command_name(self): + """Test the super consie "b" command with a function name, which is analias for _regexp-break.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + target = self.dbg.CreateTarget(exe) + + function_name = "main" + addr = self.function_address(target, function_name, skip_prologue=True) + self.line = line_number(self.source, "int main") + + break_results = lldbutil.run_break_set_command( + self, "b %s" % + function_name) + + break_set_addr = break_results['address'] + self.assertTrue(int(break_set_addr,16) == addr) + + 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']) + + def regexp_break_command_ampersand_name(self): + """Test the super consie "b" command with a function reference, which is analias for _regexp-break.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + target = self.dbg.CreateTarget(exe) + + function_name = "main" + break_expected_addr = self.function_address(target, function_name) + + break_results = lldbutil.run_break_set_command( + self, "b &%s" % + function_name) + + break_set_addr = break_results['address'] + self.assertTrue(int(break_set_addr, 16) == break_expected_addr) + + 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']) + + def regexp_break_command_shlib_method(self): + """Test the super consie "b" command with a shared library method, which is analias for _regexp-break.""" + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + target = self.dbg.CreateTarget(exe) + os_description = target.GetPlatform().GetOSDescription().split()[0] + + module_name = "libsystem_malloc.dylib" + if not os_description == "Darwin": + module_name = "libc.so" + + method_name = "malloc" + + break_results = lldbutil.run_break_set_command( + self, "b %s`%s" % + (module_name, method_name)) + + self.assertTrue(break_results['module'] == module_name) + self.assertTrue(break_results['symbol'] == method_name) + + shlib_method = module_name + "`" + method_name + + 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']) + + self.expect("frame info", substrs=[shlib_method]) + + def regexp_break_command_regex(self): + """Test the super consie "b" command with a regular expression, 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 /%s/" % + self.regex) + 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/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c --- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c @@ -6,11 +6,14 @@ // //===----------------------------------------------------------------------===// +#include + 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++; + malloc(sizeof(int)); return 0; // Set break point at this line. } diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -516,27 +516,27 @@ CommandObjectSP(new CommandObjectLanguage(*this)); const char *break_regexes[][2] = { - {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", - "breakpoint set --file '%1' --line %2"}, - {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"}, - {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, - {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, - {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", - "breakpoint set --name '%1'"}, + {"^([^[:space:]]+)[[:space:]]*:[[:space:]]*([[:digit:]]+)(?:$|\\s+)(-.*)*$", + "breakpoint set --file '%1' --line %2 %3"}, + {"/([^/]+)/(?:$|\\s+)(-.*)*$", "breakpoint set --source-pattern-regexp '%1' %2"}, + {"^([[:digit:]]+)(?:$|\\s+)(-.*)*$", "breakpoint set --line %1 %2"}, + {"^(0x[[:xdigit:]]+)(?:$|\\s+)(-.*)*$", "breakpoint set --address %1 %2"}, + {"^[\"']?([-+]?\\[[^[:space:]\"']+\\s+[^[:space:]\"']+\\])[\"']?(?:$|\\s+)(-.*)*$", + "breakpoint set --name '%1' %2"}, // Objective-C Identifier {"^(-.*)$", "breakpoint set %1"}, - {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", - "breakpoint set --name '%2' --shlib '%1'"}, - {"^\\&(.*[^[:space:]])[[:space:]]*$", + {"^([^[:space:]]+)`([^[:space:]]+)(?:$|\\s+)(-.*)*$", + "breakpoint set --name '%2' --shlib '%1' %3"}, + {"^\\&([^[:space:]]+)(?:$|\\s+)(-.*)*$", "breakpoint set --name '%1' --skip-prologue=0"}, - {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", - "breakpoint set --name '%1'"}}; + {"^[\"']?([^[:space:]\"']+)[\"']?(?:$|\\s+(-.*))*$", + "breakpoint set --name '%1' %2"}}; size_t num_regexes = llvm::array_lengthof(break_regexes); std::unique_ptr break_regex_cmd_up( new CommandObjectRegexCommand( *this, "_regexp-break", - "Set a breakpoint using one of several shorthand formats.", + "Set a breakpoint using one of several shorthand formats. Accepts breakpoint options.", "\n" "_regexp-break :\n" " main.c:12 // Break at line 12 of " @@ -561,7 +561,7 @@ "current file\n" " // containing text 'break " "here'.\n", - 2, + 3, CommandCompletions::eSymbolCompletion | CommandCompletions::eSourceFileCompletion, false));