]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Don't let exception terminate 'rbreak'
authorTom Tromey <tromey@adacore.com>
Fri, 24 May 2024 16:51:02 +0000 (10:51 -0600)
committerTom Tromey <tromey@adacore.com>
Mon, 16 Dec 2024 17:55:44 +0000 (10:55 -0700)
'rbreak' searches symbols and then sets a number of breakpoints.  If
setting one of the breakpoints fails, then 'rbreak' will terminate
before examining the remaining symbols.

However, it seems to me that it is better for 'rbreak' to keep going
in this situation.  That is what this patch implements.

This problem can be seen by writing an Ada program that uses "pragma
import" to reference a symbol that does not have debug info.  In this
case, the program will link but setting a breakpoint on the imported
name will not work.

I don't think it's possible to write a reliable test for this, as it
depends on the order in which symtabs are examined.

New in v2: rbreak now shows how many breakpoints it made and also how
many errors it encountered.

Regression tested on x86-64 Fedora 40.

Approved-By: Andrew Burgess <aburgess@redhat.com>
gdb/breakpoint.c
gdb/breakpoint.h
gdb/symtab.c
gdb/testsuite/gdb.ada/info_auto_lang.exp
gdb/testsuite/gdb.base/default.exp
gdb/testsuite/gdb.base/fullpath-expand.exp
gdb/testsuite/gdb.base/realname-expand.exp

index 60100fbe54d5245ec6adc0facb0271387ac1b449..e7fdeca91ff6a3c4ec48b80f9b0e9063fc6c7176 100644 (file)
@@ -869,6 +869,24 @@ scoped_rbreak_breakpoints::~scoped_rbreak_breakpoints ()
   prev_breakpoint_count = rbreak_start_breakpoint_count;
 }
 
+/* See breakpoint.h.  */
+
+int
+scoped_rbreak_breakpoints::first_breakpoint () const
+{
+  return rbreak_start_breakpoint_count + 1;
+}
+
+/* See breakpoint.h.  */
+
+int
+scoped_rbreak_breakpoints::last_breakpoint () const
+{
+  return (rbreak_start_breakpoint_count == breakpoint_count
+         ? -1
+         : breakpoint_count);
+}
+
 /* Used in run_command to zero the hit count when a new run starts.  */
 
 void
index be127a9e4e678a94ded7a35782fdac6e1fa7cd1d..696dd9e0028e6fdbb11cb432b4a7d19d5881c8c3 100644 (file)
@@ -1970,6 +1970,14 @@ public:
   scoped_rbreak_breakpoints ();
   ~scoped_rbreak_breakpoints ();
 
+  /* Return the number of first breakpoint made while this object is
+     in scope.  */
+  int first_breakpoint () const;
+
+  /* Return the number of the most recent breakpoint made while this
+     object is in scope, or -1 if no breakpoints were made.  */
+  int last_breakpoint () const;
+
   DISABLE_COPY_AND_ASSIGN (scoped_rbreak_breakpoints);
 };
 
index 30c22dcea38cb3e267901796964a1a119648dd3a..72a18dce2b7429fd4d2c5f0e5a1abdbde2774377 100644 (file)
@@ -46,6 +46,7 @@
 #include "fnmatch.h"
 #include "hashtab.h"
 #include "typeprint.h"
+#include "exceptions.h"
 
 #include "gdbsupport/gdb_obstack.h"
 #include "block.h"
@@ -5615,28 +5616,53 @@ rbreak_command (const char *regexp, int from_tty)
   std::vector<symbol_search> symbols = spec.search ();
 
   scoped_rbreak_breakpoints finalize;
+  int err_count = 0;
+
   for (const symbol_search &p : symbols)
     {
-      if (p.msymbol.minsym == NULL)
+      try
        {
-         struct symtab *symtab = p.symbol->symtab ();
-         const char *fullname = symtab_to_fullname (symtab);
+         if (p.msymbol.minsym == NULL)
+           {
+             struct symtab *symtab = p.symbol->symtab ();
+             const char *fullname = symtab_to_fullname (symtab);
 
-         string = string_printf ("%s:'%s'", fullname,
-                                 p.symbol->linkage_name ());
-         break_command (&string[0], from_tty);
-         print_symbol_info (p.symbol, p.block, nullptr);
+             string = string_printf ("%s:'%s'", fullname,
+                                     p.symbol->linkage_name ());
+             break_command (&string[0], from_tty);
+             print_symbol_info (p.symbol, p.block, nullptr);
+           }
+         else
+           {
+             string = string_printf ("'%s'",
+                                     p.msymbol.minsym->linkage_name ());
+
+             break_command (&string[0], from_tty);
+             gdb_printf ("<function, no debug info> %s;\n",
+                         p.msymbol.minsym->print_name ());
+           }
        }
-      else
+      catch (const gdb_exception_error &ex)
        {
-         string = string_printf ("'%s'",
-                                 p.msymbol.minsym->linkage_name ());
-
-         break_command (&string[0], from_tty);
-         gdb_printf ("<function, no debug info> %s;\n",
-                     p.msymbol.minsym->print_name ());
+         exception_print (gdb_stderr, ex);
+         ++err_count;
        }
     }
+
+  int first_bp = finalize.first_breakpoint ();
+  int last_bp = finalize.last_breakpoint ();
+
+  if (last_bp == -1)
+    gdb_printf (_("No breakpoints made.\n"));
+  else if (first_bp == last_bp)
+    gdb_printf (_("Successfully created breakpoint %d.\n"), first_bp);
+  else
+    gdb_printf (_("Successfully created breakpoints %d-%d.\n"),
+               first_bp, last_bp);
+
+  if (err_count > 0)
+    gdb_printf (_("%d breakpoints failed due to errors, see above.\n"),
+               err_count);
 }
 \f
 
index cb2a5a7a172b1dc52e00873e64331e9c42690b7d..e15232d2fb129c00c19275c4cfa108639649d6b4 100644 (file)
@@ -153,7 +153,8 @@ foreach_with_prefix language_choice { "auto" "ada" "c" } {
                     "Breakpoint.*file .*proc_in_ada.adb,.*" \
                     $rbreak_func_in_ada($ada_match) \
                     "Breakpoint.*file .*some_c.c,.*" \
-                    $rbreak_func_in_c($c_match)
+                    $rbreak_func_in_c($c_match) \
+                    "Successfully created breakpoints $decimal-$decimal."
                ]
            delete_breakpoints
        }
index 628f0705b7fc322b904700d73a8845beeec730b6..b1cf957887b21c5c235a2ed0a9b25ab5cfc23031 100644 (file)
@@ -525,7 +525,7 @@ if $use_gdb_stub {
 }
 
 #test rbreak
-gdb_test "rbreak" "rbreak"
+gdb_test "rbreak" "No breakpoints made."
 
 # test restore
 gdb_test "restore" "You can't do that without a process to debug\."
index 7ed07b98dc8657f6153265c4ae1181c3dacd6e90..c2ae85a60dcf651e3cc2509447e4d5158278c28c 100644 (file)
@@ -41,7 +41,12 @@ if { $result != 0 || $realsrcfile2 == "" } {
 
 clean_restart ${testfile}
 
-gdb_test "rbreak $realsrcfile2:func" "^Breakpoint 1 at 0x\[0-9a-f\]+: file [string_to_regexp ${subdir}/${srcfile2}], line \[0-9\]+\\.\r\nvoid func\\(void\\);" "rbreak XXX/fullpath-expand-func.c:func"
+gdb_test "rbreak $realsrcfile2:func" \
+    [multi_line \
+        "Breakpoint 1 at 0x\[0-9a-f\]+: file [string_to_regexp ${subdir}/${srcfile2}], line \[0-9\]+\\." \
+        "void func\\(void\\);" \
+        "Successfully created breakpoint 1."] \
+    "rbreak XXX/fullpath-expand-func.c:func"
 
 # Verify the compilation pathnames are as expected:
 gdb_test "list func" "\tfunc \\(void\\)\r\n.*"
index 36d3db5259f83c04c86606969b9e884777239b24..e62a4db22bd14a98fac078ce2e8b3beda41df6fb 100644 (file)
@@ -41,8 +41,9 @@ gdb_test_no_output "set basenames-may-differ on"
 
 gdb_test "rbreak realname-expand-real.c:func" \
     [multi_line "" \
-               "Breakpoint 1 at $hex: file \[^\r\n\]*/realname-expand-link\\.c, line $decimal\\." \
-               "void func\\(void\\);"]
+        "Breakpoint 1 at $hex: file \[^\r\n\]*/realname-expand-link\\.c, line $decimal\\." \
+        "void func\\(void\\);" \
+        "Successfully created breakpoint 1."]
 
 delete_breakpoints