From: Tom Tromey Date: Fri, 24 May 2024 16:51:02 +0000 (-0600) Subject: Don't let exception terminate 'rbreak' X-Git-Tag: gdb-16-branchpoint~84 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=59d25b31eb54130f1115aae20da4ac9ccaa15a53;p=thirdparty%2Fbinutils-gdb.git Don't let exception terminate 'rbreak' '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 --- diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 60100fbe54d..e7fdeca91ff 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -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 diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index be127a9e4e6..696dd9e0028 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -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); }; diff --git a/gdb/symtab.c b/gdb/symtab.c index 30c22dcea38..72a18dce2b7 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -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 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 (" %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 (" %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); } diff --git a/gdb/testsuite/gdb.ada/info_auto_lang.exp b/gdb/testsuite/gdb.ada/info_auto_lang.exp index cb2a5a7a172..e15232d2fb1 100644 --- a/gdb/testsuite/gdb.ada/info_auto_lang.exp +++ b/gdb/testsuite/gdb.ada/info_auto_lang.exp @@ -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 } diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp index 628f0705b7f..b1cf957887b 100644 --- a/gdb/testsuite/gdb.base/default.exp +++ b/gdb/testsuite/gdb.base/default.exp @@ -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\." diff --git a/gdb/testsuite/gdb.base/fullpath-expand.exp b/gdb/testsuite/gdb.base/fullpath-expand.exp index 7ed07b98dc8..c2ae85a60dc 100644 --- a/gdb/testsuite/gdb.base/fullpath-expand.exp +++ b/gdb/testsuite/gdb.base/fullpath-expand.exp @@ -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.*" diff --git a/gdb/testsuite/gdb.base/realname-expand.exp b/gdb/testsuite/gdb.base/realname-expand.exp index 36d3db5259f..e62a4db22bd 100644 --- a/gdb/testsuite/gdb.base/realname-expand.exp +++ b/gdb/testsuite/gdb.base/realname-expand.exp @@ -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