aboutsummaryrefslogtreecommitdiff
path: root/gdb/event-top.c
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2021-08-11 13:24:33 +0100
committerAndrew Burgess <andrew.burgess@embecosm.com>2021-09-28 12:21:22 +0100
commitabbbd4a3e0ca51132e7fb31a43f896d29894dae0 (patch)
tree95373a55ae00731fc4a37d1f361bbd81314a7f5d /gdb/event-top.c
parent890026e31759ae00c6bbb7eb41b5fe89580a256f (diff)
downloadgdb-abbbd4a3e0ca51132e7fb31a43f896d29894dae0.zip
gdb-abbbd4a3e0ca51132e7fb31a43f896d29894dae0.tar.gz
gdb-abbbd4a3e0ca51132e7fb31a43f896d29894dae0.tar.bz2
gdb: use libbacktrace to create a better backtrace for fatal signals
GDB recently gained the ability to print a backtrace when a fatal signal is encountered. This backtrace is produced using the backtrace and backtrace_symbols_fd API available in glibc. However, in order for this API to actually map addresses to symbol names it is required that the application (GDB) be compiled with -rdynamic, which GDB is not by default. As a result, the backtrace produced often looks like this: Fatal signal: Bus error ----- Backtrace ----- ./gdb/gdb[0x80ec00] ./gdb/gdb[0x80ed56] /lib64/libc.so.6(+0x3c6b0)[0x7fc2ce1936b0] /lib64/libc.so.6(__poll+0x4f)[0x7fc2ce24da5f] ./gdb/gdb[0x15495ba] ./gdb/gdb[0x15489b8] ./gdb/gdb[0x9b794d] ./gdb/gdb[0x9b7a6d] ./gdb/gdb[0x9b943b] ./gdb/gdb[0x9b94a1] ./gdb/gdb[0x4175dd] /lib64/libc.so.6(__libc_start_main+0xf3)[0x7fc2ce17e1a3] ./gdb/gdb[0x4174de] --------------------- This is OK if you have access to the exact same build of GDB, you can manually map the addresses back to symbols, however, it is next to useless if all you have is a backtrace copied into a bug report. GCC uses libbacktrace for printing a backtrace when it encounters an error. In recent commits I added this library into the binutils-gdb repository, and in this commit I allow this library to be used by GDB. Now (when GDB is compiled with debug information) the backtrace looks like this: ----- Backtrace ----- 0x80ee08 gdb_internal_backtrace ../../src/gdb/event-top.c:989 0x80ef0b handle_fatal_signal ../../src/gdb/event-top.c:1036 0x7f24539dd6af ??? 0x7f2453a97a5f ??? 0x154976f gdb_wait_for_event ../../src/gdbsupport/event-loop.cc:613 0x1548b6d _Z16gdb_do_one_eventv ../../src/gdbsupport/event-loop.cc:237 0x9b7b02 start_event_loop ../../src/gdb/main.c:421 0x9b7c22 captured_command_loop ../../src/gdb/main.c:481 0x9b95f0 captured_main ../../src/gdb/main.c:1353 0x9b9656 _Z8gdb_mainP18captured_main_args ../../src/gdb/main.c:1368 0x4175ec main ../../src/gdb/gdb.c:32 --------------------- Which seems much more useful. Use of libbacktrace is optional. If GDB is configured with --disable-libbacktrace then the libbacktrace directory will not be built, and GDB will not try to use this library. In this case GDB would try to use the old backtrace and backtrace_symbols_fd API. All of the functions related to writing the backtrace of GDB itself have been moved into the new files gdb/by-utils.{c,h}.
Diffstat (limited to 'gdb/event-top.c')
-rw-r--r--gdb/event-top.c47
1 files changed, 7 insertions, 40 deletions
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 9233a36..64c624c 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -41,15 +41,12 @@
#include "gdbsupport/gdb_select.h"
#include "gdbsupport/gdb-sigmask.h"
#include "async-event.h"
+#include "bt-utils.h"
/* readline include files. */
#include "readline/readline.h"
#include "readline/history.h"
-#ifdef HAVE_EXECINFO_H
-# include <execinfo.h>
-#endif /* HAVE_EXECINFO_H */
-
/* readline defines this. */
#undef savestring
@@ -102,12 +99,7 @@ int call_stdin_event_handler_again_p;
/* When true GDB will produce a minimal backtrace when a fatal signal is
reached (within GDB code). */
-static bool bt_on_fatal_signal
-#ifdef HAVE_EXECINFO_BACKTRACE
- = true;
-#else
- = false;
-#endif /* HAVE_EXECINFO_BACKTRACE */
+static bool bt_on_fatal_signal = GDB_PRINT_INTERNAL_BACKTRACE_INIT_ON;
/* Implement 'maintenance show backtrace-on-fatal-signal'. */
@@ -118,20 +110,6 @@ show_bt_on_fatal_signal (struct ui_file *file, int from_tty,
fprintf_filtered (file, _("Backtrace on a fatal signal is %s.\n"), value);
}
-/* Implement 'maintenance set backtrace-on-fatal-signal'. */
-
-static void
-set_bt_on_fatal_signal (const char *args, int from_tty, cmd_list_element *c)
-{
-#ifndef HAVE_EXECINFO_BACKTRACE
- if (bt_on_fatal_signal)
- {
- bt_on_fatal_signal = false;
- error (_("support for this feature is not compiled into GDB"));
- }
-#endif
-}
-
/* Signal handling variables. */
/* Each of these is a pointer to a function that the event loop will
invoke if the corresponding signal has received. The real signal
@@ -904,7 +882,7 @@ unblock_signal (int sig)
static void ATTRIBUTE_NORETURN
handle_fatal_signal (int sig)
{
-#ifdef HAVE_EXECINFO_BACKTRACE
+#ifdef GDB_PRINT_INTERNAL_BACKTRACE
const auto sig_write = [] (const char *msg) -> void
{
gdb_stderr->write_async_safe (msg, strlen (msg));
@@ -917,19 +895,8 @@ handle_fatal_signal (int sig)
sig_write (strsignal (sig));
sig_write ("\n");
- /* Allow up to 25 frames of backtrace. */
- void *buffer[25];
- int frames = backtrace (buffer, ARRAY_SIZE (buffer));
- sig_write (_("----- Backtrace -----\n"));
- if (gdb_stderr->fd () > -1)
- {
- backtrace_symbols_fd (buffer, frames, gdb_stderr->fd ());
- if (frames == ARRAY_SIZE (buffer))
- sig_write (_("Backtrace might be incomplete.\n"));
- }
- else
- sig_write (_("Backtrace unavailable\n"));
- sig_write ("---------------------\n");
+ gdb_internal_backtrace ();
+
sig_write (_("A fatal error internal to GDB has been detected, "
"further\ndebugging is not possible. GDB will now "
"terminate.\n\n"));
@@ -944,7 +911,7 @@ handle_fatal_signal (int sig)
gdb_stderr->flush ();
}
-#endif /* HAVE_EXECINF_BACKTRACE */
+#endif
/* If possible arrange for SIG to have its default behaviour (which
should be to terminate the current process), unblock SIG, and reraise
@@ -1449,7 +1416,7 @@ Use \"on\" to enable, \"off\" to disable.\n\
If enabled, GDB will produce a minimal backtrace if it encounters a fatal\n\
signal from within GDB itself. This is a mechanism to help diagnose\n\
crashes within GDB, not a mechanism for debugging inferiors."),
- set_bt_on_fatal_signal,
+ gdb_internal_backtrace_set_cmd,
show_bt_on_fatal_signal,
&maintenance_set_cmdlist,
&maintenance_show_cmdlist);