gdb: Add switch to disable DWARF stack unwinders
authorAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 13 Jul 2018 11:01:16 +0000 (12:01 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 26 Jul 2018 07:53:02 +0000 (08:53 +0100)
Add a maintenance command to disable the DWARF stack unwinders.
Normal users would not need this feature, but it is useful to allow
extended testing of fallback stack unwinding strategies, for example,
prologue scanners.

This is a partial implementation of the idea discussed in pr gdb/8434,
which talks about a generic ability to disable any frame unwinder.

Being able to arbitrarily disable any frame unwinder would be a more
complex patch, and I was unsure how useful such a feature would really
be, however, I can see (and have) a real need to disable DWARF
unwinders.  That's why this patch only targets that specific set of
unwinders.

If in the future we find ourselves adding more switches to disable
different unwinders, then we should probably move to a more generic
solution, and remove this patch.

gdb/ChangeLog:

* dwarf2-frame-tailcall.c (tailcall_frame_sniffer): Exit early if
DWARF unwinders are disabled.
* dwarf2-frame.c: Add dwarf2read.h include.
(dwarf2_frame_sniffer): Exit early if DWARF unwinders are
disabled.
(dwarf2_frame_unwinders_enabled_p): Define.
(show_dwarf_unwinders_enabled_p): New function.
(_initialize_dwarf2_frame): Register switch to control DWARF
unwinder use.
* dwarf2-frame.h (dwarf2_frame_unwinders_enabled_p): Declare.
* dwarf2read.c (set_dwarf_cmdlist): Remove static keyword.
(show_dwarf_cmdlist): Remove static keyword.
* dwarf2read.h (set_dwarf_cmdlist): Declare.
(show_dwarf_cmdlist): Declare.
* NEWS: Document new feature.

gdb/doc/ChangeLog:

* gdb.texinfo (Maintenance Commands): Add description of
maintenance command to control dwarf unwinders.

gdb/testsuite/ChangeLog:

* gdb.base/maint.exp: Add check that dwarf unwinders control flag
is visible.

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/dwarf2-frame-tailcall.c
gdb/dwarf2-frame.c
gdb/dwarf2-frame.h
gdb/dwarf2read.c
gdb/dwarf2read.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/maint.exp

index 605aeef603b4f9d1ee864592b063e6fd90e23881..26c1fd4cb8193baac30e19c2090c75d99d0f2b80 100644 (file)
@@ -1,3 +1,21 @@
+2018-07-26  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * dwarf2-frame-tailcall.c (tailcall_frame_sniffer): Exit early if
+       DWARF unwinders are disabled.
+       * dwarf2-frame.c: Add dwarf2read.h include.
+       (dwarf2_frame_sniffer): Exit early if DWARF unwinders are
+       disabled.
+       (dwarf2_frame_unwinders_enabled_p): Define.
+       (show_dwarf_unwinders_enabled_p): New function.
+       (_initialize_dwarf2_frame): Register switch to control DWARF
+       unwinder use.
+       * dwarf2-frame.h (dwarf2_frame_unwinders_enabled_p): Declare.
+       * dwarf2read.c (set_dwarf_cmdlist): Remove static keyword.
+       (show_dwarf_cmdlist): Remove static keyword.
+       * dwarf2read.h (set_dwarf_cmdlist): Declare.
+       (show_dwarf_cmdlist): Declare.
+       * NEWS: Document new feature.
+
 2018-07-26  Tom de Vries  <tdevries@suse.de>
 
        PR breakpoints/23366
index 76b963e2bc1ed1478ab3ba7d4eed4ad8b1576e64..669ed2d0ebd01f7210ca7cabd89e0b0f013378a3 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -27,6 +27,10 @@ tfaas COMMAND
   output).
   Shortcut for 'thread apply all -s frame apply all -s COMMAND'.
 
+maint set dwarf unwinders (on|off)
+maint show dwarf unwinders
+  Control whether DWARF unwinders can be used.
+
 * Changed commands
 
 thread apply [all | COUNT | -COUNT] [FLAG]... COMMAND
index d2bd3831aef174d401aab0d70a04923f6f42debd..1bcf9dfc167ef0034271f1b95eef0081861dce42 100644 (file)
@@ -1,3 +1,8 @@
+2018-07-26  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.texinfo (Maintenance Commands): Add description of
+       maintenance command to control dwarf unwinders.
+
 2018-07-12  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
        * gdb.texinfo (Debugging Programs with Multiple Threads):
index b36a39b5b4c528d2746dd81c955ef1424b0a3d54..b95c2b4f49afa2b6c179335249c321561679d475 100644 (file)
@@ -35986,6 +35986,30 @@ compilation units will be stored in memory longer, and more total
 memory will be used.  Setting it to zero disables caching, which will
 slow down @value{GDBN} startup, but reduce memory consumption.
 
+@kindex maint set dwarf unwinders
+@kindex maint show dwarf unwinders
+@item maint set dwarf unwinders
+@itemx maint show dwarf unwinders
+Control use of the DWARF frame unwinders.
+
+@cindex DWARF frame unwinders
+Many targets that support DWARF debugging use @value{GDBN}'s DWARF
+frame unwinders to build the backtrace.  Many of these targets will
+also have a second mechanism for building the backtrace for use in
+cases where DWARF information is not available, this second mechanism
+is often an analysis of a function's prologue.
+
+In order to extend testing coverage of the second level stack
+unwinding mechanisms it is helpful to be able to disable the DWARF
+stack unwinders, this can be done with this switch.
+
+In normal use of @value{GDBN} disabling the DWARF unwinders is not
+advisable, there are cases that are better handled through DWARF than
+prologue analysis, and the debug experience is likely to be better
+with the DWARF frame unwinders enabled.
+
+If DWARF frame unwinders are not supported for a particular target
+architecture, then enabling this flag does not cause them to be used.
 @kindex maint set profile
 @kindex maint show profile
 @cindex profiling GDB
index 1d3e1f445bba24407c8d73c1018f55f03210406e..f565a2eecc84e953c7d0b17ab72b5e9d21f84a68 100644 (file)
@@ -318,6 +318,9 @@ tailcall_frame_sniffer (const struct frame_unwind *self,
   int next_levels;
   struct tailcall_cache *cache;
 
+  if (!dwarf2_frame_unwinders_enabled_p)
+    return 0;
+
   /* Inner tail call element does not make sense for a sentinel frame.  */
   next_frame = get_next_frame (this_frame);
   if (next_frame == NULL)
index 91e16cf024e64fcbe0b682968f94133ed95c45bf..58f1ba4f2fc71df74a29f3c60f7e03d876fe9c8a 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "complaints.h"
 #include "dwarf2-frame.h"
+#include "dwarf2read.h"
 #include "ax.h"
 #include "dwarf2loc.h"
 #include "dwarf2-frame-tailcall.h"
@@ -169,6 +170,9 @@ static CORE_ADDR read_encoded_value (struct comp_unit *unit, gdb_byte encoding,
                                     CORE_ADDR func_base);
 \f
 
+/* See dwarf2-frame.h.  */
+int dwarf2_frame_unwinders_enabled_p = 1;
+
 /* Store the length the expression for the CFA in the `cfa_reg' field,
    which is unused in that case.  */
 #define cfa_exp_len cfa_reg
@@ -1326,6 +1330,9 @@ static int
 dwarf2_frame_sniffer (const struct frame_unwind *self,
                      struct frame_info *this_frame, void **this_cache)
 {
+  if (!dwarf2_frame_unwinders_enabled_p)
+    return 0;
+
   /* Grab an address that is guarenteed to reside somewhere within the
      function.  get_frame_pc(), with a no-return next function, can
      end up returning something past the end of this function's body.
@@ -2394,12 +2401,36 @@ dwarf2_build_frame_info (struct objfile *objfile)
   set_objfile_data (objfile, dwarf2_frame_objfile_data, fde_table2);
 }
 
+/* Handle 'maintenance show dwarf unwinders'.  */
+
+static void
+show_dwarf_unwinders_enabled_p (struct ui_file *file, int from_tty,
+                               struct cmd_list_element *c,
+                               const char *value)
+{
+  fprintf_filtered (file,
+                   _("The DWARF stack unwinders are currently %s.\n"),
+                   value);
+}
+
 void
 _initialize_dwarf2_frame (void)
 {
   dwarf2_frame_data = gdbarch_data_register_pre_init (dwarf2_frame_init);
   dwarf2_frame_objfile_data = register_objfile_data ();
 
+  add_setshow_boolean_cmd ("unwinders", class_obscure,
+                          &dwarf2_frame_unwinders_enabled_p , _("\
+Set whether the DWARF stack frame unwinders are used."), _("\
+Show whether the DWARF stack frame unwinders are used."), _("\
+When enabled the DWARF stack frame unwinders can be used for architectures\n\
+that support the DWARF unwinders.  Enabling the DWARF unwinders for an\n\
+architecture that doesn't support them will have no effect."),
+                          NULL,
+                          show_dwarf_unwinders_enabled_p,
+                          &set_dwarf_cmdlist,
+                          &show_dwarf_cmdlist);
+
 #if GDB_SELF_TEST
   selftests::register_test_foreach_arch ("execute_cfa_program",
                                         selftests::execute_cfa_program_test);
index 471281a2c3f3bacc8742ac7077ba3d4a15ec47eb..52316e5e168ba8c1c1987ef2aa3c7e1e8438e385 100644 (file)
@@ -210,6 +210,12 @@ struct dwarf2_frame_state
   bool armcc_cfa_offsets_reversed = false;
 };
 
+/* When this is true the DWARF frame unwinders can be used if they are
+   registered with the gdbarch.  Not all architectures can or do use the
+   DWARF unwinders.  Setting this to true on a target that does not
+   otherwise support the DWARF unwinders has no effect.  */
+extern int dwarf2_frame_unwinders_enabled_p;
+
 /* Set the architecture-specific register state initialization
    function for GDBARCH to INIT_REG.  */
 
index de6b9f13a09d0b72fa9ea9605be4bee9b0d1387f..d16700fb9241ce0e083e01206658314b30361193 100644 (file)
@@ -25345,8 +25345,8 @@ partial_die_eq (const void *item_lhs, const void *item_rhs)
   return part_die_lhs->sect_off == part_die_rhs->sect_off;
 }
 
-static struct cmd_list_element *set_dwarf_cmdlist;
-static struct cmd_list_element *show_dwarf_cmdlist;
+struct cmd_list_element *set_dwarf_cmdlist;
+struct cmd_list_element *show_dwarf_cmdlist;
 
 static void
 set_dwarf_cmd (const char *args, int from_tty)
index 74335d77db09d5a0fb452cb278684151b5873d12..6e37c5d06f5a3a92ac81cc1dec388b61dce4520e 100644 (file)
 #include "filename-seen-cache.h"
 #include "gdb_obstack.h"
 
+/* Hold 'maintenance (set|show) dwarf' commands.  */
+extern struct cmd_list_element *set_dwarf_cmdlist;
+extern struct cmd_list_element *show_dwarf_cmdlist;
+
 typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr;
 DEF_VEC_P (dwarf2_per_cu_ptr);
 
index aa8b06a07239219a4a5a0fbcb01f8486ecbf44bb..cdba393ea849120f3e1172d634f312b981b32b56 100644 (file)
@@ -1,3 +1,8 @@
+2018-07-26  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.base/maint.exp: Add check that dwarf unwinders control flag
+       is visible.
+
 2018-07-26  Tom de Vries  <tdevries@suse.de>
 
        PR breakpoints/23366
index 92086eec86204116b956664b1299c386d51cf206..ee0d08927bbc8cb1dde44d8469c86f1816eba801 100644 (file)
@@ -526,6 +526,10 @@ gdb_test_no_output "maint info line-table xxx.c" \
 
 set timeout $oldtimeout
 
+# Just check that the DWARF unwinders control flag is visible.
+gdb_test "maint show dwarf unwinders" \
+    "The DWARF stack unwinders are currently (on|off)\\."
+
 #============test help on maint commands
 
 test_prefix_command_help {"maint info" "maintenance info"} {