to open and read source code files, which can be useful if the files
   are located over a slow network connection.
 
+maint set internal-error backtrace on|off
+maint show internal-error backtrace
+maint set internal-warning backtrace on|off
+maint show internal-warning backtrace
+  GDB can now print a backtrace of itself when it encounters either an
+  internal-error, or an internal-warning.  This is on by default for
+  internal-error and off by default for internal-warning.
+
 * Python API
 
   ** New function gdb.add_history(), which takes a gdb.Value object
 
 disabled.
 @end table
 
+@kindex maint set internal-error
+@kindex maint show internal-error
+@kindex maint set internal-warning
+@kindex maint show internal-warning
+@item maint set internal-error backtrace @r{[}on|off@r{]}
+@itemx maint show internal-error backtrace
+@itemx maint set internal-warning backtrace @r{[}on|off@r{]}
+@itemx maint show internal-warning backtrace
+When @value{GDBN} reports an internal problem (error or warning) it is
+possible to have a backtrace of @value{GDBN} printed to stderr.  This
+is @samp{on} by default for @code{internal-error} and @samp{off} by
+default for @code{internal-warning}.
+
 @kindex maint packet
 @item maint packet @var{text}
 If @value{GDBN} is talking to an inferior via the serial protocol,
 
--- /dev/null
+# Copyright 2021 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Test that GDB can print a backtrace when it encounters an internal
+# error or an internal warning, and that this functionality can be
+# switched off.
+
+standard_testfile bt-on-fatal-signal.c
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} {
+    return -1
+}
+
+# Check we can run to main.  If this works this time then we just
+# assume that it will work later on (when we repeatedly restart GDB).
+if ![runto_main] then {
+    untested "run to main"
+    return -1
+}
+
+# Check that the backtrace-on-fatal-signal feature is supported.  If
+# this target doesn't have the backtrace function available then
+# trying to turn this on will give an error, in which case we just
+# skip this test.
+gdb_test_multiple "maint set internal-error backtrace on" \
+    "check backtrace is supported" {
+    -re "support for this feature is not compiled into GDB" {
+       untested "feature not supported"
+       return -1
+    }
+    -re "$gdb_prompt $" {
+       pass $gdb_test_name
+    }
+}
+
+# MODE should be either 'on' or 'off', while PROBLEM_TYPE should be
+# 'internal-error' or 'internal-warning'.  This proc sets the
+# backtrace printing for PROBLEM_TYPE to MODE, then uses 'maint
+# PROBLEM_TYPE foobar' to raise a fake error or warning.
+#
+# We then check that a backtrace either is, or isn't printed, inline
+# with MODE.
+proc run_test {problem_type mode} {
+
+    with_test_prefix "problem=${problem_type}, mode=${mode}" {
+       gdb_test_no_output "maint set ${problem_type} backtrace ${mode}"
+
+       set header_lines 0
+       set bt_lines 0
+
+       gdb_test_multiple "maint ${problem_type} foobar" "scan for backtrace" {
+           -early -re "^\r\n" {
+               exp_continue
+           }
+           -early -re "^maint ${problem_type} foobar\r\n" {
+               exp_continue
+           }
+           -early -re "^\[^\r\n\]+: ${problem_type}: foobar\r\n" {
+               incr header_lines
+               exp_continue
+           }
+           -early -re "^A problem internal to GDB has been detected,\r\n" {
+               incr header_lines
+               exp_continue
+           }
+           -early -re "^further debugging may prove unreliable\\.\r\n" {
+               incr header_lines
+               exp_continue
+           }
+           -early -re "^----- Backtrace -----\r\n" {
+               incr bt_lines
+               exp_continue
+           }
+           -early -re "^\[^-\].+\r\n---------------------\r\n" {
+               incr bt_lines
+               exp_continue
+           }
+           eof {
+               fail ${gdb_test_name}
+               return
+           }
+           -re "$::gdb_prompt $" {
+               pass ${gdb_test_name}
+           }
+       }
+
+       gdb_assert { ${header_lines} == 3 }
+       if { $mode == "on" } {
+           gdb_assert { ${bt_lines} == 2 }
+       } else {
+           gdb_assert { ${bt_lines} == 0 }
+       }
+    }
+}
+
+# For each problem type (error or warning) raise a fake problem using
+# the maintenance commands and check that a backtrace is (or isn't)
+# printed, depending on the user setting.
+foreach problem_type { internal-error internal-warning } {
+    gdb_test_no_output "maint set ${problem_type} corefile no"
+    gdb_test_no_output "maint set ${problem_type} quit no"
+
+    foreach mode { on off } {
+       run_test ${problem_type} ${mode}
+    }
+}
 
        gdb_exit
     }
 }
-
-# Check that when we get an internal error and choose to dump core, we
-# don't print a backtrace to the console.
-with_test_prefix "internal-error" {
-    # Restart GDB.
-    clean_restart $binfile
-
-    set saw_bt_start false
-
-    gdb_test_multiple "maint internal-error foo" "" {
-       -early -re "internal-error: foo\r\n" {
-           exp_continue
-       }
-       -early -re "^A problem internal to GDB has been detected,\r\n" {
-           exp_continue
-       }
-       -early -re "^further debugging may prove unreliable\\.\r\n" {
-           exp_continue
-       }
-       -early -re "^Quit this debugging session\\? \\(y or n\\)" {
-           send_gdb "y\n"
-           exp_continue
-       }
-       -early -re "^Create a core file of GDB\\? \\(y or n\\)" {
-           send_gdb "y\n"
-           exp_continue
-       }
-       -early -re "----- Backtrace -----\r\n" {
-           set saw_bt_start true
-           exp_continue
-       }
-       eof {
-           gdb_assert { [expr ! $saw_bt_start] }
-       }
-    }
-}
 
 #include "gdbarch.h"
 #include "cli-out.h"
 #include "gdbsupport/gdb-safe-ctype.h"
+#include "bt-utils.h"
 
 void (*deprecated_error_begin_hook) (void);
 
 
   /* 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
   /* 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
 
 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
 
 static struct internal_problem internal_warning_problem = {
   "internal-warning", true, internal_problem_ask, true, internal_problem_ask,
+  true, false
 };
 
 void
 
 static struct internal_problem demangler_warning_problem = {
   "demangler-warning", true, internal_problem_ask, false, internal_problem_no,
+  false, false
 };
 
 void
                            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