GNULIB_PARENT_DIR = ..
 include $(GNULIB_PARENT_DIR)/gnulib/Makefile.gnulib.inc
 
+# For libbacktrace.
+LIBBACKTRACE_INC=@LIBBACKTRACE_INC@
+LIBBACKTRACE_LIB=@LIBBACKTRACE_LIB@
+
 SUPPORT = ../gdbsupport
 LIBSUPPORT = $(SUPPORT)/libgdbsupport.a
 INCSUPPORT = -I$(srcdir)/.. -I..
        $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
        $(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) $(ZLIBINC) \
        $(BFD_CFLAGS) $(INCLUDE_CFLAGS) $(LIBDECNUMBER_CFLAGS) \
-       $(INTL_CFLAGS) $(INCGNU) $(INCSUPPORT) $(ENABLE_CFLAGS) \
-       $(INTERNAL_CPPFLAGS) $(SRCHIGH_CFLAGS) $(TOP_CFLAGS) $(PTHREAD_CFLAGS) \
-       $(DEBUGINFOD_CFLAGS)
+       $(INTL_CFLAGS) $(INCGNU) $(INCSUPPORT) $(LIBBACKTRACE_INC) \
+       $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS) $(SRCHIGH_CFLAGS) \
+       $(TOP_CFLAGS) $(PTHREAD_CFLAGS) $(DEBUGINFOD_CFLAGS)
 INTERNAL_WARN_CFLAGS = $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS)
 INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS)
 
 # LIBIBERTY appears twice on purpose.
 CLIBS = $(SIM) $(READLINE) $(OPCODES) $(LIBCTF) $(BFD) $(ZLIB) \
         $(LIBSUPPORT) $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \
-       $(XM_CLIBS) $(GDBTKLIBS) \
+       $(XM_CLIBS) $(GDBTKLIBS)  $(LIBBACKTRACE_LIB) \
        @LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
        $(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \
        $(WIN32LIBS) $(LIBGNU) $(LIBGNU_EXTRA_LIBS) $(LIBICONV) \
        $(LIBMPFR) $(LIBGMP) $(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS) \
-       $(DEBUGINFOD_LIBS)
+       $(DEBUGINFOD_LIBS) $(LIBBABELTRACE_LIB)
 CDEPS = $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) $(CTF_DEPS) \
        $(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU) \
        $(LIBSUPPORT)
        break-catch-syscall.c \
        break-catch-throw.c \
        breakpoint.c \
+       bt-utils.c \
        btrace.c \
        build-id.c \
        buildsym-legacy.c \
        breakpoint.h \
        bsd-kvm.h \
        bsd-uthread.h \
+       bt-utils.h \
        build-id.h \
        buildsym-legacy.h \
        buildsym.h \
 
--- /dev/null
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "bt-utils.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "top.h"
+#include "cli/cli-decode.h"
+
+/* See bt-utils.h.  */
+
+void
+gdb_internal_backtrace_set_cmd (const char *args, int from_tty,
+                               cmd_list_element *c)
+{
+  gdb_assert (c->type == set_cmd);
+  gdb_assert (c->var_type == var_boolean);
+  gdb_assert (c->var != nullptr);
+
+#ifndef GDB_PRINT_INTERNAL_BACKTRACE
+  bool *var_ptr = (bool *) c->var;
+
+  if (*var_ptr)
+    {
+      *var_ptr = false;
+      error (_("support for this feature is not compiled into GDB"));
+    }
+#endif
+}
+
+#ifdef GDB_PRINT_INTERNAL_BACKTRACE_USING_LIBBACKTRACE
+
+/* Callback used by libbacktrace if it encounters an error.  */
+
+static void
+libbacktrace_error (void *data, const char *errmsg, int errnum)
+{
+  /* A negative errnum indicates no debug info was available, just
+     skip printing a backtrace in this case.  */
+  if (errnum < 0)
+    return;
+
+  const auto sig_write = [] (const char *msg) -> void
+  {
+    gdb_stderr->write_async_safe (msg, strlen (msg));
+  };
+
+  sig_write ("error creating backtrace: ");
+  sig_write (errmsg);
+  if (errnum > 0)
+    {
+      char buf[20];
+      snprintf (buf, sizeof (buf), ": %d", errnum);
+      buf[sizeof (buf) - 1] = '\0';
+
+      sig_write (buf);
+    }
+  sig_write ("\n");
+}
+
+/* Callback used by libbacktrace to print a single stack frame.  */
+
+static int
+libbacktrace_print (void *data, uintptr_t pc, const char *filename,
+                   int lineno, const char *function)
+{
+  const auto sig_write = [] (const char *msg) -> void
+  {
+    gdb_stderr->write_async_safe (msg, strlen (msg));
+  };
+
+  /* Buffer to print addresses and line numbers into.  An 8-byte address
+     with '0x' prefix and a null terminator requires 20 characters.  This
+     also feels like it should be enough to represent line numbers in most
+     files.  We are also careful to ensure we don't overflow this buffer.  */
+  char buf[20];
+
+  snprintf (buf, sizeof (buf), "0x%lx ", pc);
+  buf[sizeof (buf) - 1] = '\0';
+  sig_write (buf);
+  sig_write (function == nullptr ? "???" : function);
+  if (filename != nullptr)
+    {
+      sig_write ("\n\t");
+      sig_write (filename);
+      sig_write (":");
+      snprintf (buf, sizeof (buf), "%d", lineno);
+      buf[sizeof (buf) - 1] = '\0';
+      sig_write (buf);
+    }
+  sig_write ("\n");
+
+  return function != nullptr && strcmp (function, "main") == 0;
+}
+
+/* Write a backtrace to GDB's stderr in an async safe manor.  This is a
+   backtrace of GDB, not any running inferior, and is to be used when GDB
+   crashes or hits some other error condition.  */
+
+static void
+gdb_internal_backtrace_1 ()
+{
+  static struct backtrace_state *state = nullptr;
+
+  if (state == nullptr)
+    state = backtrace_create_state (nullptr, 0, libbacktrace_error, nullptr);
+
+  backtrace_full (state, 0, libbacktrace_print, libbacktrace_error, nullptr);
+}
+
+#elif defined GDB_PRINT_INTERNAL_BACKTRACE_USING_EXECINFO
+
+/* See the comment on previous version of this function.  */
+
+static void
+gdb_internal_backtrace_1 ()
+{
+  const auto sig_write = [] (const char *msg) -> void
+  {
+    gdb_stderr->write_async_safe (msg, strlen (msg));
+  };
+
+  /* Allow up to 25 frames of backtrace.  */
+  void *buffer[25];
+  int frames = backtrace (buffer, ARRAY_SIZE (buffer));
+
+  backtrace_symbols_fd (buffer, frames, gdb_stderr->fd ());
+  if (frames == ARRAY_SIZE (buffer))
+    sig_write (_("Backtrace might be incomplete.\n"));
+}
+
+#endif
+
+/* See bt-utils.h.  */
+
+void
+gdb_internal_backtrace ()
+{
+  if (current_ui == nullptr)
+    return;
+
+  const auto sig_write = [] (const char *msg) -> void
+  {
+    gdb_stderr->write_async_safe (msg, strlen (msg));
+  };
+
+  sig_write (_("----- Backtrace -----\n"));
+
+  if (gdb_stderr->fd () > -1)
+    gdb_internal_backtrace_1 ();
+  else
+    sig_write (_("Backtrace unavailable\n"));
+
+  sig_write ("---------------------\n");
+}
 
--- /dev/null
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Support for printing a backtrace when GDB hits an error.  This is not
+   for printing backtraces of the inferior, but backtraces of GDB itself.  */
+
+#ifdef HAVE_LIBBACKTRACE
+# include "backtrace.h"
+# include "backtrace-supported.h"
+# if BACKTRACE_SUPPORTED && (! BACKTRACE_USES_MALLOC)
+#  define GDB_PRINT_INTERNAL_BACKTRACE
+#  define GDB_PRINT_INTERNAL_BACKTRACE_USING_LIBBACKTRACE
+# endif
+#endif
+
+#if defined HAVE_EXECINFO_H                    \
+  && defined HAVE_EXECINFO_BACKTRACE           \
+  && !defined PRINT_BACKTRACE_ON_FATAL_SIGNAL
+# include <execinfo.h>
+# define GDB_PRINT_INTERNAL_BACKTRACE
+# define GDB_PRINT_INTERNAL_BACKTRACE_USING_EXECINFO
+#endif
+
+/* Define GDB_PRINT_INTERNAL_BACKTRACE_INIT_ON.  This is a boolean value
+   that can be used as an initial value for a set/show user setting, where
+   the setting controls printing a GDB internal backtrace.
+
+   If backtrace printing is supported then this will have the value true,
+   but if backtrace printing is not supported then this has the value
+   false.  */
+#ifdef GDB_PRINT_INTERNAL_BACKTRACE
+# define GDB_PRINT_INTERNAL_BACKTRACE_INIT_ON true
+#else
+# define GDB_PRINT_INTERNAL_BACKTRACE_INIT_ON false
+#endif
+
+/* Print a backtrace of the current GDB process to the current
+   gdb_stderr.  The output is done in a signal async manor, so it is safe
+   to call from signal handlers.  */
+
+extern void gdb_internal_backtrace ();
+
+/* A generic function that can be used as the set function for any set
+   command that enables printing of an internal backtrace.  Command C must
+   be a boolean set command.
+
+   If GDB doesn't support printing a backtrace, and the user has tried to
+   set the variable associated with command C to true, then the associated
+   variable will be set back to false, and an error thrown.
+
+   If GDB does support printing a backtrace then this function does
+   nothing.  */
+
+extern void gdb_internal_backtrace_set_cmd (const char *args, int from_tty,
+                                           cmd_list_element *c);
 
 /* Define if you have the babeltrace library. */
 #undef HAVE_LIBBABELTRACE
 
+/* Define if libbacktrace is being used. */
+#undef HAVE_LIBBACKTRACE
+
 /* Define to 1 if debuginfod is enabled. */
 #undef HAVE_LIBDEBUGINFOD
 
 
 LTLIBBABELTRACE
 LIBBABELTRACE
 HAVE_LIBBABELTRACE
+LIBBACKTRACE_LIB
+LIBBACKTRACE_INC
 HAVE_NATIVE_GCORE_HOST
 NAT_GENERATED_FILES
 XM_CLIBS
 with_tk
 with_x
 enable_sim
+enable_libbacktrace
 with_babeltrace
 with_libbabeltrace_prefix
 with_libbabeltrace_type
                           gcc is used
   --enable-ubsan          enable undefined behavior sanitizer (auto/yes/no)
   --enable-sim            link gdb with simulator
+  --enable-libbacktrace   use libbacktrace to write a backtrace after a fatal
+                          signal.
   --enable-libctf         Handle .ctf type-info sections [default=yes]
   --enable-unit-tests     Enable the inclusion of unit tests when compiling
                           GDB
 
 fi
 
+# Setup possible use of libbacktrace.
+# Check whether --enable-libbacktrace was given.
+if test "${enable_libbacktrace+set}" = set; then :
+  enableval=$enable_libbacktrace; case "${enableval}" in
+  yes)  enable_libbacktrace=yes ;;
+  no)   enable_libbacktrace=no  ;;
+  *)    as_fn_error $? "bad value ${enableval} for --enable-libbacktrace option" "$LINENO" 5 ;;
+esac
+else
+  enable_libbacktrace=yes
+fi
+
+
+if test "${enable_libbacktrace}" == "yes"; then
+  LIBBACKTRACE_INC="-I$srcdir/../libbacktrace/ -I../libbacktrace/"
+  LIBBACKTRACE_LIB=../libbacktrace/.libs/libbacktrace.a
+
+$as_echo "#define HAVE_LIBBACKTRACE 1" >>confdefs.h
+
+else
+  LIBBACKTRACE_INC=
+  LIBBACKTRACE_LIB=
+fi
+
+
+
+
 # Check for babeltrace and babeltrace-ctf
 
 # Check whether --with-babeltrace was given.
 
                       [Define to the default OS ABI for this configuration.])
 fi
 
+# Setup possible use of libbacktrace.
+AC_ARG_ENABLE([libbacktrace],
+[AS_HELP_STRING([--enable-libbacktrace],
+                [use libbacktrace to write a backtrace after a fatal signal.])],
+[case "${enableval}" in
+  yes)  enable_libbacktrace=yes ;;
+  no)   enable_libbacktrace=no  ;;
+  *)    AC_MSG_ERROR(bad value ${enableval} for --enable-libbacktrace option) ;;
+esac],
+enable_libbacktrace=yes)
+
+if test "${enable_libbacktrace}" == "yes"; then
+  LIBBACKTRACE_INC="-I$srcdir/../libbacktrace/ -I../libbacktrace/"
+  LIBBACKTRACE_LIB=../libbacktrace/.libs/libbacktrace.a
+  AC_DEFINE(HAVE_LIBBACKTRACE, 1, [Define if libbacktrace is being used.])
+else
+  LIBBACKTRACE_INC=
+  LIBBACKTRACE_LIB=
+fi
+
+AC_SUBST(LIBBACKTRACE_INC)
+AC_SUBST(LIBBACKTRACE_LIB)
+
 # Check for babeltrace and babeltrace-ctf
 AC_ARG_WITH(babeltrace,
   AS_HELP_STRING([--with-babeltrace], [include babeltrace support (auto/yes/no)]),
 
 #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
 
 
 /* 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'.  */
 
   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
 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));
       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"));
 
       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
 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);