mib created this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
This patch fixes the regular expressions used by the CommandInterpreter
to match GDB style breakpoint command to the LLDB style.
The previous version passed the breakpoint options to _regex-break as a name
identifier, instead of recognising the options.
In addition to that, several test case have been added to check if all the
supported _regex-break command match their `b` alias.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D64853
Files:
lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py
lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c
lldb/source/Interpreter/CommandInterpreter.cpp
Index: lldb/source/Interpreter/CommandInterpreter.cpp
===================================================================
--- lldb/source/Interpreter/CommandInterpreter.cpp
+++ 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<CommandObjectRegexCommand> 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 <filename>:<linenum>\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));
Index: lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c
+++ lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/main.c
@@ -6,11 +6,14 @@
//
//===----------------------------------------------------------------------===//
+#include <stdlib.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++;
+ malloc(sizeof(int));
return 0; // Set break point at this line.
}
Index: lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestRegexpBreakCommand.py
+++ 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'])
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits