summaryrefslogtreecommitdiff
path: root/gdb/frame.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2019-06-13 00:06:53 +0100
committerPedro Alves <palves@redhat.com>2019-06-13 00:19:14 +0100
commitd4c16835cad70bd8c04ff30d5d6f40ac65e7f7e1 (patch)
tree0d491f710612a66db24b37f8ca5cb25611504c27 /gdb/frame.c
parent2daf894ed0baf72dd3f422b7a71630145568db30 (diff)
downloadbinutils-gdb-d4c16835cad70bd8c04ff30d5d6f40ac65e7f7e1.tar.gz
Make "backtrace" support -OPT options
This adds support for comand options to the "backtrace" command. We'll get: (gdb) bt - -entry-values -hide -past-main -frame-arguments -no-filters -raw-frame-arguments -full -past-entry ~~~~ (gdb) help backtrace Print backtrace of all stack frames, or innermost COUNT frames. Usage: backtrace [OPTION]... [QUALIFIER]... [COUNT | -COUNT] Options: -entry-values no|only|preferred|if-needed|both|compact|default Set printing of function arguments at function entry GDB can sometimes determine the values of function arguments at entry, in addition to their current values. This option tells GDB whether to print the current value, the value at entry (marked as val@entry), or both. Note that one or both of these values may be <optimized out>. -frame-arguments all|scalars|none Set printing of non-scalar frame arguments -raw-frame-arguments [on|off] Set whether to print frame arguments in raw form. If set, frame arguments are printed in raw form, bypassing any pretty-printers for that value. -past-main [on|off] Set whether backtraces should continue past "main". Normally the caller of "main" is not of interest, so GDB will terminate the backtrace at "main". Set this if you need to see the rest of the stack trace. -past-entry [on|off] Set whether backtraces should continue past the entry point of a program. Normally there are no callers beyond the entry point of a program, so GDB will terminate the backtrace there. Set this if you need to see the rest of the stack trace. -full Print values of local variables. -no-filters Prohibit frame filters from executing on a backtrace. -hide Causes Python frame filter elided frames to not be printed. For backward compatibility, the following qualifiers are supported: full - same as -full option. no-filters - same as -no-filters option. hide - same as -hide. With a negative COUNT, print outermost -COUNT frames. ~~~~ Implementation wise, this: - Moves relevant options/settings globals to structures. - Tweaks a number of functions to pass down references to such structures. - Adds option_def structures describing the options/settings. - Makes backtrace_command parse the options, with gdb::option::process_options. - Tweaks "backtrace"'s help to describe the new options. - Adds testcases. Note that backtrace is a PROCESS_OPTIONS_UNKNOWN_IS_OPERAND command, because of the "-COUNT" argument. The COUNT/-COUNT argument is currently parsed as an expression. I considered whether it would be prudent here to require "--", but concluded that the risk of causing a significant breakage here is much lower compared to "print", since printing the expression is not the whole point of the "backtrace" command. Seems OK to me to require typing "backtrace -past-main -- -p" if the user truly wants to refer to the negative of a backtrace count stored in an inferior variable called "p". gdb/ChangeLog: 2019-06-13 Pedro Alves <palves@redhat.com> * frame.c: Include "cli/cli-option.h. (user_set_backtrace_options): New. (backtrace_past_main, backtrace_past_entry, backtrace_limit): Delete. (get_prev_frame): Adjust. (boolean_option_def, uinteger_option_def) (set_backtrace_option_defs): New. (_initialize_frame): Adjust and use gdb::option::add_setshow_cmds_for_options to install "set backtrace past-main" and "set backtrace past-entry". * frame.h: Include "cli/cli-option.h". (struct frame_print_options): Forward declare. (print_frame_arguments_all, print_frame_arguments_scalars) (print_frame_arguments_none): Declare. (print_entry_values): Delete declaration. (struct frame_print_options, user_frame_print_options): New. (struct set_backtrace_options): New. (set_backtrace_option_defs, user_set_backtrace_options): Declare. * mi/mi-cmd-stack.c (mi_cmd_stack_list_frames) (mi_cmd_stack_list_locals, mi_cmd_stack_list_args) (mi_cmd_stack_list_variables): Pass down USER_FRAME_PRINT_OPTIONS. (list_args_or_locals): Add frame_print_options parameter. (mi_cmd_stack_info_frame): Pass down USER_FRAME_PRINT_OPTIONS. * python/py-framefilter.c (enumerate_args): Pass down USER_FRAME_PRINT_OPTIONS. * stack.c: Include "cli/cli-option.h". (print_frame_arguments_all, print_frame_arguments_scalars) (print_frame_arguments_none): Declare. (print_raw_frame_arguments, print_entry_values): Delete. (user_frame_print_options): New. (boolean_option_def, enum_option_def, frame_print_option_defs): New. (struct backtrace_cmd_options): New. (bt_flag_option_def): New. (backtrace_command_option_defs): New. (print_stack_frame): Pass down USER_FRAME_PRINT_OPTIONS. (print_frame_arg, read_frame_arg, print_frame_args) (print_frame_info, print_frame): Add frame_print_options parameter and use it. (info_frame_command_core): Pass down USER_FRAME_PRINT_OPTIONS. (backtrace_command_1): Add frame_print_options and backtrace_cmd_options parameters and use them. (make_backtrace_options_def_group): New. (backtrace_command): Process command options with gdb::option::process_options. (backtrace_command_completer): New. (_initialize_stack): Extend "backtrace"'s help to mention supported options. Install completer for "backtrace". Install some settings commands with add_setshow_cmds_for_options. gdb/testsuite/ChangeLog: 2019-06-13 Pedro Alves <palves@redhat.com> * gdb.base/options.exp (test-backtrace): New. (top level): Call it.
Diffstat (limited to 'gdb/frame.c')
-rw-r--r--gdb/frame.c84
1 files changed, 50 insertions, 34 deletions
diff --git a/gdb/frame.c b/gdb/frame.c
index f4303d13cc1..84e0397db98 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -42,6 +42,7 @@
#include "tracepoint.h"
#include "hashtab.h"
#include "valprint.h"
+#include "cli/cli-option.h"
/* The sentinel frame terminates the innermost end of the frame chain.
If unwound, it returns the information needed to construct an
@@ -52,6 +53,9 @@
static struct frame_info *sentinel_frame;
+/* The values behind the global "set backtrace ..." settings. */
+set_backtrace_options user_set_backtrace_options;
+
static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame);
static const char *frame_stop_reason_symbol_string (enum unwind_stop_reason reason);
@@ -295,9 +299,8 @@ show_frame_debug (struct ui_file *file, int from_tty,
fprintf_filtered (file, _("Frame debugging is %s.\n"), value);
}
-/* Flag to indicate whether backtraces should stop at main et.al. */
+/* Implementation of "show backtrace past-main". */
-static int backtrace_past_main;
static void
show_backtrace_past_main (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@@ -308,7 +311,8 @@ show_backtrace_past_main (struct ui_file *file, int from_tty,
value);
}
-static int backtrace_past_entry;
+/* Implementation of "show backtrace past-entry". */
+
static void
show_backtrace_past_entry (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@@ -318,7 +322,8 @@ show_backtrace_past_entry (struct ui_file *file, int from_tty,
value);
}
-static unsigned int backtrace_limit = UINT_MAX;
+/* Implementation of "show backtrace limit". */
+
static void
show_backtrace_limit (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@@ -2276,7 +2281,7 @@ get_prev_frame (struct frame_info *this_frame)
point inside the main function. */
if (this_frame->level >= 0
&& get_frame_type (this_frame) == NORMAL_FRAME
- && !backtrace_past_main
+ && !user_set_backtrace_options.backtrace_past_main
&& frame_pc_p
&& inside_main_func (this_frame))
/* Don't unwind past main(). Note, this is done _before_ the
@@ -2293,7 +2298,7 @@ get_prev_frame (struct frame_info *this_frame)
being 1-based and the level being 0-based, and the other accounts for
the level of the new frame instead of the level of the current
frame. */
- if (this_frame->level + 2 > backtrace_limit)
+ if (this_frame->level + 2 > user_set_backtrace_options.backtrace_limit)
{
frame_debug_got_null_frame (this_frame, "backtrace limit exceeded");
return NULL;
@@ -2323,7 +2328,7 @@ get_prev_frame (struct frame_info *this_frame)
application. */
if (this_frame->level >= 0
&& get_frame_type (this_frame) == NORMAL_FRAME
- && !backtrace_past_entry
+ && !user_set_backtrace_options.backtrace_past_entry
&& frame_pc_p
&& inside_entry_func (this_frame))
{
@@ -2896,6 +2901,39 @@ show_backtrace_cmd (const char *args, int from_tty)
cmd_show_list (show_backtrace_cmdlist, from_tty, "");
}
+/* Definition of the "set backtrace" settings that are exposed as
+ "backtrace" command options. */
+
+using boolean_option_def
+ = gdb::option::boolean_option_def<set_backtrace_options>;
+using uinteger_option_def
+ = gdb::option::uinteger_option_def<set_backtrace_options>;
+
+const gdb::option::option_def set_backtrace_option_defs[] = {
+
+ boolean_option_def {
+ "past-main",
+ [] (set_backtrace_options *opt) { return &opt->backtrace_past_main; },
+ show_backtrace_past_main, /* show_cmd_cb */
+ N_("Set whether backtraces should continue past \"main\"."),
+ N_("Show whether backtraces should continue past \"main\"."),
+ N_("Normally the caller of \"main\" is not of interest, so GDB will terminate\n\
+the backtrace at \"main\". Set this if you need to see the rest\n\
+of the stack trace."),
+ },
+
+ boolean_option_def {
+ "past-entry",
+ [] (set_backtrace_options *opt) { return &opt->backtrace_past_entry; },
+ show_backtrace_past_entry, /* show_cmd_cb */
+ N_("Set whether backtraces should continue past the entry point of a program."),
+ N_("Show whether backtraces should continue past the entry point of a program."),
+ N_("Normally there are no callers beyond the entry point of a program, so GDB\n\
+will terminate the backtrace there. Set this if you need to see\n\
+the rest of the stack trace."),
+ },
+};
+
void
_initialize_frame (void)
{
@@ -2916,34 +2954,8 @@ Show backtrace variables such as the backtrace limit"),
&show_backtrace_cmdlist, "show backtrace ",
0/*allow-unknown*/, &showlist);
- add_setshow_boolean_cmd ("past-main", class_obscure,
- &backtrace_past_main, _("\
-Set whether backtraces should continue past \"main\"."), _("\
-Show whether backtraces should continue past \"main\"."), _("\
-Normally the caller of \"main\" is not of interest, so GDB will terminate\n\
-the backtrace at \"main\". Set this variable if you need to see the rest\n\
-of the stack trace."),
- NULL,
- show_backtrace_past_main,
- &set_backtrace_cmdlist,
- &show_backtrace_cmdlist);
-
- add_setshow_boolean_cmd ("past-entry", class_obscure,
- &backtrace_past_entry, _("\
-Set whether backtraces should continue past the entry point of a program."),
- _("\
-Show whether backtraces should continue past the entry point of a program."),
- _("\
-Normally there are no callers beyond the entry point of a program, so GDB\n\
-will terminate the backtrace there. Set this variable if you need to see\n\
-the rest of the stack trace."),
- NULL,
- show_backtrace_past_entry,
- &set_backtrace_cmdlist,
- &show_backtrace_cmdlist);
-
add_setshow_uinteger_cmd ("limit", class_obscure,
- &backtrace_limit, _("\
+ &user_set_backtrace_options.backtrace_limit, _("\
Set an upper bound on the number of backtrace levels."), _("\
Show the upper bound on the number of backtrace levels."), _("\
No more than the specified number of frames can be displayed or examined.\n\
@@ -2953,6 +2965,10 @@ Literal \"unlimited\" or zero means no limit."),
&set_backtrace_cmdlist,
&show_backtrace_cmdlist);
+ gdb::option::add_setshow_cmds_for_options
+ (class_stack, &user_set_backtrace_options,
+ set_backtrace_option_defs, &set_backtrace_cmdlist, &show_backtrace_cmdlist);
+
/* Debug this files internals. */
add_setshow_zuinteger_cmd ("frame", class_maintenance, &frame_debug, _("\
Set frame debugging."), _("\