diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2021-08-12 18:24:59 +0100 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2021-09-28 12:21:22 +0100 |
commit | 91f2597bd24d171c1337a4629f8237aa47c59082 (patch) | |
tree | 930307c3ee14c5578dc90785324c6a653e1109a6 /gdb/utils.c | |
parent | abbbd4a3e0ca51132e7fb31a43f896d29894dae0 (diff) | |
download | binutils-91f2597bd24d171c1337a4629f8237aa47c59082.zip binutils-91f2597bd24d171c1337a4629f8237aa47c59082.tar.gz binutils-91f2597bd24d171c1337a4629f8237aa47c59082.tar.bz2 |
gdb: print backtrace for internal error/warning
This commit builds on previous work to allow GDB to print a backtrace
of itself when GDB encounters an internal-error or internal-warning.
This fixes PR gdb/26377.
There's not many places where we call internal_warning, and I guess in
most cases the user would probably continue their debug session. And
so, in order to avoid cluttering up the output, by default, printing
of a backtrace is off for internal-warnings.
In contrast, printing of a backtrace is on by default for
internal-errors, as I figure that in most cases hitting an
internal-error is going to be the end of the debug session.
Whether a backtrace is printed or not can be controlled with the new
settings:
maintenance set internal-error backtrace on|off
maintenance show internal-error backtrace
maintenance set internal-warning backtrace on|off
maintenance show internal-warning backtrace
Here is an example of what an internal-error now looks like with the
backtrace included:
(gdb) maintenance internal-error blah
../../src.dev-3/gdb/maint.c:82: internal-error: blah
A problem internal to GDB has been detected,
further debugging may prove unreliable.
----- Backtrace -----
0x5c61ca gdb_internal_backtrace_1
../../src.dev-3/gdb/bt-utils.c:123
0x5c626d _Z22gdb_internal_backtracev
../../src.dev-3/gdb/bt-utils.c:165
0xe33237 internal_vproblem
../../src.dev-3/gdb/utils.c:393
0xe33539 _Z15internal_verrorPKciS0_P13__va_list_tag
../../src.dev-3/gdb/utils.c:470
0x1549652 _Z14internal_errorPKciS0_z
../../src.dev-3/gdbsupport/errors.cc:55
0x9c7982 maintenance_internal_error
../../src.dev-3/gdb/maint.c:82
0x636f57 do_simple_func
../../src.dev-3/gdb/cli/cli-decode.c:97
.... snip, lots more backtrace lines ....
---------------------
../../src.dev-3/gdb/maint.c:82: internal-error: blah
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) y
This is a bug, please report it. For instructions, see:
<https://www.gnu.org/software/gdb/bugs/>.
../../src.dev-3/gdb/maint.c:82: internal-error: blah
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n) n
My hope is that this backtrace might make it slightly easier to
diagnose GDB issues if all that is provided is the console output, I
find that we frequently get reports of an assert being hit that is
located in pretty generic code (frame.c, value.c, etc) and it is not
always obvious how we might have arrived at the assert.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=26377
Diffstat (limited to 'gdb/utils.c')
-rw-r--r-- | gdb/utils.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/gdb/utils.c b/gdb/utils.c index 0a7c270..f6f90d7 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -75,6 +75,7 @@ #include "gdbarch.h" #include "cli-out.h" #include "gdbsupport/gdb-safe-ctype.h" +#include "bt-utils.h" void (*deprecated_error_begin_hook) (void); @@ -304,6 +305,13 @@ struct internal_problem /* Like SHOULD_QUIT, but whether GDB should dump core. */ const char *should_dump_core; + + /* Like USER_SETTABLE_SHOULD_QUIT but for SHOULD_PRINT_BACKTRACE. */ + bool user_settable_should_print_backtrace; + + /* When this is true GDB will print a backtrace when a problem of this + type is encountered. */ + bool should_print_backtrace; }; /* Report a problem, internal to GDB, to the user. Once the problem @@ -377,9 +385,13 @@ internal_vproblem (struct internal_problem *problem, /* Emit the message unless query will emit it below. */ if (problem->should_quit != internal_problem_ask || !confirm - || !filtered_printing_initialized ()) + || !filtered_printing_initialized () + || problem->should_print_backtrace) fprintf_unfiltered (gdb_stderr, "%s\n", reason.c_str ()); + if (problem->should_print_backtrace) + gdb_internal_backtrace (); + if (problem->should_quit == internal_problem_ask) { /* Default (yes/batch case) is to quit GDB. When in batch mode @@ -449,6 +461,7 @@ internal_vproblem (struct internal_problem *problem, static struct internal_problem internal_error_problem = { "internal-error", true, internal_problem_ask, true, internal_problem_ask, + true, GDB_PRINT_INTERNAL_BACKTRACE_INIT_ON }; void @@ -460,6 +473,7 @@ internal_verror (const char *file, int line, const char *fmt, va_list ap) static struct internal_problem internal_warning_problem = { "internal-warning", true, internal_problem_ask, true, internal_problem_ask, + true, false }; void @@ -470,6 +484,7 @@ internal_vwarning (const char *file, int line, const char *fmt, va_list ap) static struct internal_problem demangler_warning_problem = { "demangler-warning", true, internal_problem_ask, false, internal_problem_no, + false, false }; void @@ -571,6 +586,25 @@ add_internal_problem_command (struct internal_problem *problem) set_cmd_list, show_cmd_list); } + + if (problem->user_settable_should_print_backtrace) + { + std::string set_bt_doc + = string_printf (_("Set whether GDB should print a backtrace of " + "GDB when %s is detected."), problem->name); + std::string show_bt_doc + = string_printf (_("Show whether GDB will print a backtrace of " + "GDB when %s is detected."), problem->name); + add_setshow_boolean_cmd ("backtrace", class_maintenance, + &problem->should_print_backtrace, + set_bt_doc.c_str (), + show_bt_doc.c_str (), + NULL, /* help_doc */ + gdb_internal_backtrace_set_cmd, + NULL, /* showfunc */ + set_cmd_list, + show_cmd_list); + } } /* Return a newly allocated string, containing the PREFIX followed |