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 deleted file mode 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py +++ /dev/null @@ -1,72 +0,0 @@ -""" -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 time -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/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 @@ -1,4 +1,4 @@ -//===-- main.c --------------------------------------------------*- C++ -*-===// +//===-- 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. @@ -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/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/Makefile new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/Makefile @@ -0,0 +1,22 @@ +LEVEL := ../../../../make + +LIB_PREFIX := regexbreak_ + +LD_EXTRAS := -L. -l$(LIB_PREFIX)a +C_SOURCES := main.c +USE_LIBDL := 1 + +include $(LEVEL)/Makefile.rules + +a.out: lib_a + +lib_%: + $(MAKE) VPATH=$(SRCDIR) -I $(SRCDIR) -f $(SRCDIR)/$*.mk + +install_name_tool: +ifeq ($(OS),Darwin) + install_name_tool -id @executable_path/libregexbreak_a.dylib libregexbreak_a.dylib +endif + +clean:: + $(MAKE) -f $(SRCDIR)/a.mk clean diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/TestRegexpBreakCommand.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/TestRegexpBreakCommand.py new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/TestRegexpBreakCommand.py @@ -0,0 +1,262 @@ +""" +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 time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class RegexpBreakCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_line(self): + """Test _regexp-break command with a line number.""" + self.build() + 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, self.regex) + + def function_address(self, target, function_name, skip_prologue=False): + # Create a target by the debugger. + self.assertTrue(target, VALID_TARGET) + + 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) + + 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) + + 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( + 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']) + + 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']) + + @skipIfWindows + 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 = "libregexbreak_a" + + module_extension = "dylib" + + if os_description == "Linux": + module_extension = "so" + + method_name = "method" + shlib_name = module_name + "." + module_extension + shlib_method = shlib_name + "`" + method_name + + break_results = lldbutil.run_break_set_command( + self, "b %s`%s" % + (shlib_name, method_name)) + + self.assertTrue(break_results['module'] == shlib_name) + self.assertTrue(break_results['symbol'] == 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/regex_break/a.h b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/a.h new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/a.h @@ -0,0 +1 @@ +int method(void); diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/a.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/a.c new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/a.c @@ -0,0 +1,5 @@ +#include "a.h" + +int method(void) { + return 42; +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/a.mk b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/a.mk new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/a.mk @@ -0,0 +1,9 @@ +LEVEL := ../../../../make + +LIB_PREFIX := regexbreak_ + +DYLIB_NAME := $(LIB_PREFIX)a +DYLIB_C_SOURCES := a.c +DYLIB_ONLY := YES + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/main.c copy from lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c copy to lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/main.c --- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/regex_break/main.c @@ -1,4 +1,4 @@ -//===-- main.c --------------------------------------------------*- C++ -*-===// +//===-- 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. @@ -6,11 +6,14 @@ // //===----------------------------------------------------------------------===// +#include "a.h" + 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++; + method(); 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,28 @@ 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 +562,7 @@ "current file\n" " // containing text 'break " "here'.\n", - 2, + 3, CommandCompletions::eSymbolCompletion | CommandCompletions::eSourceFileCompletion, false));