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
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to